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.
- 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
|