ruby-llvm 3.1.0.beta.1 → 3.2.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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