rltk3 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/LICENSE +27 -0
  4. data/README.md +852 -0
  5. data/Rakefile +197 -0
  6. data/lib/rltk/ast.rb +573 -0
  7. data/lib/rltk/cfg.rb +683 -0
  8. data/lib/rltk/cg/basic_block.rb +157 -0
  9. data/lib/rltk/cg/bindings.rb +151 -0
  10. data/lib/rltk/cg/builder.rb +1127 -0
  11. data/lib/rltk/cg/context.rb +48 -0
  12. data/lib/rltk/cg/contractor.rb +51 -0
  13. data/lib/rltk/cg/execution_engine.rb +194 -0
  14. data/lib/rltk/cg/function.rb +237 -0
  15. data/lib/rltk/cg/generated_bindings.rb +8118 -0
  16. data/lib/rltk/cg/generic_value.rb +95 -0
  17. data/lib/rltk/cg/instruction.rb +519 -0
  18. data/lib/rltk/cg/llvm.rb +150 -0
  19. data/lib/rltk/cg/memory_buffer.rb +75 -0
  20. data/lib/rltk/cg/module.rb +451 -0
  21. data/lib/rltk/cg/pass_manager.rb +252 -0
  22. data/lib/rltk/cg/support.rb +29 -0
  23. data/lib/rltk/cg/target.rb +230 -0
  24. data/lib/rltk/cg/triple.rb +58 -0
  25. data/lib/rltk/cg/type.rb +554 -0
  26. data/lib/rltk/cg/value.rb +1272 -0
  27. data/lib/rltk/cg.rb +32 -0
  28. data/lib/rltk/lexer.rb +372 -0
  29. data/lib/rltk/lexers/calculator.rb +44 -0
  30. data/lib/rltk/lexers/ebnf.rb +38 -0
  31. data/lib/rltk/parser.rb +1702 -0
  32. data/lib/rltk/parsers/infix_calc.rb +43 -0
  33. data/lib/rltk/parsers/postfix_calc.rb +34 -0
  34. data/lib/rltk/parsers/prefix_calc.rb +34 -0
  35. data/lib/rltk/token.rb +90 -0
  36. data/lib/rltk/version.rb +11 -0
  37. data/lib/rltk.rb +16 -0
  38. data/test/cg/tc_basic_block.rb +83 -0
  39. data/test/cg/tc_control_flow.rb +191 -0
  40. data/test/cg/tc_function.rb +54 -0
  41. data/test/cg/tc_generic_value.rb +33 -0
  42. data/test/cg/tc_instruction.rb +256 -0
  43. data/test/cg/tc_llvm.rb +25 -0
  44. data/test/cg/tc_math.rb +88 -0
  45. data/test/cg/tc_module.rb +89 -0
  46. data/test/cg/tc_transforms.rb +68 -0
  47. data/test/cg/tc_type.rb +69 -0
  48. data/test/cg/tc_value.rb +151 -0
  49. data/test/cg/ts_cg.rb +23 -0
  50. data/test/tc_ast.rb +332 -0
  51. data/test/tc_cfg.rb +164 -0
  52. data/test/tc_lexer.rb +216 -0
  53. data/test/tc_parser.rb +711 -0
  54. data/test/tc_token.rb +34 -0
  55. data/test/ts_rltk.rb +47 -0
  56. metadata +317 -0
@@ -0,0 +1,48 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/20
4
+ # Description: This file defines the Context 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
18
+
19
+ # Bindings for LLVM contexts.
20
+ class Context
21
+ include BindingClass
22
+
23
+ # The Proc object called by the garbage collector to free resources used by LLVM.
24
+ CLASS_FINALIZER = Proc.new { |id| Bindings.context_dispose(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
25
+
26
+ #################
27
+ # Class Methods #
28
+ #################
29
+
30
+ # @return [Context] A global context.
31
+ def self.global
32
+ self.new(Bindings.get_global_context())
33
+ end
34
+
35
+ ####################
36
+ # Instance Methods #
37
+ ####################
38
+
39
+ # @param [FFI::Pointer, nil] ptr Pointer representing a context. If nil, a new context is created.
40
+ def initialize(ptr = nil)
41
+ @ptr = ptr || Bindings.context_create()
42
+
43
+ # Define a finalizer to free the memory used by LLVM for this
44
+ # context.
45
+ ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,51 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/09/21
4
+ # Description: This file contains a combination of the Visitor and Builder
5
+ # classes called a Contractor.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Gems
12
+ require 'filigree/visitor'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/cg/builder'
16
+
17
+ #######################
18
+ # Classes and Modules #
19
+ #######################
20
+
21
+ module RLTK::CG
22
+
23
+ class Contractor < Builder
24
+
25
+ include Filigree::Visitor
26
+
27
+ ####################
28
+ # Instance Methods #
29
+ ####################
30
+
31
+ # Alias out the RLTK::Visitor.visit method.
32
+ alias :wrapped_visit :visit
33
+
34
+ # Visit an object in the context of this builder. See the
35
+ # Filigree::Visitor's visit method for more details about the basic
36
+ # behaviour of this method. The special options for this method are:
37
+ #
38
+ # @param [Object] object The object to visit.
39
+ # @param [BasicBlock] at Where to position the contractor before visiting the object.
40
+ # @param [Boolean] rcb If specified the method will also return the block where the contractor is currently positioned.
41
+ #
42
+ # @return [Object]
43
+ def visit(object, at: nil, rcb: false)
44
+ target at if at
45
+
46
+ result = wrapped_visit(object)
47
+
48
+ if rcb then [result, current_block] else result end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,194 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/03/15
4
+ # Description: This file defines the ExecutionEngine class, along with its
5
+ # subclasses.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Gems
12
+ require 'filigree/abstract_class'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/cg/bindings'
16
+ require 'rltk/cg/pass_manager'
17
+ require 'rltk/cg/target'
18
+
19
+ #######################
20
+ # Classes and Modules #
21
+ #######################
22
+
23
+ module RLTK::CG
24
+
25
+ # The ExecutionEngine class and its subclasses execute code from the
26
+ # provided module, as well as providing a {PassManager} and
27
+ # {FunctionPassManager} for optimizing modules.
28
+ #
29
+ # @abstract Implemented by {Interpreter} and {JITCompiler}.
30
+ class ExecutionEngine
31
+ include Filigree::AbstractClass
32
+ include BindingClass
33
+
34
+ # The Proc object called by the garbage collector to free resources used by LLVM.
35
+ CLASS_FINALIZER = Proc.new { |id| Bindings.dispose_execution_engine(ptr) if ptr = ObjectSpace._id2ref(id).ptr }
36
+
37
+ # @return [Module]
38
+ attr_reader :module
39
+
40
+ # Create a new execution engine.
41
+ #
42
+ # @param [Module] mod Module to be executed.
43
+ # @param [Proc] block Block used by subclass constructors. Don't use this parameter.
44
+ #
45
+ # @raise [RuntimeError] An error is raised if something went horribly wrong inside LLVM during the creation of this engine.
46
+ def initialize(mod, &block)
47
+ check_type(mod, Module, 'mod')
48
+
49
+ block = Proc.new { |ptr, error| Bindings.create_execution_engine_for_module(ptr, mod, error) } if block == nil
50
+
51
+ ptr = FFI::MemoryPointer.new(:pointer)
52
+ error = FFI::MemoryPointer.new(:pointer)
53
+ status = block.call(ptr, error)
54
+
55
+ if status.zero?
56
+ @ptr = ptr.read_pointer
57
+ @module = mod
58
+
59
+ # Associate this engine with the provided module.
60
+ @module.engine = self
61
+
62
+ # Define a finalizer to free the memory used by LLVM for
63
+ # this execution engine.
64
+ ObjectSpace.define_finalizer(self, CLASS_FINALIZER)
65
+ else
66
+ errorp = error.read_pointer
67
+ message = errorp.null? ? 'Unknown' : errorp.read_string
68
+
69
+ error.autorelease = false
70
+
71
+ Bindings.dispose_message(error)
72
+
73
+ raise "Error creating execution engine: #{message}"
74
+ end
75
+ end
76
+
77
+ # Builds a pointer to a global value.
78
+ #
79
+ # @param [GlobalValue] global Value you want a pointer to.
80
+ #
81
+ # @return [FFI::Pointer]
82
+ def pointer_to_global(global)
83
+ Bindings.get_pointer_to_global(@ptr, global)
84
+ end
85
+
86
+ # Execute a function in the engine's module with the given arguments.
87
+ # The arguments may be either GnericValue objects or any object that
88
+ # can be turned into a GenericValue.
89
+ #
90
+ # @param [Function] fun Function object to be executed.
91
+ # @param [Array<GenericValue, Object>] args Arguments to be passed to the function.
92
+ #
93
+ # @return [GenericValue]
94
+ def run_function(fun, *args)
95
+ new_args =
96
+ fun.params.zip(args).map do |param, arg|
97
+ if arg.is_a?(GenericValue) then arg else GenericValue.new(arg) end
98
+ end
99
+
100
+ args_ptr = FFI::MemoryPointer.new(:pointer, args.length)
101
+ args_ptr.write_array_of_pointer(new_args)
102
+
103
+ GenericValue.new(Bindings.run_function(@ptr, fun, args.length, args_ptr))
104
+ end
105
+ alias :run :run_function
106
+
107
+ # Execute a function in the engine's module with the given arguments
108
+ # as the main function of a program.
109
+ #
110
+ # @param [Function] fun Function object to be executed.
111
+ # @param [Array<String>] args Arguments to be passed to the function.
112
+ #
113
+ # @return [GenericValue]
114
+ def run_function_as_main(fun, *args)
115
+ # Prepare the ARGV parameter.
116
+ argv = FFI::MemoryPointer.new(:pointer, argc)
117
+ argv.write_array_of_pointer(args.map { |str| FFI::MemoryPointer.from_string(str) })
118
+
119
+ # Prepare the ENV parameter.
120
+ env = FFI::MemoryPointer.new(:pointer, ENV.size)
121
+ env.write_array_of_pointer(ENV.to_a.map { |pair| FFI::MemoryPointer.from_string(pair[0] + '=' + pair[1]) })
122
+
123
+ GenericValue.new(Bindings.run_function_as_main(@ptr, fun, args.length, argv, env))
124
+ end
125
+ alias :run_main :run_function_as_main
126
+
127
+ # @return [TargetData] Information about the target architecture for this execution engine.
128
+ def target_data
129
+ TargetData.new(Bindings.get_execution_engine_target_data(@ptr))
130
+ end
131
+ end
132
+
133
+ # An execution engine that interprets the given code.
134
+ class Interpreter < ExecutionEngine
135
+
136
+ # Create a new interpreter.
137
+ #
138
+ # @param [Module] mod Module to be executed.
139
+ def initialize(mod)
140
+ super(mod) do |ptr, error|
141
+ Bindings.create_interpreter_for_module(ptr, mod, error)
142
+ end
143
+ end
144
+ end
145
+
146
+ # An execution engine that compiles the given code when needed.
147
+ class JITCompiler < ExecutionEngine
148
+
149
+ # Create a new just-in-time compiler.
150
+ #
151
+ # @param [Module] mod Module to be executed.
152
+ # @param [1, 2, 3] opt_level Optimization level; determines how much optimization is done during execution.
153
+ def initialize(mod, opt_level = 3)
154
+ super(mod) do |ptr, error|
155
+ Bindings.create_jit_compiler_for_module(ptr, mod, opt_level, error)
156
+ end
157
+ end
158
+ end
159
+
160
+ # Options for initializing a {MCJITCompiler}.
161
+ class MCJITCompilerOptions < RLTK::CG::Bindings::MCJITCompilerOptions
162
+
163
+ # Create an object representing MCJIT compiler options.
164
+ #
165
+ # @param [Integer] opt_level Optimization level
166
+ # @param [Symbol from _enum_code_model_] code_model JIT compilation code model
167
+ # @param [Boolean] no_frame_pointer_elim Disable frame pointer elimination
168
+ # @param [Boolean] enable_fast_i_sel Turn on fast instruction selection
169
+ def initialize(opt_level = 0, code_model = :jit_default, no_frame_pointer_elim = false,
170
+ enable_fast_i_sel = true)
171
+
172
+ Bindings.initialize_mcjit_compiler_options(self.to_ptr, self.class.size)
173
+
174
+ super(opt_level, code_model, no_frame_pointer_elim.to_i, enable_fast_i_sel.to_i, nil)
175
+ end
176
+ end
177
+
178
+ # The new LLVM JIT execution engine.
179
+ class MCJITCompiler < ExecutionEngine
180
+
181
+ # Create a new MC just-in-time-compiler.
182
+ #
183
+ # @see http://llvm.org/docs/MCJITDesignAndImplementation.html
184
+ # @see http://blog.llvm.org/2013/07/using-mcjit-with-kaleidoscope-tutorial.html
185
+ #
186
+ # @param [Module] mod Module to be executed
187
+ # @param [MCJITCompilerOptions] options Options used to create the MCJIT
188
+ def initialize(mod, options = MCJITCompilerOptions.new)
189
+ super(mod) do |ptr, error|
190
+ Bindings.create_mcjit_compiler_for_module(ptr, mod, options, MCJITCompilerOptions.size, error)
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,237 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/04/06
4
+ # Description: This file defines the Function class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Ruby Language Toolkit
11
+ require 'rltk/cg/bindings'
12
+ require 'rltk/cg/basic_block'
13
+ require 'rltk/cg/value'
14
+
15
+ #######################
16
+ # Classes and Modules #
17
+ #######################
18
+
19
+ module RLTK::CG
20
+
21
+ # An LLVM IR function.
22
+ class Function < GlobalValue
23
+ # @return [FunctionType] FunctionType object describing this function's type.
24
+ attr_reader :type
25
+
26
+ # Define a new function in a given module. You can also use the
27
+ # {Module::FunctionCollection#add} method to add functions to
28
+ # modules.
29
+ #
30
+ # @param [FFI::Pointer, Module] overloaded Pointer to a function objet or a module.
31
+ # @param [String] name Name of the function in LLVM IR.
32
+ # @param [FunctionType, Array(Type, Array<Type>)] type_info FunctionType or Values that will be passed to {FunctionType#initialize}.
33
+ # @param [Proc] block Block to be executed inside the context of the function.
34
+ #
35
+ # @raise [RuntimeError] An error is raised if the overloaded parameter is of an incorrect type.
36
+ def initialize(overloaded, name = '', *type_info, &block)
37
+ @ptr =
38
+ case overloaded
39
+ when FFI::Pointer
40
+ overloaded
41
+
42
+ when RLTK::CG::Module
43
+ @type = if type_info.first.is_a?(FunctionType) then type_info.first else FunctionType.new(*type_info) end
44
+
45
+ Bindings.add_function(overloaded, name.to_s, @type)
46
+
47
+ else
48
+ raise 'The first argument to Function.new must be either a pointer or an instance of RLTK::CG::Module.'
49
+ end
50
+
51
+ self.instance_exec(self, &block) if block
52
+ end
53
+
54
+ # @return [FunctionAttrCollection] Proxy object for inspecting function attributes.
55
+ def attributes
56
+ @attributes ||= FunctionAttrCollection.new(self)
57
+ end
58
+ alias :attrs :attributes
59
+
60
+ # @return [BasicBlockCollection] Proxy object for inspecting a function's basic blocks.
61
+ def basic_blocks
62
+ @basic_blocks ||= BasicBlockCollection.new(self)
63
+ end
64
+ alias :blocks :basic_blocks
65
+
66
+ # Get a function's calling convention.
67
+ #
68
+ # @see Bindings._enum_call_conv_
69
+ #
70
+ # @return [Symbol]
71
+ def calling_convention
72
+ Bindings.enum_type(:call_conv)[Bindings.get_function_call_conv(@ptr)]
73
+ end
74
+
75
+ # Set a function's calling convention.
76
+ #
77
+ # @see Bindings._enum_call_conv_
78
+ #
79
+ # @param [Symbol] conv Calling convention to set.
80
+ def calling_convention=(conv)
81
+ Bindings.set_function_call_conv(@ptr, Bindings.enum_type(:call_conv)[conv])
82
+
83
+ conv
84
+ end
85
+
86
+ # @return [ParameterCollection] Proxy object for inspecting a function's parameters.
87
+ def parameters
88
+ @parameters ||= ParameterCollection.new(self)
89
+ end
90
+ alias :params :parameters
91
+
92
+ # Verify that the function is valid LLVM IR.
93
+ #
94
+ # @return [nil, String] Human-readable description of any invalid constructs if invalid.
95
+ def verify
96
+ do_verification(:return_status)
97
+ end
98
+
99
+ # Verify that the function is valid LLVM IR and abort the process if it isn't.
100
+ #
101
+ # @return [nil]
102
+ def verify!
103
+ do_verification(:abort_process)
104
+ end
105
+
106
+ # Helper function for {#verify} and {#verify!}
107
+ def do_verification(action)
108
+ Bindings.verify_function(@ptr, action).to_bool
109
+ end
110
+ private :do_verification
111
+
112
+ # This class is used to access a function's {BasicBlock BasicBlocks}
113
+ class BasicBlockCollection
114
+ include Enumerable
115
+
116
+ # @param [Function] fun Function for which this is a proxy.
117
+ def initialize(fun)
118
+ @fun = fun
119
+ end
120
+
121
+ # Add a {BasicBlock} to the end of this function.
122
+ #
123
+ # @note The first argument to any proc passed to this function
124
+ # will be the function the block is being appended to.
125
+ #
126
+ # @param [String] name Name of the block in LLVM IR.
127
+ # @param [Builder, nil] builder Builder to be used in evaluating *block*.
128
+ # @param [Context, nil] context Context in which to create the block.
129
+ # @param [Array<Object>] block_args Arguments to be passed to *block*. The function the block is appended to is automatically added to the front of this list.
130
+ # @param [Proc] block Block to be evaluated using *builder* after positioning it at the end of the new block.
131
+ #
132
+ # @return [BasicBlock] New BasicBlock.
133
+ def append(name = '', builder = nil, context = nil, *block_args, &block)
134
+ BasicBlock.new(@fun, name, builder, context, *block_args, &block)
135
+ end
136
+
137
+ # An iterator for each block inside this collection.
138
+ #
139
+ # @yieldparam block [BasicBlock]
140
+ #
141
+ # @return [Enumerator] Returns an Enumerator if no block is given.
142
+ def each
143
+ return to_enum :each unless block_given?
144
+
145
+ ptr = Bindings.get_first_basic_block(@fun)
146
+
147
+ self.size.times do |i|
148
+ yield BasicBlock.new(ptr)
149
+ ptr = Bindings.get_next_basic_block(ptr)
150
+ end
151
+ end
152
+
153
+ # @return [BasicBlock, nil] The function's entry block if it has been added.
154
+ def entry
155
+ if (ptr = Bindings.get_entry_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
156
+ end
157
+
158
+ # @return [BasicBlock, nil] The function's first block if one has been added.
159
+ def first
160
+ if (ptr = Bindings.get_first_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
161
+ end
162
+
163
+ # @return [BasicBlock, nil] The function's last block if one has been added.
164
+ def last
165
+ if (ptr = Bindings.get_last_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
166
+ end
167
+
168
+ # @return [Integer] Number of basic blocks that comprise this function.
169
+ def size
170
+ Bindings.count_basic_blocks(@fun)
171
+ end
172
+ end
173
+
174
+ # This class is used to access a function's attributes.
175
+ class FunctionAttrCollection < AttrCollection
176
+ @@add_method = :add_function_attr
177
+ @@del_method = :remove_function_attr
178
+
179
+ # Set a target-dependent function attribute.
180
+ #
181
+ # @param [String] attribute Attribute name
182
+ # @param [String] value Attribute value
183
+ #
184
+ # @return [void]
185
+ def add_td_attr(attribute, value)
186
+ Bindings.add_target_dependent_function_attr(@value, attribute, value)
187
+ end
188
+ end
189
+
190
+
191
+ # This class is used to access a function's parameters.
192
+ class ParameterCollection
193
+ include Enumerable
194
+
195
+ # @param [Function] fun Function for which this is a proxy.
196
+ def initialize(fun)
197
+ @fun = fun
198
+ end
199
+
200
+ # Access the parameter at the given index.
201
+ #
202
+ # @param [Integer] index Index of the desired parameter. May be negative.
203
+ #
204
+ # @return [Value] Value object representing the parameter.
205
+ def [](index)
206
+ index += self.size if index < 0
207
+
208
+ if 0 <= index and index < self.size
209
+ Value.new(Bindings.get_param(@fun, index))
210
+ end
211
+ end
212
+
213
+ # An iterator for each parameter inside this collection.
214
+ #
215
+ # @yieldparam val [Value]
216
+ #
217
+ # @return [Enumerator] Returns an Enumerator if no block is given.
218
+ def each
219
+ return to_enum :each unless block_given?
220
+
221
+ self.size.times { |index| yield self[index] }
222
+
223
+ self
224
+ end
225
+
226
+ # @return [Integer] Number of function parameters.
227
+ def size
228
+ Bindings.count_params(@fun)
229
+ end
230
+
231
+ # @return [Array<Value>] Array of Value objects representing the function parameters.
232
+ def to_a
233
+ self.size.times.to_a.inject([]) { |params, index| params << self[index] }
234
+ end
235
+ end
236
+ end
237
+ end