rltk 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|