ruby-llvm 3.1.0.beta.1 → 3.2.0.beta.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.
Files changed (53) hide show
  1. data/LICENSE +30 -0
  2. data/README.md +49 -0
  3. data/ext/ruby-llvm-support/Rakefile +30 -7
  4. data/ext/ruby-llvm-support/support.cpp +48 -1
  5. data/lib/llvm.rb +26 -3
  6. data/lib/llvm/analysis.rb +8 -11
  7. data/lib/llvm/analysis_ffi.rb +1 -1
  8. data/lib/llvm/core.rb +36 -1
  9. data/lib/llvm/core/bitcode_ffi.rb +1 -1
  10. data/lib/llvm/core/builder.rb +20 -14
  11. data/lib/llvm/core/module.rb +87 -63
  12. data/lib/llvm/core/pass_manager.rb +30 -30
  13. data/lib/llvm/core/type.rb +34 -51
  14. data/lib/llvm/core/value.rb +13 -25
  15. data/lib/llvm/core_ffi.rb +62 -21
  16. data/lib/llvm/execution_engine.rb +13 -19
  17. data/lib/llvm/execution_engine_ffi.rb +1 -1
  18. data/lib/llvm/linker.rb +35 -0
  19. data/lib/llvm/linker_ffi.rb +45 -0
  20. data/lib/llvm/support.rb +32 -6
  21. data/lib/llvm/target.rb +318 -1
  22. data/lib/llvm/target_ffi.rb +302 -14
  23. data/lib/llvm/transforms/ipo_ffi.rb +1 -1
  24. data/lib/llvm/transforms/scalar_ffi.rb +1 -1
  25. data/lib/llvm/transforms/vectorize.rb +17 -0
  26. data/lib/llvm/transforms/vectorize_ffi.rb +31 -0
  27. data/lib/llvm/version.rb +21 -2
  28. data/test/array_test.rb +1 -1
  29. data/test/basic_block_test.rb +1 -1
  30. data/test/basic_test.rb +1 -1
  31. data/test/binary_operations_test.rb +1 -1
  32. data/test/bitcode_test.rb +2 -2
  33. data/test/branch_test.rb +1 -1
  34. data/test/call_test.rb +1 -1
  35. data/test/comparisons_test.rb +1 -1
  36. data/test/conversions_test.rb +1 -1
  37. data/test/double_test.rb +2 -2
  38. data/test/equality_test.rb +5 -5
  39. data/test/generic_value_test.rb +1 -1
  40. data/test/instruction_test.rb +1 -1
  41. data/test/ipo_test.rb +1 -1
  42. data/test/linker_test.rb +46 -0
  43. data/test/memory_access_test.rb +1 -1
  44. data/test/module_test.rb +50 -1
  45. data/test/phi_test.rb +1 -1
  46. data/test/select_test.rb +1 -1
  47. data/test/struct_test.rb +3 -3
  48. data/test/target_test.rb +124 -0
  49. data/test/test_helper.rb +10 -1
  50. data/test/type_test.rb +1 -1
  51. data/test/vector_test.rb +1 -1
  52. metadata +33 -22
  53. data/README.rdoc +0 -34
@@ -5,19 +5,6 @@ require 'llvm/analysis'
5
5
  require 'llvm/execution_engine_ffi'
6
6
 
7
7
  module LLVM
8
- # @private
9
- module C
10
- attach_function :initialize_x86_target_info, :LLVMInitializeX86TargetInfo, [], :void
11
- attach_function :initialize_x86_target, :LLVMInitializeX86Target, [], :void
12
- attach_function :initialize_x86_target_mc, :LLVMInitializeX86TargetMC, [], :void
13
- end
14
-
15
- def LLVM.init_x86
16
- LLVM::C.initialize_x86_target
17
- LLVM::C.initialize_x86_target_info
18
- LLVM::C.initialize_x86_target_mc
19
- end
20
-
21
8
  class JITCompiler
22
9
  # Important: Call #dispose to free backend memory after use. Do not call #dispose on mod any more.
23
10
  def initialize(mod, opt_level = 3)
@@ -36,7 +23,7 @@ module LLVM
36
23
  end
37
24
  end
38
25
  end
39
-
26
+
40
27
  def dispose
41
28
  return if @ptr.nil?
42
29
  C.dispose_execution_engine(@ptr)
@@ -48,6 +35,13 @@ module LLVM
48
35
  @ptr
49
36
  end
50
37
 
38
+ # Get the associated data layout.
39
+ #
40
+ # @return [TargetDataLayout]
41
+ def data_layout
42
+ TargetDataLayout.from_ptr(C.get_execution_engine_target_data(self))
43
+ end
44
+
51
45
  # Execute the given LLVM::Function with the supplied args (as
52
46
  # GenericValues).
53
47
  # Important: Call #dispose on the returned GenericValue to
@@ -82,7 +76,7 @@ module LLVM
82
76
  def to_ptr
83
77
  @ptr
84
78
  end
85
-
79
+
86
80
  # Casts an FFI::Pointer pointing to a GenericValue to an instance.
87
81
  def self.from_ptr(ptr)
88
82
  return if ptr.null?
@@ -90,7 +84,7 @@ module LLVM
90
84
  val.instance_variable_set(:@ptr, ptr)
91
85
  val
92
86
  end
93
-
87
+
94
88
  def dispose
95
89
  return if @ptr.nil?
96
90
  C.dispose_generic_value(@ptr)
@@ -113,7 +107,7 @@ module LLVM
113
107
  def self.from_d(val)
114
108
  from_ptr(C.create_generic_value_of_float(LLVM::Double, val))
115
109
  end
116
-
110
+
117
111
  # Creates a GenericValue from a Ruby boolean.
118
112
  def self.from_b(b)
119
113
  from_i(b ? 1 : 0, LLVM::Int1, false)
@@ -135,12 +129,12 @@ module LLVM
135
129
  def to_f(type = LLVM::Float.type)
136
130
  C.generic_value_to_float(type, self)
137
131
  end
138
-
132
+
139
133
  # Converts a GenericValue to a Ruby boolean.
140
134
  def to_b
141
135
  to_i(false) != 0
142
136
  end
143
-
137
+
144
138
  def to_value_ptr
145
139
  C.generic_value_to_pointer(self)
146
140
  end
@@ -4,7 +4,7 @@ require 'ffi'
4
4
 
5
5
  module LLVM::C
6
6
  extend FFI::Library
7
- ffi_lib 'LLVM-3.1'
7
+ ffi_lib 'LLVM-3.2'
8
8
 
9
9
  def self.attach_function(name, *_)
10
10
  begin; super; rescue FFI::NotFoundError => e
@@ -0,0 +1,35 @@
1
+ require 'llvm'
2
+ require 'llvm/core'
3
+ require 'llvm/linker_ffi'
4
+
5
+ module LLVM
6
+ class Module
7
+ # Link the current module into +other+.
8
+ #
9
+ # @return [nil, String] human-readable error if linking has failed
10
+ def link_into(other)
11
+ LLVM.with_message_output do |msg|
12
+ # HACK ALERT: ffi-gen missed LLVMLinkerPreserveSource enumeration for
13
+ # some reason. It is inlined as a constant here.
14
+
15
+ # C.link_modules(mod, self, :linker_preserve_source, msg)
16
+ C.link_modules(other, self, 1, msg)
17
+ end
18
+ end
19
+
20
+ # Link the current module into +other+, and dispose the current module.
21
+ #
22
+ # @return [nil, String] human-readable error if linking has failed
23
+ def link_into_and_destroy(other)
24
+ result = LLVM.with_message_output do |msg|
25
+ # HACK ALERT: ffi-gen missed LLVMLinkerPreserveSource enumeration for
26
+ # some reason. It is inlined as a constant here.
27
+ C.link_modules(other, self, :linker_destroy_source, msg)
28
+ end
29
+
30
+ @ptr = nil
31
+
32
+ result
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ # Generated by ffi_gen. Please do not change this file by hand.
2
+
3
+ require 'ffi'
4
+
5
+ module LLVM::C
6
+ extend FFI::Library
7
+ ffi_lib 'LLVM-3.2'
8
+
9
+ def self.attach_function(name, *_)
10
+ begin; super; rescue FFI::NotFoundError => e
11
+ (class << self; self; end).class_eval { define_method(name) { |*_| raise e } }
12
+ end
13
+ end
14
+
15
+ # (Not documented)
16
+ #
17
+ # <em>This entry is only for documentation and no real method. The FFI::Enum can be accessed via #enum_type(:linker_mode).</em>
18
+ #
19
+ # === Options:
20
+ # :linker_destroy_source ::
21
+ #
22
+ #
23
+ # @method _enum_linker_mode_
24
+ # @return [Symbol]
25
+ # @scope class
26
+ enum :linker_mode, [
27
+ :linker_destroy_source, 0
28
+ ]
29
+
30
+ # Links the source module into the destination module, taking ownership
31
+ # of the source module away from the caller. Optionally returns a
32
+ # human-readable description of any errors that occurred in linking.
33
+ # OutMessage must be disposed with LLVMDisposeMessage. The return value
34
+ # is true if an error occurred, false otherwise.
35
+ #
36
+ # @method link_modules(dest, src, mode, out_message)
37
+ # @param [FFI::Pointer(ModuleRef)] dest
38
+ # @param [FFI::Pointer(ModuleRef)] src
39
+ # @param [Symbol from _enum_linker_mode_] mode
40
+ # @param [FFI::Pointer(**CharS)] out_message
41
+ # @return [Integer]
42
+ # @scope class
43
+ attach_function :link_modules, :LLVMLinkModules, [:pointer, :pointer, :linker_mode, :pointer], :int
44
+
45
+ end
@@ -1,20 +1,46 @@
1
+ require 'llvm/core_ffi'
2
+
1
3
  module LLVM
4
+
2
5
  module Support
3
6
  # @private
7
+
4
8
  module C
5
9
  extend FFI::Library
6
- support_lib = File.expand_path(
7
- File.join(
8
- File.dirname(__FILE__),
9
- '../',
10
- FFI.map_library_name('RubyLLVMSupport-3.1.0')))
11
- ffi_lib [support_lib]
10
+
11
+ OpaqueValue = LLVM::C::OpaqueValue
12
+ OpaqueType = LLVM::C::OpaqueType
13
+ OpaqueModule = LLVM::C::OpaqueModule
14
+
15
+ lib_name = FFI.map_library_name('RubyLLVMSupport-3.2')
16
+ lib_path = File.expand_path("../../ext/ruby-llvm-support/#{lib_name}", File.dirname(__FILE__))
17
+ ffi_lib [lib_path]
18
+
12
19
  attach_function :load_library_permanently, :LLVMLoadLibraryPermanently, [:string], :int
20
+ attach_function :has_unnamed_addr, :LLVMHasUnnamedAddr, [OpaqueValue], :int
21
+ attach_function :set_unnamed_addr, :LLVMSetUnnamedAddr, [OpaqueValue, :int], :void
22
+ attach_function :dump_type, :LLVMDumpType, [OpaqueType], :void
23
+ attach_function :print_module, :LLVMPrintModuleToFD, [OpaqueModule, :int, :int, :int], :void
24
+
25
+ attach_function :initialize_all_target_infos,
26
+ :LLVMInitializeAllTargetInfos, [], :void
27
+ attach_function :initialize_all_targets,
28
+ :LLVMInitializeAllTargets, [], :void
29
+ attach_function :initialize_all_target_mcs,
30
+ :LLVMInitializeAllTargetMCs, [], :void
31
+ attach_function :initialize_all_asm_printers,
32
+ :LLVMInitializeAllAsmPrinters, [], :void
33
+
34
+ attach_function :initialize_native_target,
35
+ :LLVMInitializeNativeTarget, [], :void
36
+ attach_function :initialize_native_target_asm_printer,
37
+ :LLVMInitializeNativeTargetAsmPrinter, [], :void
13
38
  end
14
39
  end
15
40
 
16
41
  def load_library(libname)
17
42
  Support::C.load_library_permanently(libname)
43
+
18
44
  nil
19
45
  end
20
46
 
@@ -3,5 +3,322 @@ require 'llvm/core'
3
3
  require 'llvm/target_ffi'
4
4
 
5
5
  module LLVM
6
- # nothing here
6
+ # A shorthand for {LLVM::Target.init_native}
7
+ def self.init_jit
8
+ LLVM::Target.init_native
9
+ end
10
+
11
+ # @deprecated Use LLVM.init_jit or LLVM::Target.init('X86').
12
+ def self.init_x86
13
+ warn "LLVM.init_x86 is deprecated. Use LLVM.init_jit or LLVM::Target.init('X86')."
14
+ LLVM::Target.init('X86')
15
+ end
16
+
17
+ # You need to call {Target.init} for a target to be usable.
18
+ class Target
19
+ # Initializes target +target+; in particular, TargetInfo, Target and TargetMC.
20
+ #
21
+ # @param [String] target Target name in LLVM format, e.g. "X86", "ARM" or "PowerPC".
22
+ # @param [true, false] asm_printer Initialize corresponding AsmPrinter.
23
+ def self.init(target, asm_printer=false)
24
+ C.module_eval do
25
+ attach_function :"initialize_target_info_#{target}",
26
+ :"LLVMInitialize#{target}TargetInfo", [], :void
27
+ attach_function :"initialize_target_#{target}",
28
+ :"LLVMInitialize#{target}Target", [], :void
29
+ attach_function :"initialize_target_#{target}_mc",
30
+ :"LLVMInitialize#{target}TargetMC", [], :void
31
+
32
+ attach_function :"initialize_#{target}_asm_printer",
33
+ :"LLVMInitialize#{target}AsmPrinter", [], :void
34
+ attach_function :"initialize_#{target}_asm_parser",
35
+ :"LLVMInitialize#{target}AsmParser", [], :void
36
+ attach_function :"initialize_#{target}_disassembler",
37
+ :"LLVMInitialize#{target}Disassembler", [], :void
38
+ end
39
+
40
+ begin
41
+ %W(initialize_target_info_#{target}
42
+ initialize_target_#{target}
43
+ initialize_target_#{target}_mc).each do |init|
44
+ C.send init
45
+ end
46
+ rescue FFI::NotFoundError
47
+ raise ArgumentError, "LLVM target #{target} is not linked in. Try `llvm-config-3.2 --targets-built'."
48
+ end
49
+
50
+ begin
51
+ C.send :"initialize_#{target}_asm_printer" if asm_printer
52
+ rescue FFI::NotFoundError => e
53
+ raise ArgumentError, "LLVM target #{target} does not implement an ASM routime: #{e.message}"
54
+ end
55
+ end
56
+
57
+ # Initializes all available targets.
58
+ #
59
+ # @param [true, false] asm_printer Initialize corresponding AsmPrinters.
60
+ def self.init_all(asm_printer=false)
61
+ Support::C.initialize_all_target_infos
62
+ Support::C.initialize_all_targets
63
+ Support::C.initialize_all_target_mcs
64
+
65
+ Support::C.initialize_all_asm_printers if asm_printer
66
+ end
67
+
68
+ # Initializes native target. Useful for JIT applications.
69
+ #
70
+ # @param [true, false] asm_printer Initialize corresponding AsmPrinter.
71
+ def self.init_native(asm_printer=false)
72
+ Support::C.initialize_native_target
73
+
74
+ Support::C.initialize_native_target_asm_printer if asm_printer
75
+ end
76
+
77
+ # Enumerate all initialized targets.
78
+ #
79
+ # @yield [Target]
80
+ def self.each(&block)
81
+ return to_enum(:each) if block.nil?
82
+
83
+ target = C.get_first_target
84
+ until target.null?
85
+ yield from_ptr(target)
86
+
87
+ target = C.get_next_target(target)
88
+ end
89
+ end
90
+
91
+ # Fetch a target by its name.
92
+ #
93
+ # @return [Target]
94
+ def self.by_name(name)
95
+ each do |target|
96
+ return target if target.name == name
97
+ end
98
+ end
99
+
100
+ include PointerIdentity
101
+
102
+ # @private
103
+ def self.from_ptr(ptr)
104
+ target = allocate
105
+ target.instance_variable_set :@ptr, ptr
106
+ target
107
+ end
108
+
109
+ # Returns the name of the target.
110
+ #
111
+ # @return [String]
112
+ def name
113
+ C.get_target_name(self)
114
+ end
115
+
116
+ # Returns the description of the target.
117
+ #
118
+ # @return [String]
119
+ def description
120
+ C.get_target_description(self)
121
+ end
122
+
123
+ # Returns if the target has a JIT.
124
+ def jit?
125
+ !C.target_has_jit(self).zero?
126
+ end
127
+
128
+ # Returns if the target has a TargetMachine associated.
129
+ def target_machine?
130
+ !C.target_has_target_machine(self).zero?
131
+ end
132
+
133
+ # Returns if the target has an ASM backend (required for emitting output).
134
+ def asm_backend?
135
+ !C.target_has_asm_backend(self).zero?
136
+ end
137
+
138
+ # Constructs a TargetMachine.
139
+ #
140
+ # @param [String] triple Target triple
141
+ # @param [String] cpu Target CPU
142
+ # @param [String] features Target feature string
143
+ # @param [Symbol] opt_level :none, :less, :default, :aggressive
144
+ # @param [Symbol] reloc :default, :static, :pic, :dynamic_no_pic
145
+ # @param [Symbol] code_model :default, :jit_default, :small, :kernel, :medium, :large
146
+ # @return [TargetMachine]
147
+ def create_machine(triple, cpu="", features="",
148
+ opt_level=:default, reloc=:default, code_model=:default)
149
+ TargetMachine.from_ptr(C.create_target_machine(self,
150
+ triple, cpu, features, opt_level, reloc, code_model))
151
+ end
152
+ end
153
+
154
+ class TargetMachine
155
+ include PointerIdentity
156
+
157
+ # @private
158
+ def self.from_ptr(ptr)
159
+ target = allocate
160
+ target.instance_variable_set :@ptr, ptr
161
+ target
162
+ end
163
+
164
+ # Destroys this instance of TargetMachine.
165
+ def dispose
166
+ return if @ptr.nil?
167
+
168
+ C.dispose_target_machine(self)
169
+ @ptr = nil
170
+ end
171
+
172
+ # Returns the corresponding Target.
173
+ #
174
+ # @return [Target]
175
+ def target
176
+ Target.from_ptr(C.get_target_machine_target(self))
177
+ end
178
+
179
+ # Returns the triple used for creating this target machine.
180
+ def triple
181
+ C.get_target_machine_triple(self)
182
+ end
183
+
184
+ # Returns the CPU used for creating this target machine.
185
+ def cpu
186
+ C.get_target_machine_cpu(self)
187
+ end
188
+
189
+ # Returns the feature string used for creating this target machine.
190
+ def features
191
+ C.get_target_machine_feature_string(self)
192
+ end
193
+
194
+ # Returns the data layout used for this target machine.
195
+ #
196
+ # @return [TargetDataLayout]
197
+ def data_layout
198
+ TargetDataLayout.from_ptr(C.get_target_machine_data(self))
199
+ end
200
+
201
+ # Emits an asm or object file for the given module.
202
+ #
203
+ # @param [Symbol] codegen :assembly, :object
204
+ def emit(mod, filename, codegen=:assembly)
205
+ LLVM.with_error_output do |err|
206
+ C.target_machine_emit_to_file(self, mod, filename.to_s, codegen, err)
207
+ end
208
+ end
209
+ end
210
+
211
+ # @private
212
+ module C
213
+ # ffi_gen autodetects :string, which is too weak to be usable
214
+ # with LLVMDisposeMessage
215
+ attach_function :copy_string_rep_of_target_data, :LLVMCopyStringRepOfTargetData, [OpaqueTargetData], :pointer
216
+ end
217
+
218
+ class TargetDataLayout
219
+ # Creates a target data layout from a string representation.
220
+ #
221
+ # @param [String] representation
222
+ def initialize(representation)
223
+ @ptr = C.create_target_data(representation.to_s)
224
+ end
225
+
226
+ # @private
227
+ def self.from_ptr(ptr)
228
+ target = allocate
229
+ target.instance_variable_set :@ptr, ptr
230
+ target
231
+ end
232
+
233
+ # @private
234
+ def to_ptr
235
+ @ptr
236
+ end
237
+
238
+ # Destroys this instance of TargetDataLayout.
239
+ def dispose
240
+ return if ptr.nil?
241
+
242
+ C.dispose_target_data(self)
243
+ @ptr = nil
244
+ end
245
+
246
+ # Returns string representation of target data layout.
247
+ #
248
+ # @return [String]
249
+ def to_s
250
+ string_ptr = C.copy_string_rep_of_target_data(self)
251
+ string = string_ptr.read_string
252
+ C.dispose_message(string_ptr)
253
+
254
+ string
255
+ end
256
+
257
+ # Returns the byte order of a target, either :big_endian or :little_endian.
258
+ def byte_order
259
+ C.byte_order(self)
260
+ end
261
+
262
+ # Returns the pointer size in bytes for a target.
263
+ #
264
+ # @param [Integer] addr_space address space number
265
+ def pointer_size(addr_space=0)
266
+ C.pointer_size_for_as(self, addr_space)
267
+ end
268
+
269
+ # Returns the integer type that is the same size as a pointer on a target.
270
+ #
271
+ # @param [Integer] addr_space address space number
272
+ def int_ptr_type(addr_space=0)
273
+ Type.from_ptr(C.int_ptr_type_for_as(self, addr_space), :integer)
274
+ end
275
+
276
+ # Computes the size of a type in bits for a target.
277
+ def bit_size_of(type)
278
+ C.size_of_type_in_bits(self, type)
279
+ end
280
+
281
+ # Computes the storage size of a type in bytes for a target.
282
+ def storage_size_of(type)
283
+ C.store_size_of_type(self, type)
284
+ end
285
+
286
+ # Computes the ABI size of a type in bytes for a target.
287
+ def abi_size_of(type)
288
+ C.abi_size_of_type(self, type)
289
+ end
290
+
291
+ # Computes the ABI alignment of a type in bytes for a target.
292
+ def abi_alignment_of(type)
293
+ C.abi_alignment_of_type(self, type)
294
+ end
295
+
296
+ # Computes the call frame alignment of a type in bytes for a target.
297
+ def call_frame_alignment_of(type)
298
+ C.call_frame_alignment_of_type(self, type)
299
+ end
300
+
301
+ # Computes the preferred alignment of a type or a global variable in bytes
302
+ # for a target.
303
+ #
304
+ # @param [LLVM::Type, LLVM::GlobalValue] entity
305
+ def preferred_alignment_of(entity)
306
+ case entity
307
+ when LLVM::Type
308
+ C.preferred_alignment_of_type(self, entity)
309
+ when LLVM::GlobalValue
310
+ C.preferred_alignment_of_global(self, entity)
311
+ end
312
+ end
313
+
314
+ # Computes the structure element that contains the byte offset for a target.
315
+ def element_at_offset(type, offset)
316
+ C.element_at_offset(self, type, offset)
317
+ end
318
+
319
+ # Computes the byte offset of the indexed struct element for a target.
320
+ def offset_of_element(type, element)
321
+ C.offset_of_element(self, type, element)
322
+ end
323
+ end
7
324
  end