rltk 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/04/16
4
+ # Description: This file defines the MemoryBuffer class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK::CG # :nodoc:
18
+
19
+ # This class is used by the {Module} class to dump and load LLVM bitcode.
20
+ class MemoryBuffer
21
+ include BindingClass
22
+
23
+ # Create a new memory buffer.
24
+ #
25
+ # @param [FFI::Pointer, String, nil] overloaded This parameter may be either a pointer to an existing memory
26
+ # buffer, the name of a file containing LLVM bitcode, or nil. If it is nil the memory buffer will read
27
+ # from standard in.
28
+ def initialize(overloaded = nil)
29
+ @ptr =
30
+ case overloaded
31
+ when FFI::Pointer
32
+ overloaded
33
+ else
34
+ buf_ptr = FFI::MemoryPointer.new(:pointer)
35
+ msg_ptr = FFI::MemoryPointer.new(:pointer)
36
+
37
+ status =
38
+ case overloaded
39
+ when String
40
+ Bindings.create_memory_buffer_with_contents_of_file(overloaded, buf_ptr, msg_ptr)
41
+ else
42
+ Bindings.create_memory_buffer_with_stdin(buf_ptr, msg_ptr)
43
+ end
44
+
45
+ raise msg_ptr.get_pointer(0).get_string(0) if status != 0
46
+
47
+ buf_ptr.get_pointer(0)
48
+ end
49
+ end
50
+
51
+ # Frees the resources used by LLVM for this memory buffer.
52
+ #
53
+ # @return [void]
54
+ def dispose
55
+ if @ptr
56
+ Bindings.dispose_memory_buffer(@ptr)
57
+
58
+ @ptr = nil
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,328 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/20
4
+ # Description: This file defines the Module class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+ require 'rltk/cg/context'
13
+
14
+ #######################
15
+ # Classes and Modules #
16
+ #######################
17
+
18
+ module RLTK::CG # :nodoc:
19
+
20
+ # This class represents a collection of functions, constants, and global
21
+ # variables.
22
+ class Module
23
+ include BindingClass
24
+
25
+ # Load a module from LLVM bitcode.
26
+ #
27
+ # @see MemoryBuffer#initialize
28
+ #
29
+ # @param [MemoryBuffer, FFI::Pointer, String, nil] overloaded Where to read the bytecode from.
30
+ #
31
+ # @return [Module]
32
+ def self.read_bitcode(overloaded)
33
+ buffer = if overloaded.is_a?(MemoryBuffer) then overloaded else MemoryBuffer.new(overloaded) end
34
+
35
+ mod_ptr = FFI::MemoryPointer.new(:pointer)
36
+ msg_ptr = FFI::MemoryPointer.new(:pointer)
37
+
38
+ status = Bindings.parse_bitcode(buffer, mod_ptr, msg_ptr)
39
+
40
+ if status != 0
41
+ raise msg_ptr.get_pointer(0).get_string(0)
42
+ else
43
+ Module.new(mod_ptr.get_pointer(0))
44
+ end
45
+ end
46
+
47
+ # Create a new LLVM module.
48
+ #
49
+ # @param [FFI::Pointer, String] overloaded Pointer to existing module or name of new module.
50
+ # @param [Context, nil] context Optional context in which to create the module.
51
+ # @param [Proc] block Block to be executed inside the context of the module.
52
+ def initialize(overloaded, context = nil, &block)
53
+ @ptr =
54
+ case overloaded
55
+ when FFI::Pointer
56
+ overloaded
57
+
58
+ when String
59
+ if context
60
+ Bindings.module_create_with_name_in_context(overloaded, check_type(context, Context, 'context'))
61
+ else
62
+ Bindings.module_create_with_name(overloaded)
63
+ end
64
+ end
65
+
66
+ self.instance_exec(&block) if block
67
+ end
68
+
69
+ # @return [Context] Context in which this module exists.
70
+ def context
71
+ Context.new(Bindings.get_module_context(@ptr))
72
+ end
73
+
74
+ # Frees the resources used by LLVM for this module.
75
+ #
76
+ # @return [void]
77
+ def dispose
78
+ if @ptr
79
+ Bindings.dispose_module(@ptr)
80
+
81
+ @ptr = nil
82
+ end
83
+ end
84
+
85
+ # Print the IR of this module to standard out.
86
+ #
87
+ # @return [void]
88
+ def dump
89
+ Bindings.dump_module(@ptr)
90
+ end
91
+
92
+ # @return [FunctionCollection] Proxy object for inspecting this module's functions.
93
+ def functions
94
+ @functions ||= FunctionCollection.new(self)
95
+ end
96
+ alias :funs :functions
97
+
98
+ # @return [GlobalCollection] Proxy object for inspecting this module's global values and variables.
99
+ def globals
100
+ @globals ||= GlobalCollection.new(self)
101
+ end
102
+
103
+ # Write the module as LLVM bitcode to a file.
104
+ #
105
+ # @param [#path, #fileno, Integer, String] overloaded Where to write the bitcode.
106
+ #
107
+ # @return [Boolean] If the write was successful.
108
+ def write_bitcode(overloaded)
109
+ 0 ==
110
+ if overloaded.respond_to?(:path)
111
+ Bindings.write_bitcode_to_file(@ptr, overloaded.path)
112
+
113
+ elsif overloaded.respond_to?(:fileno)
114
+ Bindings.write_bitcode_to_fd(@ptr, overloaded.fileno, 0, 1)
115
+
116
+ elsif overloaded.is_a?(Integer)
117
+ Bindings.write_bitcode_to_fd(@ptr, overloaded, 0, 1)
118
+
119
+ elsif overloaded.is_a?(String)
120
+ Bindings.write_bitcode_to_file(@ptr, overloaded)
121
+ end
122
+ end
123
+
124
+ # Verify that the module is valid LLVM IR.
125
+ #
126
+ # @return [nil, String] Human-readable description of any invalid constructs if invalid.
127
+ def verify
128
+ do_verification(:return_status)
129
+ end
130
+
131
+ # Verify that a module is valid LLVM IR and abort the process if it isn't.
132
+ #
133
+ # @return [nil]
134
+ def verify!
135
+ do_verification(:abort_process)
136
+ end
137
+
138
+ # Helper function for {#verify} and {#verify!}
139
+ def do_verification(action)
140
+ str_ptr = FFI::MemoryPointer.new(:pointer)
141
+ status = Bindings.verify_module(@ptr, action, str_ptr)
142
+
143
+ returning(status == 1 ? str_ptr.read_string : nil) { Bindings.dispose_message(str_ptr.read_pointer) }
144
+ end
145
+ private :do_verification
146
+
147
+ # This class is used to access a module's {Function Functions}.
148
+ class FunctionCollection
149
+ include Enumerable
150
+
151
+ # @param [Module] mod Module for which this is a proxy.
152
+ def initialize(mod)
153
+ @module = mod
154
+ end
155
+
156
+ # Retreive a Function object.
157
+ #
158
+ # @param [String, Symbol, Integer] key Function identifier. Either the name of the function or its index.
159
+ #
160
+ # @return [Function]
161
+ def [](key)
162
+ case key
163
+ when String, Symbol
164
+ self.named(key)
165
+
166
+ when Integer
167
+ (1...key).inject(self.first) { |fun| if fun then self.next(fun) else break end }
168
+ end
169
+ end
170
+
171
+ # Add a Function to this module.
172
+ #
173
+ # @param [String] name Name of the module in LLVM IR.
174
+ # @param [FunctionType, Array(Type, Array<Type>)] type_info FunctionType or Values that will be passed to {FunctionType#initialize}.
175
+ # @param [Proc] block Block to be executed inside the context of the function.
176
+ #
177
+ # @return [Function]
178
+ def add(name, *type_info, &block)
179
+ Function.new(@module, name, *type_info, &block)
180
+ end
181
+
182
+ # Remove a function from the module.
183
+ #
184
+ # @param [Function] fun Function to remove.
185
+ #
186
+ # @return [void]
187
+ def delete(fun)
188
+ Bindings.delete_function(fun)
189
+ end
190
+
191
+ # An iterator for each function inside this collection.
192
+ #
193
+ # @yieldparam fun [Function]
194
+ #
195
+ # @return [Enumerator] Returns an Enumerator if no block is given.
196
+ def each
197
+ return to_enum(:each) unless block_given?
198
+
199
+ fun = self.first
200
+
201
+ while fun
202
+ yield fun
203
+ fun = self.next(fun)
204
+ end
205
+ end
206
+
207
+ # @return [Function, nil] The module's first function if one has been added.
208
+ def first
209
+ if (ptr = Bindings.get_first_function(@module)).null? then nil else Function.new(ptr) end
210
+ end
211
+
212
+ # @return [Function, nil] The module's last function if one has been added.
213
+ def last
214
+ if (ptr = Bindings.get_last_function(@module)).null? then nil else Function.new(ptr) end
215
+ end
216
+
217
+ # @param [String, Symbol] name Name of the desired function.
218
+ #
219
+ # @return [Function, nil] The function with the given name.
220
+ def named(name)
221
+ if (ptr = Bindings.get_named_function(@module, name)).null? then nil else Function.new(ptr) end
222
+ end
223
+
224
+ # @param [Function] fun Function you want the successor for.
225
+ #
226
+ # @return [Function, nil] Next function in the collection.
227
+ def next(fun)
228
+ if (ptr = Bindings.get_next_function(fun)).null? then nil else Function.new(ptr) end
229
+ end
230
+
231
+ # @param [Function] fun Function you want the predecessor for.
232
+ #
233
+ # @return [Function, nil] Previous function in the collection.
234
+ def previous(fun)
235
+ if (ptr = Bindings.get_previous_function(fun)).null? then nil else Function.new(ptr) end
236
+ end
237
+ end
238
+
239
+ # This class is used to access a module's global variables.
240
+ class GlobalCollection
241
+ include Enumerable
242
+
243
+ # @param [Module] mod Module for which this is a proxy.
244
+ def initialize(mod)
245
+ @module = mod
246
+ end
247
+
248
+ # Retreive a GlobalVariable object.
249
+ #
250
+ # @param [String, Symbol, Integer] key Global variable identifier. Either the name of the variable or its index.
251
+ #
252
+ # @return [GlobalVariable]
253
+ def [](key)
254
+ case key
255
+ when String, Symbol
256
+ self.named(key)
257
+
258
+ when Integer
259
+ (1...key).inject(self.first) { |global| if global then self.next(global) else break end }
260
+ end
261
+ end
262
+
263
+ # Add a global variable to a module.
264
+ #
265
+ # @param [Type] type Type of the global variable.
266
+ # @param [String] name Name of the global variable in LLVM IR.
267
+ def add(type, name)
268
+ GlobalVariable.new(Bindings.add_global(@module, type, name))
269
+ end
270
+
271
+ # Remove a global variable from the module.
272
+ #
273
+ # @param [GlobalVariable] global Global variable to remove.
274
+ #
275
+ # @return [void]
276
+ def delete(global)
277
+ Bindings.delete_global(global)
278
+ end
279
+
280
+ # An iterator for each global variable inside this collection.
281
+ #
282
+ # @yieldparam fun [GlobalVariable]
283
+ #
284
+ # @return [Enumerator] Returns an Enumerator if no block is given.
285
+ def each
286
+ return to_enum(:each) unless block_given?
287
+
288
+ global = self.first
289
+
290
+ while global
291
+ yield global
292
+ global = self.next(global)
293
+ end
294
+ end
295
+
296
+ # @return [GlobalVariable, nil] The module's first global variable if one has been added.
297
+ def first
298
+ if (ptr = Bindings.get_first_global(@module)).null? then nil else GlobalValue.new(ptr) end
299
+ end
300
+
301
+ # @return [GlobalVariable, nil] The module's last global variable if one has been added.
302
+ def last
303
+ if (ptr = Bindings.get_last_global(@module)).null? then nil else GlobalValue.new(ptr) end
304
+ end
305
+
306
+ # @param [String, Symbol] name Name of the desired global variable.
307
+ #
308
+ # @return [GlobalVariable, nil] The global variable with the given name.
309
+ def named(name)
310
+ if (ptr = Bindings.get_named_global(@module, name)).null? then nil else GlobalValue.new(ptr) end
311
+ end
312
+
313
+ # @param [GlobalVariable] global Global variable you want the successor for.
314
+ #
315
+ # @return [GlobalVariable, nil] global Next global variable in the collection.
316
+ def next(global)
317
+ if (ptr = Bindings.get_next_global(global)).null? then nil else GlobalValue.new(ptr) end
318
+ end
319
+
320
+ # @param [GlobalVariable] global Global variable you want the predecessor for.
321
+ #
322
+ # @return [GlobalVariable, nil] Previous global variable in the collection.
323
+ def previous(global)
324
+ if (ptr = Bindings.get_previous_global(global)).null? then nil else GlobalValue.new(ptr) end
325
+ end
326
+ end
327
+ end
328
+ end
@@ -0,0 +1,201 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/15
4
+ # Description: This file defines the PassManager class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK::CG # :nodoc:
18
+
19
+ # A PassManager is responsible for scheduling and running optimization
20
+ # passes on modules.
21
+ class PassManager
22
+ include BindingClass
23
+
24
+ # A list of passes that are available to be added to the pass
25
+ # manager via the {PassManager#add} method.
26
+ PASSES = {
27
+ :ADCE => :agressive_dce,
28
+ :AlwaysInline => :always_inliner,
29
+ :ArgPromote => :argument_promotion,
30
+ :BasicAliasAnalysis => :basic_alias_analysis,
31
+ :CFGSimplify => :cfg_simplification,
32
+ :ConstMerge => :constant_merge,
33
+ :ConstProp => :constant_propagation,
34
+ :CorValProp => :correlated_value_propagation,
35
+ :DAE => :dead_arg_elimination,
36
+ :DSE => :dead_store_elimination,
37
+ :DemoteMemToReg => :demote_memory_to_register,
38
+ :EarlyCSE => :early_cse,
39
+ :FunctionAttrs => :function_attrs,
40
+ :FunctionInline => :function_inlining,
41
+ :GDCE => :global_dce,
42
+ :GlobalOpt => :global_optimizer,
43
+ :GVN => :gvn,
44
+ :Internalize => :internalize,
45
+ :IndVarSimplify => :ind_var_simplify,
46
+ :InstCombine => :instruction_combining,
47
+ :IPConstProp => :ip_constant_propagation,
48
+ :IPSCCP => :ipsccp,
49
+ :JumpThreading => :jump_threading,
50
+ :LICM => :licm,
51
+ :LoopDeletion => :loop_deletion,
52
+ :LoopIdiom => :loop_idiom,
53
+ :LoopRotate => :loop_rotate,
54
+ :LoopUnroll => :loop_unroll,
55
+ :LoopUnswitch => :loop_unswitch,
56
+ :LEI => :lower_expect_intrinsics,
57
+ :MemCopyOpt => :mem_cpy_opt,
58
+ :PromoteMemToReg => :promote_memory_to_register,
59
+ :PruneEH => :prune_eh,
60
+ :Reassociate => :reassociate,
61
+ :SCCP => :sccp,
62
+ :ScalarRepl => :scalar_repl_aggregates,
63
+ :SimplifyLibCalls => :simplify_lib_calls,
64
+ :StripDeadProtos => :strip_dead_prototypes,
65
+ :StripSymbols => :strip_symbols,
66
+ :TailCallElim => :tail_call_elimination,
67
+ :TBAA => :type_based_alias_analysis,
68
+ :Verifier => :verifier
69
+ }
70
+
71
+ # Creat a new pass manager. You should never have to do this as
72
+ # {ExecutionEngine ExecutionEngines} creates a PassManager whenever
73
+ # one is requested.
74
+ #
75
+ # @param [ExecutionEngine] engine ExecutionEngine this pass manager belongs to.
76
+ # @param [Module] mod Module this pass manager belongs to.
77
+ def initialize(engine, mod)
78
+ # LLVM Initialization
79
+ @ptr = Bindings.create_pass_manager
80
+ @mod = mod
81
+
82
+ Bindings.add_target_data(Bindings.get_execution_engine_target_data(engine), @ptr)
83
+
84
+ # RLTK Initialization
85
+ @enabled = Array.new
86
+ end
87
+
88
+ # Frees the resources used by LLVM for this pass manager.
89
+ #
90
+ # @return [void]
91
+ def dispose
92
+ if @ptr
93
+ self.finalize
94
+
95
+ Bindings.dispose_pass_manager(@ptr)
96
+
97
+ @ptr = nil
98
+ end
99
+ end
100
+
101
+ # Add a pass or passes to this pass manager. Passes may either be
102
+ # specified via the keys for the PASSES hash or any string that will
103
+ # be turned into a string (via the {Bindings.get_bname} method)
104
+ # appearing as a value of the PASSES hash.
105
+ #
106
+ # @see PASSES
107
+ #
108
+ # @param [Array<Symbol>] names Passes to add to the pass manager.
109
+ #
110
+ # @return [PassManager] self
111
+ def add(*names)
112
+ names.each do |name|
113
+ name = name.to_sym
114
+
115
+ if PASSES.has_key?(name)
116
+ next if @enabled.include?(name)
117
+
118
+ Bindings.send("add_#{PASSES[name]}_pass", @ptr)
119
+
120
+ @enabled << name
121
+
122
+ elsif PASSES.has_value?(bname = Bindings.get_bname(name))
123
+ next if @enabled.include?(PASSES.key(bname))
124
+
125
+ Bindings.send("add_#{bname}_pass", @ptr)
126
+
127
+ @enabled << PASSES.key(bname)
128
+
129
+ else
130
+ raise "Unknown pass: #{name}"
131
+ end
132
+ end
133
+
134
+ self
135
+ end
136
+ alias :<< :add
137
+
138
+ # @return [Array<Symbol>] List of passes that have been enabled.
139
+ def enabled
140
+ @enabled.clone
141
+ end
142
+
143
+ # @return [Boolean] Weather the pass has been enabled or not.
144
+ def enabled?(name)
145
+ @enabled.include?(name) or @enabled.include?(PASSES.key(Bindings.get_bname(name)))
146
+ end
147
+
148
+ # Run the enabled passes on the execution engine's module.
149
+ #
150
+ # @return [void]
151
+ def run
152
+ Bindings.run_pass_manager(@ptr, @mod).to_bool
153
+ end
154
+
155
+ protected
156
+ # Empty method used by {FunctionPassManager} to clean up resources.
157
+ def finalize
158
+ end
159
+ end
160
+
161
+ # A FunctionPassManager is responsible for scheduling and running optimization
162
+ # passes on individual functions inside the context of a module.
163
+ class FunctionPassManager < PassManager
164
+ # Creat a new function pass manager. You should never have to do
165
+ # this as {ExecutionEngine ExecutionEngines} creates a
166
+ # FunctionPassManager whenever one is requested.
167
+ #
168
+ # @param [ExecutionEngine] engine ExecutionEngine this pass manager belongs to.
169
+ # @param [Module] mod Module this pass manager belongs to.
170
+ def initialize(engine, mod)
171
+ # LLVM Initialization
172
+ @ptr = Bindings.create_function_pass_manager_for_module(mod)
173
+
174
+ Bindings.add_target_data(Bindings.get_execution_engine_target_data(engine), @ptr)
175
+
176
+ Bindings.initialize_function_pass_manager(@ptr).to_bool
177
+
178
+ # RLTK Initialization
179
+ @enabled = Array.new
180
+ end
181
+
182
+ # Run the enabled passes on the given function inside the execution
183
+ # engine's module.
184
+ #
185
+ # @param [Function] fun Function to optimize.
186
+ #
187
+ # @return [void]
188
+ def run(fun)
189
+ Bindings.run_function_pass_manager(@ptr, fun).to_bool
190
+ end
191
+
192
+ protected
193
+ # Called by {#dispose} to finalize any operations of the function
194
+ # pass manager.
195
+ #
196
+ # @return [void]
197
+ def finalize
198
+ Bindings.finalize_function_pass_manager(@ptr).to_bool
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,29 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/15
4
+ # Description: This file defines the Support module.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+
13
+ #######################
14
+ # Classes and Modules #
15
+ #######################
16
+
17
+ module RLTK::CG # :nodoc:
18
+
19
+ # Support functionality for LLVM code generation.
20
+ module Support
21
+ # Load a shared library into memory and make its exported symbols
22
+ # available to execution engines.
23
+ #
24
+ # @param [String] lib Path to the shared library to load.
25
+ def self.load_library(lib)
26
+ Bindings.load_library_permanently(lib).to_bool
27
+ end
28
+ end
29
+ end