ruby-llvm 2.9.1 → 2.9.3
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.
- data/README.rdoc +3 -2
- data/ext/ruby-llvm-support/Rakefile +18 -0
- data/ext/ruby-llvm-support/support.cpp +12 -0
- data/lib/llvm/analysis.rb +22 -3
- data/lib/llvm/core/bitcode.rb +88 -0
- data/lib/llvm/core/builder.rb +401 -81
- data/lib/llvm/core/context.rb +5 -13
- data/lib/llvm/core/module.rb +6 -11
- data/lib/llvm/core/pass_manager.rb +27 -13
- data/lib/llvm/core/type.rb +29 -18
- data/lib/llvm/core/value.rb +32 -24
- data/lib/llvm/core.rb +1 -0
- data/lib/llvm/execution_engine.rb +45 -40
- data/lib/llvm/support.rb +22 -0
- data/lib/llvm/transforms/ipo.rb +6 -0
- data/lib/llvm/version.rb +4 -0
- data/lib/llvm.rb +3 -9
- data/test/array_test.rb +38 -0
- data/test/basic_block_test.rb +88 -0
- data/test/basic_test.rb +11 -0
- data/test/binary_operations_test.rb +58 -0
- data/test/bitcode_test.rb +25 -0
- data/test/branch_test.rb +57 -0
- data/test/call_test.rb +82 -0
- data/test/comparisons_test.rb +66 -0
- data/test/conversions_test.rb +86 -0
- data/test/double_test.rb +33 -0
- data/test/equality_test.rb +91 -0
- data/test/generic_value_test.rb +22 -0
- data/test/instruction_test.rb +32 -0
- data/test/ipo_test.rb +53 -0
- data/test/memory_access_test.rb +38 -0
- data/test/module_test.rb +21 -0
- data/test/parameter_collection_test.rb +28 -0
- data/test/phi_test.rb +33 -0
- data/test/select_test.rb +22 -0
- data/test/struct_test.rb +75 -0
- data/test/test_helper.rb +50 -0
- data/test/type_test.rb +15 -0
- data/test/vector_test.rb +64 -0
- metadata +116 -39
data/lib/llvm/core/context.rb
CHANGED
@@ -1,27 +1,19 @@
|
|
1
1
|
module LLVM
|
2
2
|
class Context
|
3
|
-
|
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)
|
data/lib/llvm/core/module.rb
CHANGED
@@ -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?
|
5
|
+
return if ptr.null?
|
6
|
+
mod = allocate
|
7
|
+
mod.instance_variable_set(:@ptr, ptr)
|
8
|
+
mod
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
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
|
-
|
24
|
-
|
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
|
data/lib/llvm/core/type.rb
CHANGED
@@ -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?
|
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
|
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
|
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
|
150
|
+
def Pointer(ty)
|
140
151
|
LLVM::Type.pointer(ty)
|
141
152
|
end
|
142
153
|
|
143
154
|
# Shortcut to Type.vector.
|
144
|
-
def
|
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
|
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
|
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
|
170
|
+
def Void
|
160
171
|
LLVM::Type.void
|
161
172
|
end
|
162
173
|
end
|
data/lib/llvm/core/value.rb
CHANGED
@@ -2,14 +2,10 @@ module LLVM
|
|
2
2
|
class Value
|
3
3
|
# @private
|
4
4
|
def self.from_ptr(ptr)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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.
|
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
|
-
|
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
|
-
|
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(
|
745
|
-
|
746
|
-
incoming.
|
747
|
-
|
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 |
|
758
|
-
|
759
|
-
C.LLVMAddIncoming(self, vals_ptr,
|
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
@@ -52,21 +52,8 @@ module LLVM
|
|
52
52
|
LLVM::C.LLVMInitializeX86TargetInfo
|
53
53
|
end
|
54
54
|
|
55
|
-
class
|
56
|
-
|
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
|
-
|
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 { |
|
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,
|
118
|
-
|
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
|
-
|
124
|
-
|
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.
|
134
|
-
|
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
|
-
#
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
when
|
158
|
-
when
|
159
|
-
when
|
160
|
-
|
161
|
-
|
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
|
data/lib/llvm/support.rb
ADDED
@@ -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
|
data/lib/llvm/transforms/ipo.rb
CHANGED
@@ -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
|
data/lib/llvm/version.rb
ADDED
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
|
data/test/array_test.rb
ADDED
@@ -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
|