rltk 3.0.0 → 3.0.1
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.
- 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)
|