rltk 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +610 -0
- data/Rakefile +156 -21
- data/lib/rltk/ast.rb +179 -127
- data/lib/rltk/cfg.rb +131 -38
- data/lib/rltk/cg/basic_block.rb +167 -0
- data/lib/rltk/cg/bindings.rb +136 -0
- data/lib/rltk/cg/builder.rb +1095 -0
- data/lib/rltk/cg/context.rb +51 -0
- data/lib/rltk/cg/execution_engine.rb +172 -0
- data/lib/rltk/cg/function.rb +224 -0
- data/lib/rltk/cg/generated_bindings.rb +6158 -0
- data/lib/rltk/cg/generated_extended_bindings.rb +43 -0
- data/lib/rltk/cg/generic_value.rb +98 -0
- data/lib/rltk/cg/instruction.rb +498 -0
- data/lib/rltk/cg/llvm.rb +51 -0
- data/lib/rltk/cg/memory_buffer.rb +62 -0
- data/lib/rltk/cg/module.rb +328 -0
- data/lib/rltk/cg/pass_manager.rb +201 -0
- data/lib/rltk/cg/support.rb +29 -0
- data/lib/rltk/cg/type.rb +510 -0
- data/lib/rltk/cg/value.rb +1207 -0
- data/lib/rltk/cg.rb +33 -0
- data/lib/rltk/lexer.rb +135 -85
- data/lib/rltk/lexers/calculator.rb +4 -1
- data/lib/rltk/lexers/ebnf.rb +1 -4
- data/lib/rltk/parser.rb +360 -196
- data/lib/rltk/token.rb +29 -4
- data/lib/rltk/util/abstract_class.rb +25 -0
- data/lib/rltk/util/monkeys.rb +125 -0
- data/lib/rltk/version.rb +5 -2
- data/test/tc_ast.rb +11 -11
- data/test/tc_lexer.rb +41 -41
- data/test/tc_parser.rb +123 -97
- data/test/ts_rltk.rb +50 -0
- metadata +181 -87
- data/README +0 -390
@@ -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
|