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.
@@ -0,0 +1,51 @@
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 # :nodoc:
18
+
19
+ # Bindings for LLVM contexts.
20
+ class Context
21
+ include BindingClass
22
+
23
+ #################
24
+ # Class Methods #
25
+ #################
26
+
27
+ # @return [Context] A global context.
28
+ def self.global
29
+ self.new(Bindings.get_global_context())
30
+ end
31
+
32
+ ####################
33
+ # Instance Methods #
34
+ ####################
35
+
36
+ # @param [FFI::Pointer, nil] ptr Pointer representing a context. If nil, a new context is created.
37
+ def initialize(ptr = nil)
38
+ @ptr = ptr || Bindings.context_create()
39
+ end
40
+
41
+ # Frees the resources used by LLVM for this context.
42
+ #
43
+ # @return [void]
44
+ def dispose
45
+ if @ptr
46
+ Bindings.context_dispose(@ptr)
47
+ @ptr = nil
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,172 @@
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
+ # Ruby Language Toolkit
12
+ require 'rltk/util/abstract_class'
13
+ require 'rltk/cg/bindings'
14
+ require 'rltk/cg/pass_manager'
15
+
16
+ #######################
17
+ # Classes and Modules #
18
+ #######################
19
+
20
+ module RLTK::CG # :nodoc:
21
+
22
+ # The ExecutionEngine class and its subclasses execute code from the
23
+ # provided module, as well as providing a {PassManager} and
24
+ # {FunctionPassManager} for optimizing modules.
25
+ #
26
+ # @abstract Implemented by {Interpreter} and {JITCompiler}.
27
+ class ExecutionEngine
28
+ include AbstractClass
29
+ include BindingClass
30
+
31
+ # @return [Module]
32
+ attr_reader :module
33
+
34
+ # Create a new execution engine.
35
+ #
36
+ # @param [Module] mod Module to be executed.
37
+ # @param [Proc] block Block used by subclass constructors. Don't use this parameter.
38
+ #
39
+ # @raise [RuntimeError] An error is raised if something went horribly wrong inside LLVM during the creation of this engine.
40
+ def initialize(mod, &block)
41
+ block = Proc.new { |ptr, error| Bindings.create_execution_engine_for_module(ptr, mod, error) } if block == nil
42
+
43
+ ptr = FFI::MemoryPointer.new(:pointer)
44
+ error = FFI::MemoryPointer.new(:pointer)
45
+ status = block.call(ptr, error)
46
+
47
+ if status.zero?
48
+ @ptr = ptr.read_pointer
49
+ @module = mod
50
+
51
+ else
52
+ errorp = error.read_pointer
53
+ message = errorp.null? ? 'Unknown' : errorp.read_string
54
+
55
+ error.autorelease = false
56
+
57
+ Bindings.dispose_message(error)
58
+
59
+ raise "Error creating execution engine: #{message}"
60
+ end
61
+ end
62
+
63
+ # Frees the resources used by LLVM for this execution engine..
64
+ #
65
+ # @return [void]
66
+ def dispose
67
+ if @ptr
68
+ Bindings.dispose_execution_engine(@ptr)
69
+
70
+ @ptr = nil
71
+ end
72
+ end
73
+
74
+ # @return [FunctionPassManager] Function pass manager for this engine.
75
+ def function_pass_manager
76
+ @function_pass_manager ||= FunctionPassManager.new(self, @module)
77
+ end
78
+ alias :fpm :function_pass_manager
79
+
80
+ # @return [PassManager] Pass manager for this engine.
81
+ def pass_manager
82
+ @pass_manager ||= PassManager.new(self, @module)
83
+ end
84
+ alias :pm :pass_manager
85
+
86
+ # Builds a pointer to a global value.
87
+ #
88
+ # @param [GlobalValue] global Value you want a pointer to.
89
+ #
90
+ # @return [FFI::Pointer]
91
+ def pointer_to_global(global)
92
+ Bindings.get_pointer_to_global(@ptr, global)
93
+ end
94
+
95
+ # Execute a function in the engine's module with the given arguments.
96
+ # The arguments may be either GnericValue objects or any object that
97
+ # can be turned into a GenericValue.
98
+ #
99
+ # @param [Function] fun Function object to be executed.
100
+ # @param [Array<GenericValue, Object>] args Arguments to be passed to the function.
101
+ #
102
+ # @return [GenericValue]
103
+ def run_function(fun, *args)
104
+ new_values = Array.new
105
+
106
+ new_args =
107
+ fun.params.zip(args).map do |param, arg|
108
+ if arg.is_a?(GenericValue)
109
+ arg
110
+
111
+ else
112
+ returning(GenericValue.new(arg)) { |val| new_values << val }
113
+ end
114
+ end
115
+
116
+ args_ptr = FFI::MemoryPointer.new(:pointer, args.length)
117
+ args_ptr.write_array_of_pointer(new_args)
118
+
119
+ returning(GenericValue.new(Bindings.run_function(@ptr, fun, args.length, args_ptr))) do
120
+ new_values.each { |val| val.dispose }
121
+ end
122
+ end
123
+ alias :run :run_function
124
+
125
+ # Execute a function in the engine's module with the given arguments
126
+ # as the main function of a program.
127
+ #
128
+ # @param [Function] fun Function object to be executed.
129
+ # @param [Array<String>] args Arguments to be passed to the function.
130
+ #
131
+ # @return [GenericValue]
132
+ def run_function_as_main(fun, *args)
133
+ # Prepare the ARGV parameter.
134
+ argv = FFI::MemoryPointer.new(:pointer, argc)
135
+ argv.write_array_of_pointer(args.map { |str| FFI::MemoryPointer.from_string(str) })
136
+
137
+ # Prepare the ENV parameter.
138
+ env = FFI::MemoryPointer.new(:pointer, ENV.size)
139
+ env.write_array_of_pointer(ENV.to_a.map { |pair| FFI::MemoryPointer.from_string(pair[0] + '=' + pair[1]) })
140
+
141
+ GenericValue.new(Bindings.run_function_as_main(@ptr, fun, args.length, argv, env))
142
+ end
143
+ alias :run_main :run_function_as_main
144
+ end
145
+
146
+ # An execution engine that interprets the given code.
147
+ class Interpreter < ExecutionEngine
148
+
149
+ # Create a new interpreter.
150
+ #
151
+ # @param [Module] mod Module to be executed.
152
+ def initialize(mod)
153
+ super(mod) do |ptr, error|
154
+ Bindings.create_interpreter_for_module(ptr, mod, error)
155
+ end
156
+ end
157
+ end
158
+
159
+ # An execution engine that compiles the given code when needed.
160
+ class JITCompiler < ExecutionEngine
161
+
162
+ # Create a new just-in-time compiler.
163
+ #
164
+ # @param [Module] mod Module to be executed.
165
+ # @param [1, 2, 3] opt_level Optimization level; determines how much optimization is done during execution.
166
+ def initialize(mod, opt_level = 3)
167
+ super(mod) do |ptr, error|
168
+ Bindings.create_jit_compiler_for_module(ptr, mod, opt_level, error)
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,224 @@
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 # :nodoc:
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
+ # @param [String] name Name of the block in LLVM IR.
124
+ # @param [Context, nil] context Context in which to create the block.
125
+ # @param [Builder, nil] builder Builder to be used in evaluating *block*.
126
+ # @param [Array<Object>] block_args Arguments to be passed to *block*.
127
+ # @param [Proc] block Block to be evaluated using *builder* after positioning it at the end of the new block.
128
+ #
129
+ # @return [BasicBlock] New BasicBlock.
130
+ def append(name = '', context = nil, builder = nil, *block_args, &block)
131
+ BasicBlock.new(@fun, name, context, builder, *block_args, &block)
132
+ end
133
+
134
+ # An iterator for each block inside this collection.
135
+ #
136
+ # @yieldparam block [BasicBlock]
137
+ #
138
+ # @return [Enumerator] Returns an Enumerator if no block is given.
139
+ def each
140
+ return to_enum :each unless block_given?
141
+
142
+ ptr = Bindings.get_first_basic_block(@fun)
143
+
144
+ self.size.times do |i|
145
+ yield BasicBlock.new(ptr)
146
+ ptr = Bindings.get_next_basic_block(ptr)
147
+ end
148
+ end
149
+
150
+ # @return [BasicBlock, nil] The function's entry block if it has been added.
151
+ def entry
152
+ if (ptr = Bindings.get_entry_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
153
+ end
154
+
155
+ # @return [BasicBlock, nil] The function's first block if one has been added.
156
+ def first
157
+ if (ptr = Bindings.get_first_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
158
+ end
159
+
160
+ # @return [BasicBlock, nil] The function's last block if one has been added.
161
+ def last
162
+ if (ptr = Bindings.get_last_basic_block(@fun)) then BasicBlock.new(ptr) else nil end
163
+ end
164
+
165
+ # @return [Integer] Number of basic blocks that comprise this function.
166
+ def size
167
+ Bindings.count_basic_blocks(@fun)
168
+ end
169
+ end
170
+
171
+ # This class is used to access a function's attributes.
172
+ class FunctionAttrCollection < AttrCollection
173
+ @@add_method = :add_function_attr
174
+ @@del_method = :remove_function_attr
175
+ end
176
+
177
+
178
+ # This class is used to access a function's parameters.
179
+ class ParameterCollection
180
+ include Enumerable
181
+
182
+ # @param [Function] fun Function for which this is a proxy.
183
+ def initialize(fun)
184
+ @fun = fun
185
+ end
186
+
187
+ # Access the parameter at the given index.
188
+ #
189
+ # @param [Integer] index Index of the desired parameter. May be negative.
190
+ #
191
+ # @return [Value] Value object representing the parameter.
192
+ def [](index)
193
+ index += self.size if index < 0
194
+
195
+ if 0 <= index and index < self.size
196
+ Value.new(Bindings.get_param(@fun, index))
197
+ end
198
+ end
199
+
200
+ # An iterator for each parameter inside this collection.
201
+ #
202
+ # @yieldparam val [Value]
203
+ #
204
+ # @return [Enumerator] Returns an Enumerator if no block is given.
205
+ def each
206
+ return to_enum :each unless block_given?
207
+
208
+ self.size.times { |index| yield self[index] }
209
+
210
+ self
211
+ end
212
+
213
+ # @return [Integer] Number of function parameters.
214
+ def size
215
+ Bindings.count_params(@fun)
216
+ end
217
+
218
+ # @return [Array<Value>] Array of Value objects representing the function parameters.
219
+ def to_a
220
+ self.size.times.to_a.inject([]) { |params, index| params << self[index] }
221
+ end
222
+ end
223
+ end
224
+ end