ruby-llvm 2.9.1 → 2.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,27 +1,19 @@
1
1
  module LLVM
2
2
  class Context
3
- private_class_method :new
4
-
5
- # @private
6
- def initialize(ptr)
7
- @ptr = ptr
3
+ def initialize
4
+ @ptr = C.LLVMContextCreate()
8
5
  end
9
-
6
+
10
7
  # @private
11
8
  def to_ptr
12
9
  @ptr
13
10
  end
14
-
15
- # Creates a new Context.
16
- def self.create
17
- new(C.LLVMContextCreate())
18
- end
19
-
11
+
20
12
  # Obtains a reference to the global Context.
21
13
  def self.global
22
14
  new(C.LLVMGetGlobalContext())
23
15
  end
24
-
16
+
25
17
  # Diposes the Context.
26
18
  def dispose
27
19
  C.LLVMContextDispose(@ptr)
@@ -1,15 +1,15 @@
1
1
  module LLVM
2
2
  class Module
3
- private_class_method :new
4
-
5
3
  # @private
6
4
  def self.from_ptr(ptr)
7
- ptr.null? ? nil : new(ptr)
5
+ return if ptr.null?
6
+ mod = allocate
7
+ mod.instance_variable_set(:@ptr, ptr)
8
+ mod
8
9
  end
9
10
 
10
- # @private
11
- def initialize(ptr)
12
- @ptr = ptr
11
+ def initialize(name)
12
+ @ptr = C.LLVMModuleCreateWithName(name)
13
13
  end
14
14
 
15
15
  # @private
@@ -32,11 +32,6 @@ module LLVM
32
32
  other.instance_of?(self.class) && self == other
33
33
  end
34
34
 
35
- # Creates a module with the given name.
36
- def self.create(name)
37
- new(C.LLVMModuleCreateWithName(name))
38
- end
39
-
40
35
  # Returns a TypeCollection of all the Types in the module.
41
36
  def types
42
37
  @types ||= TypeCollection.new(self)
@@ -8,6 +8,8 @@ module LLVM
8
8
  C.LLVMAddTargetData(
9
9
  C.LLVMGetExecutionEngineTargetData(execution_engine), ptr)
10
10
  @ptr = ptr
11
+
12
+ do_initialization
11
13
  end
12
14
 
13
15
  # @private
@@ -15,26 +17,34 @@ module LLVM
15
17
  @ptr
16
18
  end
17
19
 
20
+ # Append a pass to the pass queue.
21
+ # @param [Symbol]
22
+ # @return [LLVM::PassManager]
18
23
  def <<(name)
19
24
  send(:"#{name}!")
20
25
  self
21
26
  end
22
27
 
23
- def do_initialization
24
- end
25
-
26
- def do_finalization
27
- end
28
-
29
- # Runs the passes on the given module.
28
+ # Run the pass queue on the given module.
29
+ # @param [LLVM::Module]
30
+ # @return [true, false] Indicates whether the module was modified.
30
31
  def run(mod)
31
- C.LLVMRunPassManager(self, mod)
32
+ C.LLVMRunPassManager(self, mod) != 0
32
33
  end
33
34
 
34
35
  # Disposes the pass manager.
35
36
  def dispose
37
+ do_finalization
36
38
  C.LLVMDisposePassManager(self)
37
39
  end
40
+
41
+ protected
42
+
43
+ def do_initialization
44
+ end
45
+
46
+ def do_finalization
47
+ end
38
48
  end
39
49
 
40
50
  class FunctionPassManager < PassManager
@@ -46,6 +56,15 @@ module LLVM
46
56
  @ptr = ptr
47
57
  end
48
58
 
59
+ # Run the pass queue on the given function.
60
+ # @param [LLVM::Function]
61
+ # @return [true, false] indicates whether the function was modified.
62
+ def run(fn)
63
+ C.LLVMRunFunctionPassManager(self, fn) != 0
64
+ end
65
+
66
+ protected
67
+
49
68
  def do_initialization
50
69
  C.LLVMInitializeFunctionPassManager(self) != 0
51
70
  end
@@ -53,10 +72,5 @@ module LLVM
53
72
  def do_finalization
54
73
  C.LLVMFinalizeFunctionPassManager(self) != 0
55
74
  end
56
-
57
- # Runs the passes on the given function.
58
- def run(fn)
59
- C.LLVMRunFunctionPassManager(self, fn)
60
- end
61
75
  end
62
76
  end
@@ -1,12 +1,5 @@
1
1
  module LLVM
2
2
  class Type
3
- private_class_method :new
4
-
5
- # @private
6
- def initialize(ptr)
7
- @ptr = ptr
8
- end
9
-
10
3
  # @private
11
4
  def to_ptr
12
5
  @ptr
@@ -34,11 +27,11 @@ module LLVM
34
27
 
35
28
  # Returns the size of the type.
36
29
  def size
37
- Int64.from_ptr(C.LLVMSizeOf(self))
30
+ LLVM::Int64.from_ptr(C.LLVMSizeOf(self))
38
31
  end
39
32
 
40
33
  def align
41
- Int64.from_ptr(C.LLVMAlignOf(self))
34
+ LLVM::Int64.from_ptr(C.LLVMAlignOf(self))
42
35
  end
43
36
 
44
37
  # Returns the type of this types elements (works only for Pointer, Vector, and Array types.)
@@ -64,8 +57,12 @@ module LLVM
64
57
  Type.pointer(self, address_space)
65
58
  end
66
59
 
60
+ # @private
67
61
  def self.from_ptr(ptr)
68
- ptr.null? ? nil : new(ptr)
62
+ return if ptr.null?
63
+ ty = allocate
64
+ ty.instance_variable_set(:@ptr, ptr)
65
+ ty
69
66
  end
70
67
 
71
68
  # Creates an array type of Type with the given size.
@@ -89,7 +86,7 @@ module LLVM
89
86
  arg_types.map! { |ty| LLVM::Type(ty) }
90
87
  arg_types_ptr = FFI::MemoryPointer.new(FFI.type_size(:pointer) * arg_types.size)
91
88
  arg_types_ptr.write_array_of_pointer(arg_types)
92
- from_ptr(C.LLVMFunctionType(LLVM::Type(result_type), arg_types_ptr, arg_types.size, options[:varargs] ? 1 : 0))
89
+ FunctionType.from_ptr(C.LLVMFunctionType(LLVM::Type(result_type), arg_types_ptr, arg_types.size, options[:varargs] ? 1 : 0))
93
90
  end
94
91
 
95
92
  # Creates a struct type with the given array of element types.
@@ -121,9 +118,23 @@ module LLVM
121
118
  C.LLVMRefineType(self, ty)
122
119
  end
123
120
  end
121
+
122
+ class IntType < Type
123
+ def width
124
+ C.LLVMGetIntTypeWidth(self)
125
+ end
126
+ end
127
+
128
+ class FunctionType < Type
129
+ def return_type
130
+ LLVM::Type.from_ptr(C.LLVMGetReturnType(self))
131
+ end
132
+ end
133
+
134
+ module_function
124
135
 
125
136
  # Creates a Type from the given object.
126
- def LLVM.Type(ty)
137
+ def Type(ty)
127
138
  case ty
128
139
  when LLVM::Type then ty
129
140
  else ty.type
@@ -131,32 +142,32 @@ module LLVM
131
142
  end
132
143
 
133
144
  # Shortcut to Type.array.
134
- def LLVM.Array(ty, sz = 0)
145
+ def Array(ty, sz = 0)
135
146
  LLVM::Type.array(ty, sz)
136
147
  end
137
148
 
138
149
  # Shortcut to Type.pointer.
139
- def LLVM.Pointer(ty)
150
+ def Pointer(ty)
140
151
  LLVM::Type.pointer(ty)
141
152
  end
142
153
 
143
154
  # Shortcut to Type.vector.
144
- def LLVM.Vector(ty, sz)
155
+ def Vector(ty, sz)
145
156
  LLVM::Type.vector(ty, sz)
146
157
  end
147
158
 
148
159
  # Shortcut to Type.function.
149
- def LLVM.Function(argtypes, rettype, options = {})
160
+ def Function(argtypes, rettype, options = {})
150
161
  LLVM::Type.function(argtypes, rettype, options)
151
162
  end
152
163
 
153
164
  # Shortcut to Type.struct.
154
- def LLVM.Struct(*elt_types)
165
+ def Struct(*elt_types)
155
166
  LLVM::Type.struct(elt_types, false)
156
167
  end
157
168
 
158
169
  # Shortcut to Type.void.
159
- def LLVM.Void
170
+ def Void
160
171
  LLVM::Type.void
161
172
  end
162
173
  end
@@ -2,14 +2,10 @@ module LLVM
2
2
  class Value
3
3
  # @private
4
4
  def self.from_ptr(ptr)
5
- new(ptr) unless ptr.null?
6
- end
7
-
8
- private_class_method :new
9
-
10
- # @private
11
- def initialize(ptr)
12
- @ptr = ptr
5
+ return if ptr.null?
6
+ val = allocate
7
+ val.instance_variable_set(:@ptr, ptr)
8
+ val
13
9
  end
14
10
 
15
11
  # @private
@@ -26,6 +22,10 @@ module LLVM
26
22
  false
27
23
  end
28
24
  end
25
+
26
+ def hash
27
+ @ptr.address.hash
28
+ end
29
29
 
30
30
  # Checks if the value is equal to other.
31
31
  def eql?(other)
@@ -104,7 +104,7 @@ module LLVM
104
104
  # Build the basic block with the given builder. Creates a new one if nil. Yields the builder.
105
105
  def build(builder = nil)
106
106
  if builder.nil?
107
- builder = Builder.create
107
+ builder = Builder.new
108
108
  islocal = true
109
109
  else
110
110
  islocal = false
@@ -401,7 +401,7 @@ module LLVM
401
401
  eval <<-KLASS
402
402
  class #{name} < ConstantInt
403
403
  def self.type
404
- Type.from_ptr(C.LLVMIntType(#{width}))
404
+ IntType.from_ptr(C.LLVMIntType(#{width}))
405
405
  end
406
406
  end
407
407
  KLASS
@@ -412,7 +412,8 @@ module LLVM
412
412
  end
413
413
 
414
414
  # Native integer type
415
- ::LLVM::Int = const_get("Int#{NATIVE_INT_SIZE}")
415
+ bits = FFI.type_size(:int) * 8
416
+ ::LLVM::Int = const_get("Int#{bits}")
416
417
 
417
418
  # Creates a LLVM Int (subclass of ConstantInt) at the NATIVE_INT_SIZE from a integer (val).
418
419
  def LLVM.Int(val)
@@ -421,6 +422,10 @@ module LLVM
421
422
  when Integer then Int.from_i(val)
422
423
  end
423
424
  end
425
+
426
+ # Boolean values
427
+ ::LLVM::TRUE = ::LLVM::Int1.from_i(-1)
428
+ ::LLVM::FALSE = ::LLVM::Int1.from_i(0)
424
429
 
425
430
  class ConstantReal < Constant
426
431
  # Creates a ConstantReal from a float of Type.
@@ -598,6 +603,10 @@ module LLVM
598
603
  @basic_block_collection ||= BasicBlockCollection.new(self)
599
604
  end
600
605
 
606
+ def type
607
+ FunctionType.from_ptr(C.LLVMTypeOf(self))
608
+ end
609
+
601
610
  # @private
602
611
  class BasicBlockCollection
603
612
  include Enumerable
@@ -661,6 +670,9 @@ module LLVM
661
670
 
662
671
  # Returns a Value representation of the parameter at the given index.
663
672
  def [](i)
673
+ sz = self.size
674
+ i = sz + i if i < 0
675
+ return unless 0 <= i && i < sz
664
676
  Value.from_ptr(C.LLVMGetParam(@fun, i))
665
677
  end
666
678
 
@@ -737,26 +749,21 @@ module LLVM
737
749
  end
738
750
  end
739
751
 
752
+ # @private
740
753
  class Phi < Instruction
741
754
  # Add incoming branches to a phi node by passing an alternating list of
742
755
  # resulting values and BasicBlocks. e.g.
743
756
  # phi.add_incoming(val1, block1, val2, block2, ...)
744
- def add_incoming(*incoming)
745
- vals, blocks = [], []
746
- incoming.each_with_index do |node, i|
747
- (i % 2 == 0 ? vals : blocks) << node
748
- end
749
-
750
- unless vals.size == blocks.size
751
- raise ArgumentError, "Expected vals.size and blocks.size to match"
752
- end
757
+ def add_incoming(incoming)
758
+ blks = incoming.keys
759
+ vals = incoming.values_at(*blks)
760
+ size = incoming.size
753
761
 
754
- size = vals.size
755
762
  FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |vals_ptr|
756
763
  vals_ptr.write_array_of_pointer(vals)
757
- FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |blocks_ptr|
758
- blocks_ptr.write_array_of_pointer(blocks)
759
- C.LLVMAddIncoming(self, vals_ptr, blocks_ptr, vals.size)
764
+ FFI::MemoryPointer.new(FFI.type_size(:pointer) * size) do |blks_ptr|
765
+ blks_ptr.write_array_of_pointer(blks)
766
+ C.LLVMAddIncoming(self, vals_ptr, blks_ptr, vals.size)
760
767
  end
761
768
  end
762
769
 
@@ -764,6 +771,7 @@ module LLVM
764
771
  end
765
772
  end
766
773
 
774
+ # @private
767
775
  class SwitchInst < Instruction
768
776
  # Adds a case to a switch instruction. First the value to match on, then
769
777
  # the basic block.
data/lib/llvm/core.rb CHANGED
@@ -594,4 +594,5 @@ module LLVM
594
594
  require 'llvm/core/value'
595
595
  require 'llvm/core/builder'
596
596
  require 'llvm/core/pass_manager'
597
+ require 'llvm/core/bitcode'
597
598
  end
@@ -52,21 +52,8 @@ module LLVM
52
52
  LLVM::C.LLVMInitializeX86TargetInfo
53
53
  end
54
54
 
55
- class ExecutionEngine
56
- private_class_method :new
57
-
58
- # @private
59
- def initialize(ptr)
60
- @ptr = ptr
61
- end
62
-
63
- # @private
64
- def to_ptr
65
- @ptr
66
- end
67
-
68
- # Create a JIT compiler with an LLVM::Module.
69
- def self.create_jit_compiler(mod, opt_level = 3)
55
+ class JITCompiler
56
+ def initialize(mod, opt_level = 3)
70
57
  FFI::MemoryPointer.new(FFI.type_size(:pointer)) do |ptr|
71
58
  error = FFI::MemoryPointer.new(FFI.type_size(:pointer))
72
59
  status = C.LLVMCreateJITCompilerForModule(ptr, mod, opt_level, error)
@@ -74,7 +61,7 @@ module LLVM
74
61
  message = errorp.read_string unless errorp.null?
75
62
 
76
63
  if status.zero?
77
- return new(ptr.read_pointer)
64
+ @ptr = ptr.read_pointer
78
65
  else
79
66
  C.LLVMDisposeMessage(error)
80
67
  error.autorelease=false
@@ -83,11 +70,18 @@ module LLVM
83
70
  end
84
71
  end
85
72
 
73
+ # @private
74
+ def to_ptr
75
+ @ptr
76
+ end
77
+
86
78
  # Execute the given LLVM::Function with the supplied args (as
87
79
  # GenericValues).
88
80
  def run_function(fun, *args)
89
81
  FFI::MemoryPointer.new(FFI.type_size(:pointer) * args.size) do |args_ptr|
90
- args_ptr.write_array_of_pointer(args.map { |arg| LLVM.GenericValue(arg).to_ptr })
82
+ args_ptr.write_array_of_pointer fun.params.zip(args).map { |p, a|
83
+ a.kind_of?(GenericValue) ? a : LLVM.make_generic_value(p.type, a)
84
+ }
91
85
  return LLVM::GenericValue.from_ptr(
92
86
  C.LLVMRunFunction(self, fun, args.size, args_ptr))
93
87
  end
@@ -100,28 +94,34 @@ module LLVM
100
94
  end
101
95
 
102
96
  class GenericValue
103
- private_class_method :new
104
-
105
- # @private
106
- def initialize(ptr)
107
- @ptr = ptr
108
- end
109
-
110
97
  # @private
111
98
  def to_ptr
112
99
  @ptr
113
100
  end
101
+
102
+ # Casts an FFI::Pointer pointing to a GenericValue to an instance.
103
+ def self.from_ptr(ptr)
104
+ return if ptr.null?
105
+ val = allocate
106
+ val.instance_variable_set(:@ptr, ptr)
107
+ val
108
+ end
114
109
 
115
110
  # Creates a Generic Value from an integer. Type is the size of integer to
116
111
  # create (ex. Int32, Int8, etc.)
117
- def self.from_i(i, type = LLVM::Int, signed = true)
118
- new(C.LLVMCreateGenericValueOfInt(type, i, signed ? 1 : 0))
112
+ def self.from_i(i, options = {})
113
+ type = options.fetch(:type, LLVM::Int)
114
+ signed = options.fetch(:signed, true)
115
+ from_ptr(C.LLVMCreateGenericValueOfInt(type, i, signed ? 1 : 0))
119
116
  end
120
117
 
121
118
  # Creates a Generic Value from a Float.
122
119
  def self.from_f(f)
123
- type = LLVM::Float.type
124
- new(C.LLVMCreateGenericValueOfFloat(type, f))
120
+ from_ptr(C.LLVMCreateGenericValueOfFloat(LLVM::Float, f))
121
+ end
122
+
123
+ def self.from_d(val)
124
+ from_ptr(C.LLVMCreateGenericValueOfFloat(LLVM::Double, val))
125
125
  end
126
126
 
127
127
  # Creates a GenericValue from a Ruby boolean.
@@ -129,9 +129,9 @@ module LLVM
129
129
  from_i(b ? 1 : 0, LLVM::Int1, false)
130
130
  end
131
131
 
132
- # Creates a GenericValue from an FFI::Pointer.
133
- def self.from_ptr(ptr)
134
- new(ptr)
132
+ # Creates a GenericValue from an FFI::Pointer pointing to some arbitrary value.
133
+ def self.from_value_ptr(ptr)
134
+ from_ptr(LLVM::C.LLVMCreateGenericValueOfPointer(ptr))
135
135
  end
136
136
 
137
137
  # Converts a GenericValue to a Ruby Integer.
@@ -148,17 +148,22 @@ module LLVM
148
148
  def to_b
149
149
  to_i(false) != 0
150
150
  end
151
+
152
+ def to_value_ptr
153
+ C.LLVMGenericValueToPointer(self)
154
+ end
151
155
  end
152
156
 
153
- # Creates a GenericValue from an object (GenericValue, Integer, Float, true,
154
- # false).
155
- def LLVM.GenericValue(val)
156
- case val
157
- when GenericValue then val
158
- when ::Integer then GenericValue.from_i(val)
159
- when ::Float then GenericValue.from_f(val)
160
- when ::TrueClass then GenericValue.from_b(true)
161
- when ::FalseClass then GenericValue.from_b(false)
157
+ # @private
158
+ def make_generic_value(ty, val)
159
+ case ty.kind
160
+ when :double then GenericValue.from_d(val)
161
+ when :float then GenericValue.from_f(val)
162
+ when :pointer then GenericValue.from_value_ptr(val)
163
+ when :integer then GenericValue.from_i(val, :type => ty)
164
+ else
165
+ raise "Unsupported type #{ty.kind}."
162
166
  end
163
167
  end
168
+ module_function :make_generic_value
164
169
  end
@@ -0,0 +1,22 @@
1
+ module LLVM
2
+ module Support
3
+ # @private
4
+ module C
5
+ extend FFI::Library
6
+ support_lib = File.expand_path(
7
+ File.join(
8
+ File.dirname(__FILE__),
9
+ '../',
10
+ FFI.map_library_name('RubyLLVMSupport-2.9.2')))
11
+ ffi_lib [support_lib]
12
+ attach_function :LLVMLoadLibraryPermanently, [:string], :int
13
+ end
14
+ end
15
+
16
+ def load_library(libname)
17
+ Support::C.LLVMLoadLibraryPermanently(libname)
18
+ nil
19
+ end
20
+
21
+ module_function :load_library
22
+ end
@@ -6,6 +6,7 @@ module LLVM
6
6
  # @private
7
7
  module C
8
8
  attach_function :LLVMAddGlobalDCEPass, [:pointer], :void
9
+ attach_function :LLVMAddFunctionInliningPass, [:pointer], :void
9
10
  end
10
11
 
11
12
  class PassManager
@@ -13,5 +14,10 @@ module LLVM
13
14
  def gdce!
14
15
  C.LLVMAddGlobalDCEPass(self)
15
16
  end
17
+
18
+ # @LLVMpass inline
19
+ def inline!
20
+ C.LLVMAddFunctionInliningPass(self)
21
+ end
16
22
  end
17
23
  end
@@ -0,0 +1,4 @@
1
+ module LLVM
2
+ LLVM_VERSION = "2.9"
3
+ RUBY_LLVM_VERSION = "2.9.3"
4
+ end
data/lib/llvm.rb CHANGED
@@ -1,18 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'ffi'
3
3
 
4
+ require 'llvm/support'
5
+
4
6
  module LLVM
5
7
  # @private
6
8
  module C
7
9
  extend ::FFI::Library
8
-
9
- # load required libraries
10
- ffi_lib ['LLVM-2.9', 'libLLVM-2.9']
11
- end
12
-
13
- NATIVE_INT_SIZE = case FFI::Platform::ARCH
14
- when "x86_64" then 64
15
- # PPC, other arches?
16
- else 32
10
+ ffi_lib ['LLVM-2.9']
17
11
  end
18
12
  end
@@ -0,0 +1,38 @@
1
+ require "test_helper"
2
+
3
+ class ArrayTestCase < Test::Unit::TestCase
4
+
5
+ def setup
6
+ LLVM.init_x86
7
+ end
8
+
9
+ def test_constant_array_from_size
10
+ array = LLVM::ConstantArray.const(LLVM::Int, 2) { |i| LLVM::Int(i) }
11
+ assert_instance_of LLVM::ConstantArray, array
12
+ assert_equal 2, array.operands.size
13
+ end
14
+
15
+ def test_constant_array_from_array
16
+ array = LLVM::ConstantArray.const(LLVM::Int, [LLVM::Int(0), LLVM::Int(1)])
17
+ assert_instance_of LLVM::ConstantArray, array
18
+ assert_equal 2, array.operands.size
19
+ end
20
+
21
+ def test_array_values
22
+ assert_equal 2 + 3, run_array_values(2, 3).to_i
23
+ end
24
+
25
+ def run_array_values(value1, value2)
26
+ run_function([LLVM::Int, LLVM::Int], [value1, value2], LLVM::Int) do |builder, function, *arguments|
27
+ entry = function.basic_blocks.append
28
+ builder.position_at_end(entry)
29
+ pointer = builder.alloca(LLVM::Array(LLVM::Int, 2))
30
+ array = builder.load(pointer)
31
+ array = builder.insert_value(array, arguments.first, 0)
32
+ array = builder.insert_value(array, arguments.last, 1)
33
+ builder.ret(builder.add(builder.extract_value(array, 0),
34
+ builder.extract_value(array, 1)))
35
+ end
36
+ end
37
+
38
+ end