ruby-llvm-next 10.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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +30 -0
  3. data/README.md +67 -0
  4. data/ext/ruby-llvm-support/Rakefile +110 -0
  5. data/ext/ruby-llvm-support/support.cpp +32 -0
  6. data/lib/llvm.rb +29 -0
  7. data/lib/llvm/analysis.rb +49 -0
  8. data/lib/llvm/analysis_ffi.rb +77 -0
  9. data/lib/llvm/config.rb +10 -0
  10. data/lib/llvm/core.rb +97 -0
  11. data/lib/llvm/core/bitcode.rb +84 -0
  12. data/lib/llvm/core/bitcode_ffi.rb +132 -0
  13. data/lib/llvm/core/builder.rb +944 -0
  14. data/lib/llvm/core/context.rb +24 -0
  15. data/lib/llvm/core/module.rb +240 -0
  16. data/lib/llvm/core/pass_manager.rb +80 -0
  17. data/lib/llvm/core/type.rb +210 -0
  18. data/lib/llvm/core/value.rb +1005 -0
  19. data/lib/llvm/core_ffi.rb +6021 -0
  20. data/lib/llvm/execution_engine.rb +323 -0
  21. data/lib/llvm/execution_engine_ffi.rb +421 -0
  22. data/lib/llvm/linker.rb +16 -0
  23. data/lib/llvm/linker_ffi.rb +44 -0
  24. data/lib/llvm/support.rb +38 -0
  25. data/lib/llvm/target.rb +318 -0
  26. data/lib/llvm/target_ffi.rb +628 -0
  27. data/lib/llvm/transforms/builder.rb +107 -0
  28. data/lib/llvm/transforms/builder_ffi.rb +117 -0
  29. data/lib/llvm/transforms/ipo.rb +78 -0
  30. data/lib/llvm/transforms/ipo_ffi.rb +127 -0
  31. data/lib/llvm/transforms/scalar.rb +152 -0
  32. data/lib/llvm/transforms/scalar_ffi.rb +344 -0
  33. data/lib/llvm/transforms/vectorize.rb +22 -0
  34. data/lib/llvm/transforms/vectorize_ffi.rb +38 -0
  35. data/lib/llvm/version.rb +5 -0
  36. data/test/array_test.rb +38 -0
  37. data/test/basic_block_test.rb +87 -0
  38. data/test/binary_operations_test.rb +58 -0
  39. data/test/bitcode_test.rb +24 -0
  40. data/test/branch_test.rb +57 -0
  41. data/test/call_test.rb +82 -0
  42. data/test/comparisons_test.rb +66 -0
  43. data/test/conversions_test.rb +92 -0
  44. data/test/double_test.rb +34 -0
  45. data/test/equality_test.rb +89 -0
  46. data/test/function_test.rb +100 -0
  47. data/test/generic_value_test.rb +22 -0
  48. data/test/instruction_test.rb +30 -0
  49. data/test/ipo_test.rb +53 -0
  50. data/test/linker_test.rb +37 -0
  51. data/test/mcjit_test.rb +94 -0
  52. data/test/memory_access_test.rb +38 -0
  53. data/test/module_test.rb +93 -0
  54. data/test/parameter_collection_test.rb +28 -0
  55. data/test/pass_manager_builder_test.rb +53 -0
  56. data/test/phi_test.rb +33 -0
  57. data/test/select_test.rb +22 -0
  58. data/test/struct_test.rb +98 -0
  59. data/test/target_test.rb +113 -0
  60. data/test/test_helper.rb +62 -0
  61. data/test/type_test.rb +15 -0
  62. data/test/vector_test.rb +64 -0
  63. metadata +240 -0
@@ -0,0 +1,24 @@
1
+ module LLVM
2
+ class Context
3
+ def initialize(ptr = nil)
4
+ @ptr = ptr || C.context_create()
5
+ end
6
+
7
+ # @private
8
+ def to_ptr
9
+ @ptr
10
+ end
11
+
12
+ # Obtains a reference to the global Context.
13
+ def self.global
14
+ new(C.get_global_context())
15
+ end
16
+
17
+ # Diposes the Context.
18
+ def dispose
19
+ return if @ptr.nil?
20
+ C.context_dispose(@ptr)
21
+ @ptr = nil
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,240 @@
1
+ module LLVM
2
+ class Module
3
+ include PointerIdentity
4
+
5
+ # @private
6
+ def self.from_ptr(ptr)
7
+ return if ptr.null?
8
+ mod = allocate
9
+ mod.instance_variable_set(:@ptr, ptr)
10
+ mod
11
+ end
12
+
13
+ # Important: Call #dispose to free backend memory after use, but not when using JITCompiler with this module.
14
+ def initialize(name)
15
+ @ptr = C.module_create_with_name(name)
16
+ end
17
+
18
+ def dispose
19
+ return if @ptr.nil?
20
+
21
+ C.dispose_module(@ptr)
22
+ @ptr = nil
23
+ end
24
+
25
+ # Get module triple.
26
+ #
27
+ # @return [String]
28
+ def triple
29
+ C.get_target(self)
30
+ end
31
+
32
+ # Set module triple.
33
+ #
34
+ # @param [String] triple
35
+ def triple=(triple)
36
+ C.set_target(self, triple.to_s)
37
+ end
38
+
39
+ # Get module data layout.
40
+ #
41
+ # @return [String]
42
+ def data_layout
43
+ C.get_data_layout(self)
44
+ end
45
+
46
+ # Set module data layout.
47
+ #
48
+ # @param [String, TargetDataLayout] data_layout
49
+ def data_layout=(data_layout)
50
+ C.set_data_layout(self, data_layout.to_s)
51
+ end
52
+
53
+ # Returns a TypeCollection of all the Types in the module.
54
+ def types
55
+ @types ||= TypeCollection.new(self)
56
+ end
57
+
58
+ class TypeCollection
59
+ def initialize(mod)
60
+ @module = mod
61
+ end
62
+
63
+ # Returns the Type with the given name (symbol or string).
64
+ def named(name)
65
+ Type.from_ptr(C.get_type_by_name(@module, name.to_s), nil)
66
+ end
67
+
68
+ alias [] named
69
+ end
70
+
71
+ # Returns an Enumerable of all the GlobalVariables in the module.
72
+ def globals
73
+ @globals ||= GlobalCollection.new(self)
74
+ end
75
+
76
+ class GlobalCollection
77
+ include Enumerable
78
+
79
+ def initialize(mod)
80
+ @module = mod
81
+ end
82
+
83
+ # Adds a GlobalVariable with the given type and name to the collection (symbol or string).
84
+ def add(ty, name)
85
+ GlobalVariable.from_ptr(C.add_global(@module, LLVM::Type(ty), name.to_s)).tap do |gvar|
86
+ yield gvar if block_given?
87
+ end
88
+ end
89
+
90
+ # Returns the GlobalVariable with the given name (symbol or string).
91
+ def named(name)
92
+ GlobalValue.from_ptr(C.get_named_global(@module, name.to_s))
93
+ end
94
+
95
+ # Returns the first GlobalVariable in the collection.
96
+ def first
97
+ GlobalValue.from_ptr(C.get_first_global(@module))
98
+ end
99
+
100
+ # Returns the last GlobalVariable in the collection.
101
+ def last
102
+ GlobalValue.from_ptr(C.get_last_global(@module))
103
+ end
104
+
105
+ # Returns the next GlobalVariable in the collection after global.
106
+ def next(global)
107
+ GlobalValue.from_ptr(C.get_next_global(global))
108
+ end
109
+
110
+ # Returns the previous GlobalVariable in the collection before global.
111
+ def previous(global)
112
+ GlobalValue.from_ptr(C.get_previous_global(global))
113
+ end
114
+
115
+ # Deletes the GlobalVariable from the collection.
116
+ def delete(global)
117
+ C.delete_global(global)
118
+ end
119
+
120
+ # Returns the GlobalVariable with a name equal to key (symbol or string) or at key (integer).
121
+ def [](key)
122
+ case key
123
+ when String, Symbol then named(key)
124
+ when Integer then
125
+ i = 0
126
+ g = first
127
+ until i >= key || g.nil?
128
+ g = self.next(g)
129
+ i += 1
130
+ end
131
+ g
132
+ end
133
+ end
134
+
135
+ # Iterates through each GlobalVariable in the collection.
136
+ def each
137
+ g = first
138
+ until g.nil?
139
+ yield g
140
+ g = self.next(g)
141
+ end
142
+ end
143
+ end
144
+
145
+ # Returns a FunctionCollection of all the Functions in the module.
146
+ def functions
147
+ @functions ||= FunctionCollection.new(self)
148
+ end
149
+
150
+ class FunctionCollection
151
+ include Enumerable
152
+
153
+ def initialize(mod)
154
+ @module = mod
155
+ end
156
+
157
+ # Adds a Function with the given name (symbol or string) and args (Types).
158
+ def add(name, *args)
159
+ if args.first.kind_of? FunctionType
160
+ type = args.first
161
+ else
162
+ type = Type.function(*args)
163
+ end
164
+ function = Function.from_ptr(C.add_function(@module, name.to_s, type))
165
+
166
+ if block_given?
167
+ params = (0...function.params.size).map { |i| function.params[i] }
168
+ yield function, *params
169
+ end
170
+
171
+ function
172
+ end
173
+
174
+ # Returns the Function with the given name (symbol or string).
175
+ def named(name)
176
+ Function.from_ptr(C.get_named_function(@module, name.to_s))
177
+ end
178
+
179
+ # Returns the first Function in the collection.
180
+ def first
181
+ Function.from_ptr(C.get_first_function(@module))
182
+ end
183
+
184
+ # Returns the last Function in the collection.
185
+ def last
186
+ Function.from_ptr(C.get_last_function(@module))
187
+ end
188
+
189
+ # Returns the next Function in the collection after function.
190
+ def next(function)
191
+ Function.from_ptr(C.get_next_function(function))
192
+ end
193
+
194
+ # Returns the previous Function in the collection before function.
195
+ def previous(function)
196
+ Function.from_ptr(C.get_previous_function(function))
197
+ end
198
+
199
+ # Deletes the Function from the collection.
200
+ def delete(function)
201
+ C.delete_function(function)
202
+ end
203
+
204
+ # Returns the Function with a name equal to key (symbol or string) or at key (integer).
205
+ def [](key)
206
+ case key
207
+ when String, Symbol then named(key)
208
+ when Integer
209
+ i = 0
210
+ f = first
211
+ until i >= key || f.nil?
212
+ f = self.next(f)
213
+ i += 1
214
+ end
215
+ f
216
+ end
217
+ end
218
+
219
+ # Iterates through each Function in the collection.
220
+ def each
221
+ f = first
222
+ until f.nil?
223
+ yield f
224
+ f = self.next(f)
225
+ end
226
+ end
227
+ end
228
+
229
+ # Returns the LLVM IR of the module as a string.
230
+ def to_s
231
+ C.print_module_to_string(self)
232
+ end
233
+
234
+ # Print the module's IR to the standard error.
235
+ def dump
236
+ C.dump_module(self)
237
+ end
238
+
239
+ end
240
+ end
@@ -0,0 +1,80 @@
1
+ module LLVM
2
+ # The PassManager runs a queue of passes on a module. See
3
+ # http://llvm.org/docs/Passes.html for the list of available passes.
4
+ class PassManager
5
+ # Creates a new pass manager.
6
+ #
7
+ # @param [LLVM::ExecutionEngine, LLVM::TargetMachine] machine
8
+ def initialize(machine = nil)
9
+ if machine
10
+ warn("[DEPRECATION] PassManager.new should be called without parameters")
11
+ end
12
+ @ptr = C.create_pass_manager()
13
+ end
14
+
15
+ # @private
16
+ def to_ptr
17
+ @ptr
18
+ end
19
+
20
+ # Append a pass to the pass queue.
21
+ #
22
+ # @param [Symbol] name
23
+ # @return [LLVM::PassManager]
24
+ def <<(name)
25
+ send(:"#{name}!")
26
+
27
+ self
28
+ end
29
+
30
+ # Run the pass queue on the given module.
31
+ #
32
+ # @param [LLVM::Module] mod
33
+ # @return [true, false] Indicates whether the module was modified.
34
+ def run(mod)
35
+ C.run_pass_manager(self, mod) != 0
36
+ end
37
+
38
+ # Disposes the pass manager.
39
+ def dispose
40
+ return if @ptr.nil?
41
+
42
+ finalize
43
+
44
+ C.dispose_pass_manager(@ptr)
45
+ @ptr = nil
46
+ end
47
+
48
+ protected
49
+
50
+ def finalize
51
+ end
52
+ end
53
+
54
+ class FunctionPassManager < PassManager
55
+ # Creates a new function pass manager.
56
+ #
57
+ # @param [LLVM::ExecutionEngine, LLVM::TargetMachine] machine
58
+ # @param [LLVM::Module] mod
59
+ def initialize(machine, mod)
60
+ @ptr = C.create_function_pass_manager_for_module(mod)
61
+ C.add_target_data(machine.data_layout, @ptr)
62
+
63
+ C.initialize_function_pass_manager(self) != 0
64
+ end
65
+
66
+ # Run the pass queue on the given function.
67
+ #
68
+ # @param [LLVM::Function] fn
69
+ # @return [true, false] indicates whether the function was modified.
70
+ def run(fn)
71
+ C.run_function_pass_manager(self, fn) != 0
72
+ end
73
+
74
+ protected
75
+
76
+ def finalize
77
+ C.finalize_function_pass_manager(self) != 0
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,210 @@
1
+ module LLVM
2
+ class Type
3
+ include PointerIdentity
4
+
5
+ # @private
6
+ def self.from_ptr(ptr, kind)
7
+ return if ptr.null?
8
+ kind ||= C.get_type_kind(ptr)
9
+ ty = case kind
10
+ when :integer then IntType.allocate
11
+ when :function then FunctionType.allocate
12
+ when :struct then StructType.allocate
13
+ else allocate
14
+ end
15
+ ty.instance_variable_set(:@ptr, ptr)
16
+ ty.instance_variable_set(:@kind, kind)
17
+ ty
18
+ end
19
+
20
+ # Returns a symbol representation of the types kind (ex. :pointer, :vector, :array.)
21
+ def kind
22
+ @kind
23
+ end
24
+
25
+ # Returns the size of the type.
26
+ def size
27
+ LLVM::Int64.from_ptr(C.size_of(self))
28
+ end
29
+
30
+ def align
31
+ LLVM::Int64.from_ptr(C.align_of(self))
32
+ end
33
+
34
+ # Returns the type of this types elements (works only for Pointer, Vector, and Array types.)
35
+ def element_type
36
+ case kind
37
+ when :pointer, :vector, :array
38
+ Type.from_ptr(C.get_element_type(self), nil)
39
+ end
40
+ end
41
+
42
+ # Returns a null pointer ConstantExpr of this type.
43
+ def null_pointer
44
+ ConstantExpr.from_ptr(C.const_pointer_null(self))
45
+ end
46
+
47
+ # Returns a null ConstantExpr of this type.
48
+ def null
49
+ ConstantExpr.from_ptr(C.const_null(self))
50
+ end
51
+
52
+ # Creates a pointer type with this type and the given address space.
53
+ def pointer(address_space = 0)
54
+ Type.pointer(self, address_space)
55
+ end
56
+
57
+ # Print the type's representation to stdout.
58
+ def dump
59
+ C.dump_type(self)
60
+ end
61
+
62
+ # Creates an array type of Type with the given size.
63
+ def self.array(ty, sz = 0)
64
+ from_ptr(C.array_type(LLVM::Type(ty), sz), :array)
65
+ end
66
+
67
+ # Creates the pointer type of Type with the given address space.
68
+ def self.pointer(ty, address_space = 0)
69
+ from_ptr(C.pointer_type(LLVM::Type(ty), address_space), :pointer)
70
+ end
71
+
72
+ # Creates a vector type of Type with the given element count.
73
+ def self.vector(ty, element_count)
74
+ from_ptr(C.vector_type(LLVM::Type(ty), element_count), :vector)
75
+ end
76
+
77
+ # Creates a function type. Takes an array of argument Types and the result Type. The only option is <tt>:varargs</tt>,
78
+ # which when set to true makes the function type take a variable number of args.
79
+ def self.function(arg_types, result_type, options = {})
80
+ arg_types.map! { |ty| LLVM::Type(ty) }
81
+ arg_types_ptr = FFI::MemoryPointer.new(FFI.type_size(:pointer) * arg_types.size)
82
+ arg_types_ptr.write_array_of_pointer(arg_types)
83
+ from_ptr(C.function_type(LLVM::Type(result_type), arg_types_ptr, arg_types.size, options[:varargs] ? 1 : 0), :function)
84
+ end
85
+
86
+ # Creates a struct type with the given array of element types.
87
+ def self.struct(elt_types, is_packed, name = nil)
88
+ elt_types.map! { |ty| LLVM::Type(ty) }
89
+ elt_types_ptr = FFI::MemoryPointer.new(FFI.type_size(:pointer) * elt_types.size)
90
+ elt_types_ptr.write_array_of_pointer(elt_types)
91
+ if name
92
+ struct = from_ptr(C.struct_create_named(Context.global, name), :struct)
93
+ C.struct_set_body(struct, elt_types_ptr, elt_types.size, is_packed ? 1 : 0) unless elt_types.empty?
94
+ struct
95
+ else
96
+ from_ptr(C.struct_type(elt_types_ptr, elt_types.size, is_packed ? 1 : 0), :struct)
97
+ end
98
+ end
99
+
100
+ # Creates a void type.
101
+ def self.void
102
+ from_ptr(C.void_type, :void)
103
+ end
104
+
105
+ def self.rec
106
+ h = opaque
107
+ ty = yield h
108
+ h.refine(ty)
109
+ ty
110
+ end
111
+ end
112
+
113
+ class IntType < Type
114
+ def width
115
+ C.get_int_type_width(self)
116
+ end
117
+ end
118
+
119
+ class FunctionType < Type
120
+ def return_type
121
+ Type.from_ptr(C.get_return_type(self), nil)
122
+ end
123
+
124
+ def argument_types
125
+ size = C.count_param_types(self)
126
+ result = nil
127
+ FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |types_ptr|
128
+ C.get_param_types(self, types_ptr)
129
+ result = types_ptr.read_array_of_pointer(size)
130
+ end
131
+ result.map { |p| Type.from_ptr(p, nil) }
132
+ end
133
+
134
+ def vararg?
135
+ C.is_function_var_arg(self) != 0
136
+ end
137
+ end
138
+
139
+ class StructType < Type
140
+ # Returns the name of the struct.
141
+ def name
142
+ C.get_struct_name(self)
143
+ end
144
+
145
+ # Returns the element types of the struct.
146
+ def element_types
147
+ count = C.count_struct_element_types(self)
148
+ elt_types = nil
149
+ FFI::MemoryPointer.new(FFI.type_size(:pointer) * count) do |types_ptr|
150
+ C.get_struct_element_types(self, types_ptr)
151
+ elt_types = types_ptr.read_array_of_pointer(count).map { |type_ptr| Type.from_ptr(type_ptr, nil) }
152
+ end
153
+ elt_types
154
+ end
155
+
156
+ # Sets the struct body.
157
+ def element_types=(elt_types)
158
+ elt_types.map! { |ty| LLVM::Type(ty) }
159
+ elt_types_ptr = FFI::MemoryPointer.new(FFI.type_size(:pointer) * elt_types.size)
160
+ elt_types_ptr.write_array_of_pointer(elt_types)
161
+ C.struct_set_body(self, elt_types_ptr, elt_types.size, 0)
162
+ end
163
+ end
164
+
165
+ module_function
166
+
167
+ # Creates a Type from the given object.
168
+ def Type(ty)
169
+ case ty
170
+ when LLVM::Type then ty
171
+ else ty.type
172
+ end
173
+ end
174
+
175
+ # Shortcut to Type.array.
176
+ def Array(ty, sz = 0)
177
+ LLVM::Type.array(ty, sz)
178
+ end
179
+
180
+ # Shortcut to Type.pointer.
181
+ def Pointer(ty)
182
+ LLVM::Type.pointer(ty)
183
+ end
184
+
185
+ # Shortcut to Type.vector.
186
+ def Vector(ty, sz)
187
+ LLVM::Type.vector(ty, sz)
188
+ end
189
+
190
+ # Shortcut to Type.function.
191
+ def Function(argtypes, rettype, options = {})
192
+ LLVM::Type.function(argtypes, rettype, options)
193
+ end
194
+
195
+ # Shortcut to Type.struct.
196
+ def Struct(*elt_types)
197
+ name = if elt_types.last.is_a? String
198
+ elt_types.pop
199
+ else
200
+ nil
201
+ end
202
+ LLVM::Type.struct(elt_types, false, name)
203
+ end
204
+
205
+ # Shortcut to Type.void.
206
+ def Void
207
+ LLVM::Type.void
208
+ end
209
+
210
+ end