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/context.rb
CHANGED
@@ -15,31 +15,31 @@ require 'rltk/cg/bindings'
|
|
15
15
|
#######################
|
16
16
|
|
17
17
|
module RLTK::CG
|
18
|
-
|
18
|
+
|
19
19
|
# Bindings for LLVM contexts.
|
20
20
|
class Context
|
21
21
|
include BindingClass
|
22
|
-
|
22
|
+
|
23
23
|
# The Proc object called by the garbage collector to free resources used by LLVM.
|
24
24
|
CLASS_FINALIZER = Proc.new { |id| Bindings.context_dispose(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
|
25
|
-
|
25
|
+
|
26
26
|
#################
|
27
27
|
# Class Methods #
|
28
28
|
#################
|
29
|
-
|
29
|
+
|
30
30
|
# @return [Context] A global context.
|
31
31
|
def self.global
|
32
32
|
self.new(Bindings.get_global_context())
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
####################
|
36
36
|
# Instance Methods #
|
37
37
|
####################
|
38
|
-
|
38
|
+
|
39
39
|
# @param [FFI::Pointer, nil] ptr Pointer representing a context. If nil, a new context is created.
|
40
40
|
def initialize(ptr = nil)
|
41
41
|
@ptr = ptr || Bindings.context_create()
|
42
|
-
|
42
|
+
|
43
43
|
# Define a finalizer to free the memory used by LLVM for this
|
44
44
|
# context.
|
45
45
|
ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
|
data/lib/rltk/cg/contractor.rb
CHANGED
@@ -19,18 +19,18 @@ require 'rltk/cg/builder'
|
|
19
19
|
#######################
|
20
20
|
|
21
21
|
module RLTK::CG
|
22
|
-
|
22
|
+
|
23
23
|
class Contractor < Builder
|
24
|
-
|
24
|
+
|
25
25
|
include Filigree::Visitor
|
26
|
-
|
26
|
+
|
27
27
|
####################
|
28
28
|
# Instance Methods #
|
29
29
|
####################
|
30
|
-
|
30
|
+
|
31
31
|
# Alias out the RLTK::Visitor.visit method.
|
32
32
|
alias :wrapped_visit :visit
|
33
|
-
|
33
|
+
|
34
34
|
# Visit an object in the context of this builder. See the
|
35
35
|
# Filigree::Visitor's visit method for more details about the basic
|
36
36
|
# behaviour of this method. The special options for this method are:
|
@@ -42,9 +42,9 @@ module RLTK::CG
|
|
42
42
|
# @return [Object]
|
43
43
|
def visit(object, at: nil, rcb: false)
|
44
44
|
target at if at
|
45
|
-
|
45
|
+
|
46
46
|
result = wrapped_visit(object)
|
47
|
-
|
47
|
+
|
48
48
|
if rcb then [result, current_block] else result end
|
49
49
|
end
|
50
50
|
end
|
@@ -21,7 +21,7 @@ require 'rltk/cg/target'
|
|
21
21
|
#######################
|
22
22
|
|
23
23
|
module RLTK::CG
|
24
|
-
|
24
|
+
|
25
25
|
# The ExecutionEngine class and its subclasses execute code from the
|
26
26
|
# provided module, as well as providing a {PassManager} and
|
27
27
|
# {FunctionPassManager} for optimizing modules.
|
@@ -30,13 +30,13 @@ module RLTK::CG
|
|
30
30
|
class ExecutionEngine
|
31
31
|
include Filigree::AbstractClass
|
32
32
|
include BindingClass
|
33
|
-
|
33
|
+
|
34
34
|
# The Proc object called by the garbage collector to free resources used by LLVM.
|
35
35
|
CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_execution_engine(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
|
36
|
-
|
36
|
+
|
37
37
|
# @return [Module]
|
38
38
|
attr_reader :module
|
39
|
-
|
39
|
+
|
40
40
|
# Create a new execution engine.
|
41
41
|
#
|
42
42
|
# @param [Module] mod Module to be executed.
|
@@ -45,35 +45,35 @@ module RLTK::CG
|
|
45
45
|
# @raise [RuntimeError] An error is raised if something went horribly wrong inside LLVM during the creation of this engine.
|
46
46
|
def initialize(mod, &block)
|
47
47
|
check_type(mod, Module, 'mod')
|
48
|
-
|
48
|
+
|
49
49
|
block = Proc.new { |ptr, error| Bindings.create_execution_engine_for_module(ptr, mod, error) } if block == nil
|
50
|
-
|
50
|
+
|
51
51
|
ptr = FFI::MemoryPointer.new(:pointer)
|
52
52
|
error = FFI::MemoryPointer.new(:pointer)
|
53
53
|
status = block.call(ptr, error)
|
54
|
-
|
54
|
+
|
55
55
|
if status.zero?
|
56
56
|
@ptr = ptr.read_pointer
|
57
57
|
@module = mod
|
58
|
-
|
58
|
+
|
59
59
|
# Associate this engine with the provided module.
|
60
60
|
@module.engine = self
|
61
|
-
|
61
|
+
|
62
62
|
# Define a finalizer to free the memory used by LLVM for
|
63
63
|
# this execution engine.
|
64
64
|
ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
|
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 execution engine: #{message}"
|
74
74
|
end
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
# Builds a pointer to a global value.
|
78
78
|
#
|
79
79
|
# @param [GlobalValue] global Value you want a pointer to.
|
@@ -82,7 +82,7 @@ module RLTK::CG
|
|
82
82
|
def pointer_to_global(global)
|
83
83
|
Bindings.get_pointer_to_global(@ptr, global)
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# Execute a function in the engine's module with the given arguments.
|
87
87
|
# The arguments may be either GnericValue objects or any object that
|
88
88
|
# can be turned into a GenericValue.
|
@@ -96,14 +96,14 @@ module RLTK::CG
|
|
96
96
|
fun.params.zip(args).map do |param, arg|
|
97
97
|
if arg.is_a?(GenericValue) then arg else GenericValue.new(arg) end
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
args_ptr = FFI::MemoryPointer.new(:pointer, args.length)
|
101
101
|
args_ptr.write_array_of_pointer(new_args)
|
102
|
-
|
102
|
+
|
103
103
|
GenericValue.new(Bindings.run_function(@ptr, fun, args.length, args_ptr))
|
104
104
|
end
|
105
105
|
alias :run :run_function
|
106
|
-
|
106
|
+
|
107
107
|
# Execute a function in the engine's module with the given arguments
|
108
108
|
# as the main function of a program.
|
109
109
|
#
|
@@ -115,24 +115,24 @@ module RLTK::CG
|
|
115
115
|
# Prepare the ARGV parameter.
|
116
116
|
argv = FFI::MemoryPointer.new(:pointer, argc)
|
117
117
|
argv.write_array_of_pointer(args.map { |str| FFI::MemoryPointer.from_string(str) })
|
118
|
-
|
118
|
+
|
119
119
|
# Prepare the ENV parameter.
|
120
120
|
env = FFI::MemoryPointer.new(:pointer, ENV.size)
|
121
121
|
env.write_array_of_pointer(ENV.to_a.map { |pair| FFI::MemoryPointer.from_string(pair[0] + '=' + pair[1]) })
|
122
|
-
|
122
|
+
|
123
123
|
GenericValue.new(Bindings.run_function_as_main(@ptr, fun, args.length, argv, env))
|
124
124
|
end
|
125
125
|
alias :run_main :run_function_as_main
|
126
|
-
|
126
|
+
|
127
127
|
# @return [TargetData] Information about the target architecture for this execution engine.
|
128
128
|
def target_data
|
129
129
|
TargetData.new(Bindings.get_execution_engine_target_data(@ptr))
|
130
130
|
end
|
131
131
|
end
|
132
|
-
|
132
|
+
|
133
133
|
# An execution engine that interprets the given code.
|
134
134
|
class Interpreter < ExecutionEngine
|
135
|
-
|
135
|
+
|
136
136
|
# Create a new interpreter.
|
137
137
|
#
|
138
138
|
# @param [Module] mod Module to be executed.
|
@@ -142,10 +142,10 @@ module RLTK::CG
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
end
|
145
|
-
|
145
|
+
|
146
146
|
# An execution engine that compiles the given code when needed.
|
147
147
|
class JITCompiler < ExecutionEngine
|
148
|
-
|
148
|
+
|
149
149
|
# Create a new just-in-time compiler.
|
150
150
|
#
|
151
151
|
# @param [Module] mod Module to be executed.
|
@@ -156,10 +156,10 @@ module RLTK::CG
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
end
|
159
|
-
|
159
|
+
|
160
160
|
# Options for initializing a {MCJITCompiler}.
|
161
161
|
class MCJITCompilerOptions < RLTK::CG::Bindings::MCJITCompilerOptions
|
162
|
-
|
162
|
+
|
163
163
|
# Create an object representing MCJIT compiler options.
|
164
164
|
#
|
165
165
|
# @param [Integer] opt_level Optimization level
|
@@ -168,16 +168,16 @@ module RLTK::CG
|
|
168
168
|
# @param [Boolean] enable_fast_i_sel Turn on fast instruction selection
|
169
169
|
def initialize(opt_level = 0, code_model = :jit_default, no_frame_pointer_elim = false,
|
170
170
|
enable_fast_i_sel = true)
|
171
|
-
|
171
|
+
|
172
172
|
Bindings.initialize_mcjit_compiler_options(self.to_ptr, self.class.size)
|
173
|
-
|
173
|
+
|
174
174
|
super(opt_level, code_model, no_frame_pointer_elim.to_i, enable_fast_i_sel.to_i, nil)
|
175
175
|
end
|
176
176
|
end
|
177
|
-
|
177
|
+
|
178
178
|
# The new LLVM JIT execution engine.
|
179
179
|
class MCJITCompiler < ExecutionEngine
|
180
|
-
|
180
|
+
|
181
181
|
# Create a new MC just-in-time-compiler.
|
182
182
|
#
|
183
183
|
# @see http://llvm.org/docs/MCJITDesignAndImplementation.html
|
data/lib/rltk/cg/function.rb
CHANGED
@@ -17,12 +17,12 @@ require 'rltk/cg/value'
|
|
17
17
|
#######################
|
18
18
|
|
19
19
|
module RLTK::CG
|
20
|
-
|
20
|
+
|
21
21
|
# An LLVM IR function.
|
22
22
|
class Function < GlobalValue
|
23
23
|
# @return [FunctionType] FunctionType object describing this function's type.
|
24
24
|
attr_reader :type
|
25
|
-
|
25
|
+
|
26
26
|
# Define a new function in a given module. You can also use the
|
27
27
|
# {Module::FunctionCollection#add} method to add functions to
|
28
28
|
# modules.
|
@@ -38,31 +38,31 @@ module RLTK::CG
|
|
38
38
|
case overloaded
|
39
39
|
when FFI::Pointer
|
40
40
|
overloaded
|
41
|
-
|
41
|
+
|
42
42
|
when RLTK::CG::Module
|
43
43
|
@type = if type_info.first.is_a?(FunctionType) then type_info.first else FunctionType.new(*type_info) end
|
44
|
-
|
44
|
+
|
45
45
|
Bindings.add_function(overloaded, name.to_s, @type)
|
46
|
-
|
46
|
+
|
47
47
|
else
|
48
48
|
raise 'The first argument to Function.new must be either a pointer or an instance of RLTK::CG::Module.'
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
self.instance_exec(self, &block) if block
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# @return [FunctionAttrCollection] Proxy object for inspecting function attributes.
|
55
55
|
def attributes
|
56
56
|
@attributes ||= FunctionAttrCollection.new(self)
|
57
57
|
end
|
58
58
|
alias :attrs :attributes
|
59
|
-
|
59
|
+
|
60
60
|
# @return [BasicBlockCollection] Proxy object for inspecting a function's basic blocks.
|
61
61
|
def basic_blocks
|
62
62
|
@basic_blocks ||= BasicBlockCollection.new(self)
|
63
63
|
end
|
64
64
|
alias :blocks :basic_blocks
|
65
|
-
|
65
|
+
|
66
66
|
# Get a function's calling convention.
|
67
67
|
#
|
68
68
|
# @see Bindings._enum_call_conv_
|
@@ -71,7 +71,7 @@ module RLTK::CG
|
|
71
71
|
def calling_convention
|
72
72
|
Bindings.enum_type(:call_conv)[Bindings.get_function_call_conv(@ptr)]
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
# Set a function's calling convention.
|
76
76
|
#
|
77
77
|
# @see Bindings._enum_call_conv_
|
@@ -79,45 +79,45 @@ module RLTK::CG
|
|
79
79
|
# @param [Symbol] conv Calling convention to set.
|
80
80
|
def calling_convention=(conv)
|
81
81
|
Bindings.set_function_call_conv(@ptr, Bindings.enum_type(:call_conv)[conv])
|
82
|
-
|
82
|
+
|
83
83
|
conv
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# @return [ParameterCollection] Proxy object for inspecting a function's parameters.
|
87
87
|
def parameters
|
88
88
|
@parameters ||= ParameterCollection.new(self)
|
89
89
|
end
|
90
90
|
alias :params :parameters
|
91
|
-
|
91
|
+
|
92
92
|
# Verify that the function is valid LLVM IR.
|
93
93
|
#
|
94
94
|
# @return [nil, String] Human-readable description of any invalid constructs if invalid.
|
95
95
|
def verify
|
96
96
|
do_verification(:return_status)
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
# Verify that the function is valid LLVM IR and abort the process if it isn't.
|
100
100
|
#
|
101
101
|
# @return [nil]
|
102
102
|
def verify!
|
103
103
|
do_verification(:abort_process)
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
# Helper function for {#verify} and {#verify!}
|
107
107
|
def do_verification(action)
|
108
108
|
Bindings.verify_function(@ptr, action).to_bool
|
109
109
|
end
|
110
110
|
private :do_verification
|
111
|
-
|
111
|
+
|
112
112
|
# This class is used to access a function's {BasicBlock BasicBlocks}
|
113
113
|
class BasicBlockCollection
|
114
114
|
include Enumerable
|
115
|
-
|
115
|
+
|
116
116
|
# @param [Function] fun Function for which this is a proxy.
|
117
117
|
def initialize(fun)
|
118
118
|
@fun = fun
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
# Add a {BasicBlock} to the end of this function.
|
122
122
|
#
|
123
123
|
# @note The first argument to any proc passed to this function
|
@@ -133,7 +133,7 @@ module RLTK::CG
|
|
133
133
|
def append(name = '', builder = nil, context = nil, *block_args, &block)
|
134
134
|
BasicBlock.new(@fun, name, builder, context, *block_args, &block)
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
137
|
# An iterator for each block inside this collection.
|
138
138
|
#
|
139
139
|
# @yieldparam block [BasicBlock]
|
@@ -141,41 +141,41 @@ module RLTK::CG
|
|
141
141
|
# @return [Enumerator] Returns an Enumerator if no block is given.
|
142
142
|
def each
|
143
143
|
return to_enum :each unless block_given?
|
144
|
-
|
144
|
+
|
145
145
|
ptr = Bindings.get_first_basic_block(@fun)
|
146
|
-
|
146
|
+
|
147
147
|
self.size.times do |i|
|
148
148
|
yield BasicBlock.new(ptr)
|
149
149
|
ptr = Bindings.get_next_basic_block(ptr)
|
150
150
|
end
|
151
151
|
end
|
152
|
-
|
152
|
+
|
153
153
|
# @return [BasicBlock, nil] The function's entry block if it has been added.
|
154
154
|
def entry
|
155
155
|
if (ptr = Bindings.get_entry_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
# @return [BasicBlock, nil] The function's first block if one has been added.
|
159
159
|
def first
|
160
160
|
if (ptr = Bindings.get_first_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
# @return [BasicBlock, nil] The function's last block if one has been added.
|
164
164
|
def last
|
165
165
|
if (ptr = Bindings.get_last_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
|
166
166
|
end
|
167
|
-
|
167
|
+
|
168
168
|
# @return [Integer] Number of basic blocks that comprise this function.
|
169
169
|
def size
|
170
170
|
Bindings.count_basic_blocks(@fun)
|
171
171
|
end
|
172
172
|
end
|
173
|
-
|
173
|
+
|
174
174
|
# This class is used to access a function's attributes.
|
175
175
|
class FunctionAttrCollection < AttrCollection
|
176
176
|
@@add_method = :add_function_attr
|
177
177
|
@@del_method = :remove_function_attr
|
178
|
-
|
178
|
+
|
179
179
|
# Set a target-dependent function attribute.
|
180
180
|
#
|
181
181
|
# @param [String] attribute Attribute name
|
@@ -186,17 +186,17 @@ module RLTK::CG
|
|
186
186
|
Bindings.add_target_dependent_function_attr(@value, attribute, value)
|
187
187
|
end
|
188
188
|
end
|
189
|
-
|
190
|
-
|
189
|
+
|
190
|
+
|
191
191
|
# This class is used to access a function's parameters.
|
192
192
|
class ParameterCollection
|
193
193
|
include Enumerable
|
194
|
-
|
194
|
+
|
195
195
|
# @param [Function] fun Function for which this is a proxy.
|
196
196
|
def initialize(fun)
|
197
197
|
@fun = fun
|
198
198
|
end
|
199
|
-
|
199
|
+
|
200
200
|
# Access the parameter at the given index.
|
201
201
|
#
|
202
202
|
# @param [Integer] index Index of the desired parameter. May be negative.
|
@@ -204,12 +204,12 @@ module RLTK::CG
|
|
204
204
|
# @return [Value] Value object representing the parameter.
|
205
205
|
def [](index)
|
206
206
|
index += self.size if index < 0
|
207
|
-
|
207
|
+
|
208
208
|
if 0 <= index and index < self.size
|
209
209
|
Value.new(Bindings.get_param(@fun, index))
|
210
210
|
end
|
211
211
|
end
|
212
|
-
|
212
|
+
|
213
213
|
# An iterator for each parameter inside this collection.
|
214
214
|
#
|
215
215
|
# @yieldparam val [Value]
|
@@ -217,17 +217,17 @@ module RLTK::CG
|
|
217
217
|
# @return [Enumerator] Returns an Enumerator if no block is given.
|
218
218
|
def each
|
219
219
|
return to_enum :each unless block_given?
|
220
|
-
|
220
|
+
|
221
221
|
self.size.times { |index| yield self[index] }
|
222
|
-
|
222
|
+
|
223
223
|
self
|
224
224
|
end
|
225
|
-
|
225
|
+
|
226
226
|
# @return [Integer] Number of function parameters.
|
227
227
|
def size
|
228
228
|
Bindings.count_params(@fun)
|
229
229
|
end
|
230
|
-
|
230
|
+
|
231
231
|
# @return [Array<Value>] Array of Value objects representing the function parameters.
|
232
232
|
def to_a
|
233
233
|
self.size.times.to_a.inject([]) { |params, index| params << self[index] }
|