rltk 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +21 -22
- data/lib/rltk/ast.rb +185 -118
- data/lib/rltk/cfg.rb +157 -103
- data/lib/rltk/cg/basic_block.rb +19 -19
- data/lib/rltk/cg/bindings.rb +16 -16
- data/lib/rltk/cg/builder.rb +129 -129
- data/lib/rltk/cg/context.rb +7 -7
- data/lib/rltk/cg/contractor.rb +7 -7
- data/lib/rltk/cg/execution_engine.rb +30 -30
- data/lib/rltk/cg/function.rb +37 -37
- data/lib/rltk/cg/generated_bindings.rb +3932 -3932
- data/lib/rltk/cg/generic_value.rb +17 -17
- data/lib/rltk/cg/instruction.rb +116 -116
- data/lib/rltk/cg/llvm.rb +22 -22
- data/lib/rltk/cg/memory_buffer.rb +7 -7
- data/lib/rltk/cg/module.rb +73 -73
- data/lib/rltk/cg/pass_manager.rb +35 -35
- data/lib/rltk/cg/target.rb +41 -41
- data/lib/rltk/cg/triple.rb +7 -7
- data/lib/rltk/cg/type.rb +75 -75
- data/lib/rltk/cg/value.rb +161 -161
- data/lib/rltk/lexer.rb +57 -57
- data/lib/rltk/lexers/calculator.rb +7 -7
- data/lib/rltk/lexers/ebnf.rb +5 -5
- data/lib/rltk/parser.rb +338 -295
- data/lib/rltk/parsers/infix_calc.rb +7 -7
- data/lib/rltk/parsers/postfix_calc.rb +3 -3
- data/lib/rltk/parsers/prefix_calc.rb +3 -3
- data/lib/rltk/token.rb +13 -13
- data/lib/rltk/version.rb +6 -6
- data/test/cg/tc_basic_block.rb +17 -17
- data/test/cg/tc_control_flow.rb +41 -41
- data/test/cg/tc_function.rb +4 -4
- data/test/cg/tc_generic_value.rb +3 -3
- data/test/cg/tc_instruction.rb +53 -53
- data/test/cg/tc_math.rb +12 -12
- data/test/cg/tc_module.rb +14 -14
- data/test/cg/tc_transforms.rb +11 -11
- data/test/cg/tc_type.rb +12 -12
- data/test/cg/tc_value.rb +35 -35
- data/test/cg/ts_cg.rb +5 -5
- data/test/tc_ast.rb +137 -60
- data/test/tc_cfg.rb +34 -34
- data/test/tc_lexer.rb +42 -42
- data/test/tc_parser.rb +250 -173
- data/test/tc_token.rb +2 -2
- data/test/ts_rltk.rb +8 -8
- metadata +84 -85
- data/lib/rltk/cg/old_generated_bindings.rb +0 -6152
data/lib/rltk/cg/pass_manager.rb
CHANGED
@@ -15,15 +15,15 @@ require 'rltk/cg/bindings'
|
|
15
15
|
#######################
|
16
16
|
|
17
17
|
module RLTK::CG
|
18
|
-
|
18
|
+
|
19
19
|
# A PassManager is responsible for scheduling and running optimization
|
20
20
|
# passes on modules.
|
21
21
|
class PassManager
|
22
22
|
include BindingClass
|
23
|
-
|
23
|
+
|
24
24
|
# The Proc object called by the garbage collector to free resources used by LLVM.
|
25
25
|
CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_pass_manager(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
|
26
|
-
|
26
|
+
|
27
27
|
# A list of passes that are available to be added to the pass
|
28
28
|
# manager via the {PassManager#add} method.
|
29
29
|
PASSES = {
|
@@ -75,7 +75,7 @@ module RLTK::CG
|
|
75
75
|
:TBAA => :type_based_alias_analysis,
|
76
76
|
:Verifier => :verifier
|
77
77
|
}
|
78
|
-
|
78
|
+
|
79
79
|
# Create a new pass manager. You should never have to do this as
|
80
80
|
# {Module Modules} should create PassManagers for you whenever they
|
81
81
|
# are requested.
|
@@ -87,18 +87,18 @@ module RLTK::CG
|
|
87
87
|
# LLVM Initialization
|
88
88
|
@ptr = Bindings.create_pass_manager
|
89
89
|
@mod = mod
|
90
|
-
|
90
|
+
|
91
91
|
# Set the target data if the module is associated with a execution engine.
|
92
92
|
self.target_data = mod.engine.target_data if mod.engine
|
93
|
-
|
93
|
+
|
94
94
|
# RLTK Initialization
|
95
95
|
@enabled = Array.new
|
96
|
-
|
96
|
+
|
97
97
|
# Define a finalizer to free the memory used by LLVM for this
|
98
98
|
# pass manager.
|
99
99
|
ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
# Add a pass or passes to this pass manager. Passes may either be
|
103
103
|
# specified via the keys for the PASSES hash or any string that will
|
104
104
|
# be turned into a string (via the {Bindings.get_bname} method)
|
@@ -112,47 +112,47 @@ module RLTK::CG
|
|
112
112
|
def add(*names)
|
113
113
|
names.each do |name|
|
114
114
|
name = name.to_sym
|
115
|
-
|
115
|
+
|
116
116
|
if PASSES.has_key?(name)
|
117
117
|
next if @enabled.include?(name)
|
118
|
-
|
118
|
+
|
119
119
|
Bindings.send("add_#{PASSES[name]}_pass", @ptr)
|
120
|
-
|
120
|
+
|
121
121
|
@enabled << name
|
122
|
-
|
122
|
+
|
123
123
|
elsif PASSES.has_value?(bname = Bindings.get_bname(name))
|
124
124
|
next if @enabled.include?(PASSES.key(bname))
|
125
|
-
|
125
|
+
|
126
126
|
Bindings.send("add_#{bname}_pass", @ptr)
|
127
|
-
|
127
|
+
|
128
128
|
@enabled << PASSES.key(bname)
|
129
|
-
|
129
|
+
|
130
130
|
else
|
131
131
|
raise "Unknown pass: #{name}"
|
132
132
|
end
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
135
|
self
|
136
136
|
end
|
137
137
|
alias :<< :add
|
138
|
-
|
138
|
+
|
139
139
|
# @return [Array<Symbol>] List of passes that have been enabled.
|
140
140
|
def enabled
|
141
141
|
@enabled.clone
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
# @return [Boolean] Weather the pass has been enabled or not.
|
145
145
|
def enabled?(name)
|
146
146
|
@enabled.include?(name) or @enabled.include?(PASSES.key(Bindings.get_bname(name)))
|
147
147
|
end
|
148
|
-
|
148
|
+
|
149
149
|
# Run the enabled passes on the execution engine's module.
|
150
150
|
#
|
151
151
|
# @return [void]
|
152
152
|
def run
|
153
153
|
Bindings.run_pass_manager(@ptr, @mod).to_bool
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
# Set the target data for this pass manager.
|
157
157
|
#
|
158
158
|
# @param [TargetData] data
|
@@ -161,13 +161,13 @@ module RLTK::CG
|
|
161
161
|
def target_data=(data)
|
162
162
|
Bindings.add_target_data(check_type(data, TargetData, 'data'), @ptr)
|
163
163
|
end
|
164
|
-
|
164
|
+
|
165
165
|
protected
|
166
166
|
# Empty method used by {FunctionPassManager} to clean up resources.
|
167
167
|
def finalize
|
168
168
|
end
|
169
169
|
end
|
170
|
-
|
170
|
+
|
171
171
|
# A FunctionPassManager is responsible for scheduling and running optimization
|
172
172
|
# passes on individual functions inside the context of a module.
|
173
173
|
class FunctionPassManager < PassManager
|
@@ -181,16 +181,16 @@ module RLTK::CG
|
|
181
181
|
def initialize(mod)
|
182
182
|
# LLVM Initialization
|
183
183
|
@ptr = Bindings.create_function_pass_manager_for_module(mod)
|
184
|
-
|
184
|
+
|
185
185
|
# Set the target data if the module is associated with a execution engine.
|
186
186
|
self.target_data = mod.engine.target_data if mod.engine
|
187
|
-
|
187
|
+
|
188
188
|
Bindings.initialize_function_pass_manager(@ptr)
|
189
|
-
|
189
|
+
|
190
190
|
# RLTK Initialization
|
191
191
|
@enabled = Array.new
|
192
192
|
end
|
193
|
-
|
193
|
+
|
194
194
|
# Run the enabled passes on the given function inside the execution
|
195
195
|
# engine's module.
|
196
196
|
#
|
@@ -200,7 +200,7 @@ module RLTK::CG
|
|
200
200
|
def run(fun)
|
201
201
|
Bindings.run_function_pass_manager(@ptr, fun).to_bool
|
202
202
|
end
|
203
|
-
|
203
|
+
|
204
204
|
protected
|
205
205
|
# Called by {#dispose} to finalize any operations of the function
|
206
206
|
# pass manager.
|
@@ -210,7 +210,7 @@ module RLTK::CG
|
|
210
210
|
Bindings.finalize_function_pass_manager(@ptr).to_bool
|
211
211
|
end
|
212
212
|
end
|
213
|
-
|
213
|
+
|
214
214
|
PASS_GROUPS = [
|
215
215
|
:analysis,
|
216
216
|
:core,
|
@@ -224,29 +224,29 @@ module RLTK::CG
|
|
224
224
|
:transform_utils,
|
225
225
|
:vectorization
|
226
226
|
]
|
227
|
-
|
227
|
+
|
228
228
|
class PassRegistry
|
229
229
|
include BindingClass
|
230
|
-
|
230
|
+
|
231
231
|
def self.global
|
232
232
|
PassRegistry.allocate.tap { |pr| pr.ptr = Bindings.get_global_pass_registry }
|
233
233
|
end
|
234
|
-
|
234
|
+
|
235
235
|
def initialize
|
236
236
|
@ptr = Bindings::OpaquePassRegistry.new
|
237
237
|
end
|
238
|
-
|
238
|
+
|
239
239
|
def init(pass_group = :all)
|
240
240
|
if pass_group == :all
|
241
241
|
PASS_GROUPS.each { |pg| Bindings.send("initialize_#{pg}", @ptr) }
|
242
|
-
|
242
|
+
|
243
243
|
elsif PASS_GROUPS.include?(pass_group)
|
244
244
|
Bindings.send("initialize_#{pass_group}", @ptr)
|
245
245
|
end
|
246
246
|
end
|
247
|
-
|
247
|
+
|
248
248
|
def init(pass_group)
|
249
|
-
|
249
|
+
|
250
250
|
end
|
251
251
|
end
|
252
252
|
end
|
data/lib/rltk/cg/target.rb
CHANGED
@@ -20,100 +20,100 @@ module RLTK::CG
|
|
20
20
|
# Class binding for the LLVM Triple class.
|
21
21
|
class Target
|
22
22
|
include BindingClass
|
23
|
-
|
23
|
+
|
24
24
|
#################
|
25
25
|
# Class Methods #
|
26
26
|
#################
|
27
|
-
|
27
|
+
|
28
28
|
# @return [Target] First target in the target list
|
29
29
|
def self.first
|
30
30
|
@first ||= self.new(Bindings.get_first_target)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# @return [Target] Target object for the host architecture.
|
34
34
|
def self.host
|
35
35
|
@host ||= self.new(Triple.host)
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# @return [Target] Next target in the target list
|
39
39
|
def self.next_target(target)
|
40
40
|
self.new(Bindings.get_next_target(target))
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
####################
|
44
44
|
# Instance Methods #
|
45
45
|
####################
|
46
|
-
|
46
|
+
|
47
47
|
# Create an object representing a particular code generation target.
|
48
48
|
# You can create a target either from a string or a Triple.
|
49
49
|
#
|
50
50
|
# @param [Triple, String] overloaded Object describing the target.
|
51
51
|
def initialize(overloaded)
|
52
|
-
@ptr, @triple =
|
52
|
+
@ptr, @triple =
|
53
53
|
case overloaded
|
54
54
|
when String
|
55
55
|
[Bindings.get_target_from_name(overloaded), Triple.new(overloaded)]
|
56
|
-
|
56
|
+
|
57
57
|
when RLTK::CG::Triple
|
58
58
|
ptr = FFI::MemoryPointer.new(:pointer)
|
59
59
|
error = FFI::MemoryPointer.new(:pointer)
|
60
60
|
status = Bindings.get_target_from_triple(overloaded.to_s, ptr, error)
|
61
|
-
|
61
|
+
|
62
62
|
if status.zero?
|
63
63
|
[ptr, overloaded]
|
64
|
-
|
64
|
+
|
65
65
|
else
|
66
66
|
errorp = error.read_pointer
|
67
67
|
message = errorp.null? ? 'Unknown' : errorp.read_string
|
68
|
-
|
68
|
+
|
69
69
|
error.autorelease = false
|
70
|
-
|
70
|
+
|
71
71
|
Bindings.dispose_message(error)
|
72
|
-
|
72
|
+
|
73
73
|
raise "Error creating target: #{message}"
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
when RLTK::CG::Bindings::Triple
|
77
77
|
[overloaded, nil]
|
78
78
|
end
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
# @return [Boolean] Whether or not the target has an ASM backend
|
82
82
|
def asm_backend?
|
83
83
|
Bindings.target_has_asm_backend(@ptr).to_bool
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# @return [Boolean] Whether or not the target has a JIT
|
87
87
|
def jit?
|
88
88
|
Bindings.target_has_jit(@ptr).to_bool
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
# @return [Boolean] Whether or not the target has a TargetMachine
|
92
92
|
def target_machine?
|
93
93
|
Bindings.target_has_target_machine(@ptr).to_bool
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
# @return [String] Description of the target
|
97
97
|
def describe
|
98
98
|
Bindings.get_target_description(@ptr)
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
# @return [Triple] Triple object for this target
|
102
102
|
def triple
|
103
103
|
@triple ||= Triple.new(Bindings.get_target_name(@ptr))
|
104
104
|
end
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
# This class represents data about a specific architecture. Currently it
|
108
108
|
# is for internal use only and should not be instantiated by users.
|
109
109
|
class TargetData
|
110
110
|
include BindingClass
|
111
|
-
|
111
|
+
|
112
112
|
# @param [FFI::Pointer] ptr
|
113
113
|
def initialize(ptr)
|
114
114
|
@ptr = ptr
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
# Gets the pointer size for this target machine and address space
|
118
118
|
# combination.
|
119
119
|
#
|
@@ -124,20 +124,20 @@ module RLTK::CG
|
|
124
124
|
Bindings.pointer_size_for_as(@ptr, as)
|
125
125
|
end
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
# This class represents a specific architecture that wil be targeted by
|
129
129
|
# LLVM's compilation process.
|
130
130
|
class TargetMachine
|
131
131
|
include BindingClass
|
132
|
-
|
132
|
+
|
133
133
|
# The Proc object called by the garbage collector to free resources used by LLVM.
|
134
134
|
CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_target_machine(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
|
135
|
-
|
135
|
+
|
136
136
|
# @return [TargetMachine] TargetMachine representation of the host machine.
|
137
137
|
def self.host
|
138
138
|
@host ||= self.new(Target.host)
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
# Create a new object describing a target machine.
|
142
142
|
#
|
143
143
|
# @see Bindings._enum_reloc_model_
|
@@ -152,24 +152,24 @@ module RLTK::CG
|
|
152
152
|
def initialize(target, mcpu = '', features = '', opt_level = :none, reloc_mode = :default, code_model = :default)
|
153
153
|
# Convert the features parameter if necessary.
|
154
154
|
features = TargetMachine.build_feature_string(features) if features.is_a?(Array)
|
155
|
-
|
155
|
+
|
156
156
|
@ptr = Bindings.create_target_machine(target, target.triple.to_s, mcpu, features, opt_level, reloc_mode, code_model)
|
157
|
-
|
157
|
+
|
158
158
|
# Define a finalizer to free the memory used by LLVM for
|
159
159
|
# this target machine.
|
160
160
|
ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
# @return [String] Name of the target machine's CPU
|
164
164
|
def cpu
|
165
165
|
Bindings.get_target_machine_cpu(@ptr)
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
# @return [TargetData]
|
169
169
|
def data
|
170
170
|
TargetData.new(Bindings.get_target_machine_data(@pt))
|
171
171
|
end
|
172
|
-
|
172
|
+
|
173
173
|
# Emit assembly or object code for the given module to the file
|
174
174
|
# specified.
|
175
175
|
#
|
@@ -183,34 +183,34 @@ module RLTK::CG
|
|
183
183
|
def emit_module(mod, file_name, emit_type)
|
184
184
|
error = FFI::MemoryPointer.new(:pointer)
|
185
185
|
status = Bindings.target_machine_emit_to_file(@ptr, mod, file_name, emit_type, error)
|
186
|
-
|
186
|
+
|
187
187
|
if not status.zero?
|
188
188
|
errorp = error.read_pointer
|
189
189
|
message = errorp.null? ? 'Unknown' : errorp.read_string
|
190
|
-
|
190
|
+
|
191
191
|
error.autorelease = false
|
192
|
-
|
192
|
+
|
193
193
|
Bindings.dispose_message(error)
|
194
|
-
|
194
|
+
|
195
195
|
raise "Error emiting code for module: #{message}"
|
196
196
|
end
|
197
197
|
end
|
198
|
-
|
198
|
+
|
199
199
|
# @return [String] Feature string for this target machine
|
200
200
|
def feature_string
|
201
201
|
Bindings.get_target_machine_feature_string(@ptr)
|
202
202
|
end
|
203
|
-
|
203
|
+
|
204
204
|
# @return [Target]
|
205
205
|
def target
|
206
206
|
Target.new(Bindings.get_target_machine_target(@ptr))
|
207
207
|
end
|
208
|
-
|
208
|
+
|
209
209
|
# @return [Triple]
|
210
210
|
def triple
|
211
211
|
Triple.new(Bindings.get_target_machine_triple(@ptr))
|
212
212
|
end
|
213
|
-
|
213
|
+
|
214
214
|
# Set verbose ASM property.
|
215
215
|
#
|
216
216
|
# @param [Boolean] bool Verbose ASM or not
|
@@ -218,10 +218,10 @@ module RLTK::CG
|
|
218
218
|
# @return [void]
|
219
219
|
def verbose_asm=(bool)
|
220
220
|
@verbose_asm = bool
|
221
|
-
|
221
|
+
|
222
222
|
Bindings.set_target_machine_asm_verbosity(@ptr, bool.to_i)
|
223
223
|
end
|
224
|
-
|
224
|
+
|
225
225
|
# @return [Boolean] If this target machine should print verbose ASM
|
226
226
|
def verbose_asm?
|
227
227
|
@verbose_asm ||= false
|
data/lib/rltk/cg/triple.rb
CHANGED
@@ -19,37 +19,37 @@ module RLTK::CG
|
|
19
19
|
# Class binding for the LLVM Triple class.
|
20
20
|
class Triple
|
21
21
|
include BindingClass
|
22
|
-
|
22
|
+
|
23
23
|
#################
|
24
24
|
# Class Methods #
|
25
25
|
#################
|
26
|
-
|
26
|
+
|
27
27
|
# @return [Triple] Object representing the host architecture, vendor, OS, and environment.
|
28
28
|
def self.host
|
29
29
|
@host ||= Triple.new(host_string)
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# @return [String] String representation of the host architecture, vendor, OS, and environment.
|
33
33
|
def self.host_string
|
34
34
|
@host_string ||= Bindings.get_default_target_triple
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
####################
|
38
38
|
# Instance Methods #
|
39
39
|
####################
|
40
|
-
|
40
|
+
|
41
41
|
# Create a new triple describing the host architecture, vendor, OS,
|
42
42
|
# and (optionally) environment.
|
43
43
|
#
|
44
44
|
# @param [FFI::Pointer, String] overloaded
|
45
45
|
def initialize(overloaded)
|
46
|
-
@ptr, @str =
|
46
|
+
@ptr, @str =
|
47
47
|
case overloaded
|
48
48
|
when FFI::Pointer then [overloaded, nil]
|
49
49
|
when String then [Bindings.triple_create(overloaded), overloaded]
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# @return [String] String representation of this triple.
|
54
54
|
def to_s
|
55
55
|
@str ||= Bindings.get_triple_string(@ptr)
|