ruby-llvm-next 10.0.0
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.
- checksums.yaml +7 -0
- data/LICENSE +30 -0
- data/README.md +67 -0
- data/ext/ruby-llvm-support/Rakefile +110 -0
- data/ext/ruby-llvm-support/support.cpp +32 -0
- data/lib/llvm.rb +29 -0
- data/lib/llvm/analysis.rb +49 -0
- data/lib/llvm/analysis_ffi.rb +77 -0
- data/lib/llvm/config.rb +10 -0
- data/lib/llvm/core.rb +97 -0
- data/lib/llvm/core/bitcode.rb +84 -0
- data/lib/llvm/core/bitcode_ffi.rb +132 -0
- data/lib/llvm/core/builder.rb +944 -0
- data/lib/llvm/core/context.rb +24 -0
- data/lib/llvm/core/module.rb +240 -0
- data/lib/llvm/core/pass_manager.rb +80 -0
- data/lib/llvm/core/type.rb +210 -0
- data/lib/llvm/core/value.rb +1005 -0
- data/lib/llvm/core_ffi.rb +6021 -0
- data/lib/llvm/execution_engine.rb +323 -0
- data/lib/llvm/execution_engine_ffi.rb +421 -0
- data/lib/llvm/linker.rb +16 -0
- data/lib/llvm/linker_ffi.rb +44 -0
- data/lib/llvm/support.rb +38 -0
- data/lib/llvm/target.rb +318 -0
- data/lib/llvm/target_ffi.rb +628 -0
- data/lib/llvm/transforms/builder.rb +107 -0
- data/lib/llvm/transforms/builder_ffi.rb +117 -0
- data/lib/llvm/transforms/ipo.rb +78 -0
- data/lib/llvm/transforms/ipo_ffi.rb +127 -0
- data/lib/llvm/transforms/scalar.rb +152 -0
- data/lib/llvm/transforms/scalar_ffi.rb +344 -0
- data/lib/llvm/transforms/vectorize.rb +22 -0
- data/lib/llvm/transforms/vectorize_ffi.rb +38 -0
- data/lib/llvm/version.rb +5 -0
- data/test/array_test.rb +38 -0
- data/test/basic_block_test.rb +87 -0
- data/test/binary_operations_test.rb +58 -0
- data/test/bitcode_test.rb +24 -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 +92 -0
- data/test/double_test.rb +34 -0
- data/test/equality_test.rb +89 -0
- data/test/function_test.rb +100 -0
- data/test/generic_value_test.rb +22 -0
- data/test/instruction_test.rb +30 -0
- data/test/ipo_test.rb +53 -0
- data/test/linker_test.rb +37 -0
- data/test/mcjit_test.rb +94 -0
- data/test/memory_access_test.rb +38 -0
- data/test/module_test.rb +93 -0
- data/test/parameter_collection_test.rb +28 -0
- data/test/pass_manager_builder_test.rb +53 -0
- data/test/phi_test.rb +33 -0
- data/test/select_test.rb +22 -0
- data/test/struct_test.rb +98 -0
- data/test/target_test.rb +113 -0
- data/test/test_helper.rb +62 -0
- data/test/type_test.rb +15 -0
- data/test/vector_test.rb +64 -0
- metadata +240 -0
data/test/double_test.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DoubleTestCase < Minitest::Test
|
4
|
+
def setup
|
5
|
+
LLVM.init_jit
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_double
|
9
|
+
mod = LLVM::Module.new("Double Test")
|
10
|
+
mod.functions.add(:sin, [LLVM::Double], LLVM::Double)
|
11
|
+
|
12
|
+
builder = LLVM::Builder.new
|
13
|
+
|
14
|
+
mod.functions.add('test', [LLVM::Double], LLVM::Double) do |fun, p0|
|
15
|
+
p0.name = 'x'
|
16
|
+
|
17
|
+
bb = fun.basic_blocks.append
|
18
|
+
builder.position_at_end(bb)
|
19
|
+
|
20
|
+
builder.ret(builder.fadd(p0, LLVM::Double(1.0)))
|
21
|
+
end
|
22
|
+
|
23
|
+
engine = LLVM::MCJITCompiler.new(mod)
|
24
|
+
|
25
|
+
arg = 5.0
|
26
|
+
result = engine.run_function(mod.functions["test"], arg)
|
27
|
+
assert_equal arg + 1, result.to_f(LLVM::Double)
|
28
|
+
|
29
|
+
# TODO: fix this
|
30
|
+
# assert_in_delta(Math.sin(1.0),
|
31
|
+
# engine.run_function(mod.functions["sin"], 1.0).to_f(LLVM::Double),
|
32
|
+
# 1e-10)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "llvm/core"
|
3
|
+
|
4
|
+
class EqualityTestCase < Minitest::Test
|
5
|
+
def setup
|
6
|
+
LLVM.init_jit
|
7
|
+
end
|
8
|
+
|
9
|
+
class MyModule < LLVM::Module; end
|
10
|
+
class MyInt < LLVM::Int32; end
|
11
|
+
class MyType < LLVM::Type; end
|
12
|
+
class MyFunction < LLVM::Function; end
|
13
|
+
|
14
|
+
def assert_equalities(options)
|
15
|
+
map = {
|
16
|
+
:equal => method(:assert_equal),
|
17
|
+
:not_equal => lambda {|n, m, name| assert n != m, name },
|
18
|
+
:same => method(:assert_same),
|
19
|
+
:not_same => lambda {|n, m, name| assert !n.equal?(m), name },
|
20
|
+
:eql => lambda {|n, m, name| assert n.eql?(m), name },
|
21
|
+
:not_eql => lambda {|n, m, name| assert !n.eql?(m), name },
|
22
|
+
}
|
23
|
+
|
24
|
+
map.each do |name, callable|
|
25
|
+
options[name].combination(2).each do |n, m|
|
26
|
+
callable.call(n, m, name.to_s)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_int_value
|
32
|
+
int1 = LLVM::Int32.from_i(1)
|
33
|
+
int2 = LLVM::Int32.from_ptr(int1.to_ptr)
|
34
|
+
int3 = LLVM::Int32.from_i(2)
|
35
|
+
int4 = MyInt.from_ptr(int1.to_ptr)
|
36
|
+
|
37
|
+
assert_equalities :equal => [int1, int2, int4],
|
38
|
+
:not_equal => [int1, int3],
|
39
|
+
:same => [int1, int1],
|
40
|
+
:not_same => [int1, int2, int3, int4],
|
41
|
+
:eql => [int1, int2],
|
42
|
+
:not_eql => [int1, int3]
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_module
|
46
|
+
mod1 = LLVM::Module.new('test')
|
47
|
+
mod2 = LLVM::Module.from_ptr(mod1.to_ptr)
|
48
|
+
mod3 = LLVM::Module.new('dummy')
|
49
|
+
mod4 = MyModule.from_ptr(mod1.to_ptr)
|
50
|
+
|
51
|
+
assert_equalities :equal => [mod1, mod2, mod4],
|
52
|
+
:not_equal => [mod1, mod3],
|
53
|
+
:same => [mod1, mod1],
|
54
|
+
:not_same => [mod1, mod2, mod3, mod4],
|
55
|
+
:eql => [mod1, mod2],
|
56
|
+
:not_eql => [mod1, mod3]
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_type
|
60
|
+
type1 = LLVM::Float.type
|
61
|
+
type2 = LLVM::Type.from_ptr(type1.to_ptr, nil)
|
62
|
+
type3 = LLVM::Double.type
|
63
|
+
type4 = MyType.from_ptr(type1.to_ptr, :mytype)
|
64
|
+
|
65
|
+
assert_equalities :equal => [type1, type2, type4],
|
66
|
+
:not_equal => [type1, type3],
|
67
|
+
:same => [type1, type1],
|
68
|
+
:not_same => [type1, type2, type3, type4],
|
69
|
+
:eql => [type1, type2],
|
70
|
+
:not_eql => [type1, type3]
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_function
|
74
|
+
mod = LLVM::Module.new('test')
|
75
|
+
|
76
|
+
fn1 = mod.functions.add('test1', [], LLVM.Void)
|
77
|
+
fn2 = LLVM::Function.from_ptr(fn1.to_ptr)
|
78
|
+
fn3 = mod.functions.add('test2', [], LLVM.Void)
|
79
|
+
fn4 = MyFunction.from_ptr(fn1.to_ptr)
|
80
|
+
|
81
|
+
assert_equalities :equal => [fn1, fn2, fn4],
|
82
|
+
:not_equal => [fn1, fn3],
|
83
|
+
:same => [fn1, fn1],
|
84
|
+
:not_same => [fn1, fn2, fn3, fn4],
|
85
|
+
:eql => [fn1, fn2],
|
86
|
+
:not_eql => [fn1, fn3]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "llvm/core"
|
3
|
+
|
4
|
+
|
5
|
+
def with_function(arguments, retty, &block)
|
6
|
+
mod = LLVM::Module.new('test')
|
7
|
+
fun = mod.functions.add('fun', arguments, retty)
|
8
|
+
block.yield(fun)
|
9
|
+
mod.dispose
|
10
|
+
end
|
11
|
+
|
12
|
+
class FunctionTest < Minitest::Test
|
13
|
+
|
14
|
+
def test_type
|
15
|
+
with_function [], LLVM.Void do |fun|
|
16
|
+
type = fun.type
|
17
|
+
|
18
|
+
assert_instance_of LLVM::Type, type
|
19
|
+
assert_equal :pointer, type.kind
|
20
|
+
assert_equal :function, type.element_type.kind
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_function_type
|
25
|
+
with_function [], LLVM.Void do |fun|
|
26
|
+
type = fun.function_type
|
27
|
+
|
28
|
+
assert_instance_of LLVM::FunctionType, type
|
29
|
+
assert_equal :function, type.kind
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def helper_test_attribute(name)
|
34
|
+
with_function [], LLVM.Void do |fun|
|
35
|
+
assert_equal 0, fun.attribute_count
|
36
|
+
assert_equal [], fun.attributes
|
37
|
+
|
38
|
+
fun.add_attribute(name)
|
39
|
+
assert_equal 1, fun.attribute_count
|
40
|
+
assert_equal [33], fun.attributes
|
41
|
+
|
42
|
+
assert_equal false, fun.verify
|
43
|
+
|
44
|
+
fun.remove_attribute(name)
|
45
|
+
assert_equal 0, fun.attribute_count
|
46
|
+
assert_equal [], fun.attributes
|
47
|
+
|
48
|
+
assert_equal false, fun.verify
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_add_attribute_old_name
|
53
|
+
helper_test_attribute(:no_unwind_attribute)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_add_attribute_new_name
|
57
|
+
helper_test_attribute(:nounwind)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
class FunctionTypeTest < Minitest::Test
|
63
|
+
|
64
|
+
def test_return_type
|
65
|
+
with_function [], LLVM.Void do |fun|
|
66
|
+
type = fun.function_type
|
67
|
+
assert_equal LLVM.Void, type.return_type
|
68
|
+
end
|
69
|
+
|
70
|
+
with_function [], LLVM::Int32 do |fun|
|
71
|
+
retty = fun.function_type.return_type
|
72
|
+
|
73
|
+
assert_kind_of LLVM::IntType, retty
|
74
|
+
assert_equal 32, retty.width
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_argument_types
|
79
|
+
with_function [], LLVM.Void do |fun|
|
80
|
+
types = fun.function_type.argument_types
|
81
|
+
assert_equal [], types
|
82
|
+
end
|
83
|
+
|
84
|
+
with_function [LLVM::Int32], LLVM.Void do |fun|
|
85
|
+
types = fun.function_type.argument_types
|
86
|
+
assert_equal 1, types.size
|
87
|
+
a1 = types[0]
|
88
|
+
assert_kind_of LLVM::IntType, a1
|
89
|
+
assert_equal 32, a1.width
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_vararg
|
94
|
+
with_function [], LLVM.Void do |fun|
|
95
|
+
type = fun.function_type
|
96
|
+
assert !type.vararg?, 'should be false'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class GenericValueTestCase < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
LLVM.init_jit
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_from_i
|
10
|
+
assert_equal 2, LLVM::GenericValue.from_i(2).to_i
|
11
|
+
assert_equal 2, LLVM::GenericValue.from_i(2.2).to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_from_float
|
15
|
+
assert_in_delta 2.2, LLVM::GenericValue.from_f(2.2).to_f, 1e-6
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_from_double
|
19
|
+
assert_in_delta 2.2, LLVM::GenericValue.from_d(2.2).to_f(LLVM::Double), 1e-6
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class InstructionTestCase < Minitest::Test
|
4
|
+
def setup
|
5
|
+
LLVM.init_jit
|
6
|
+
@module = LLVM::Module.new("InstructionTestCase")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_instruction
|
10
|
+
fn = @module.functions.add("test_instruction", [LLVM::Double], LLVM::Double) do |fn, arg|
|
11
|
+
fn.basic_blocks.append.build do |builder|
|
12
|
+
builder.ret(
|
13
|
+
builder.fadd(arg, LLVM.Double(3.0)))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
entry = fn.basic_blocks.entry
|
18
|
+
|
19
|
+
inst1 = entry.instructions.first
|
20
|
+
inst2 = entry.instructions.last
|
21
|
+
|
22
|
+
assert_kind_of LLVM::Instruction, inst1
|
23
|
+
assert_kind_of LLVM::Instruction, inst2
|
24
|
+
|
25
|
+
assert_equal inst2, inst1.next
|
26
|
+
assert_equal inst1, inst2.previous
|
27
|
+
assert_equal entry, inst1.parent
|
28
|
+
assert_equal entry, inst2.parent
|
29
|
+
end
|
30
|
+
end
|
data/test/ipo_test.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "llvm/core"
|
3
|
+
require 'llvm/transforms/ipo'
|
4
|
+
require 'llvm/core/pass_manager'
|
5
|
+
|
6
|
+
class IPOTestCase < Minitest::Test
|
7
|
+
|
8
|
+
def setup
|
9
|
+
LLVM.init_jit
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_gdce
|
13
|
+
mod = LLVM::Module.new('test')
|
14
|
+
|
15
|
+
fn1 = mod.functions.add("fn1", [], LLVM.Void) do |fn|
|
16
|
+
fn.linkage = :internal
|
17
|
+
fn.basic_blocks.append.build do |builder|
|
18
|
+
builder.ret_void
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
fn2 = mod.functions.add("fn2", [], LLVM.Void) do |fn|
|
23
|
+
fn.linkage = :internal
|
24
|
+
fn.basic_blocks.append.build do |builder|
|
25
|
+
builder.ret_void
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
main = mod.functions.add("main", [], LLVM.Void) do |fn|
|
30
|
+
fn.basic_blocks.append.build do |builder|
|
31
|
+
builder.call(fn1)
|
32
|
+
builder.ret_void
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
fns = mod.functions.to_a
|
37
|
+
assert fns.include?(fn1)
|
38
|
+
assert fns.include?(fn2)
|
39
|
+
assert fns.include?(main)
|
40
|
+
|
41
|
+
# optimize
|
42
|
+
engine = LLVM::MCJITCompiler.new(mod)
|
43
|
+
passm = LLVM::PassManager.new(engine)
|
44
|
+
|
45
|
+
passm.gdce!
|
46
|
+
passm.run(mod)
|
47
|
+
|
48
|
+
fns = mod.functions.to_a
|
49
|
+
assert fns.include?(fn1)
|
50
|
+
assert !fns.include?(fn2), 'fn2 should be eliminated'
|
51
|
+
assert fns.include?(main)
|
52
|
+
end
|
53
|
+
end
|
data/test/linker_test.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'llvm/core'
|
3
|
+
require 'llvm/linker'
|
4
|
+
|
5
|
+
class LinkerTestCase < Minitest::Test
|
6
|
+
def setup
|
7
|
+
LLVM.init_jit
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_modules
|
11
|
+
@mod1 = define_module('mod1') do |mod|
|
12
|
+
mod1calc = mod.functions.add("calc", [], LLVM::Int32)
|
13
|
+
|
14
|
+
mod.functions.add("main", [], LLVM::Int32) do |fn|
|
15
|
+
fn.basic_blocks.append.build do |builder|
|
16
|
+
val = builder.call(mod1calc)
|
17
|
+
builder.ret val
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
@mod2 = define_module('mod2') do |mod|
|
23
|
+
mod.functions.add("calc", [], LLVM::Int32) do |fn|
|
24
|
+
fn.basic_blocks.append.build do |builder|
|
25
|
+
builder.ret LLVM::Int32.from_i(42)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_link_into
|
32
|
+
create_modules
|
33
|
+
@mod2.link_into(@mod1)
|
34
|
+
|
35
|
+
assert_equal 42, run_function_on_module(@mod1, 'main').to_i
|
36
|
+
end
|
37
|
+
end
|
data/test/mcjit_test.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class MCJITTestCase < Minitest::Test
|
4
|
+
def setup
|
5
|
+
LLVM.init_jit(true)
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_square_function_module
|
9
|
+
LLVM::Module.new('square').tap do |mod|
|
10
|
+
mod.functions.add(:square, [LLVM::Int], LLVM::Int) do |fun, x|
|
11
|
+
fun.basic_blocks.append.build do |builder|
|
12
|
+
n = builder.mul(x, x)
|
13
|
+
builder.ret(n)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
mod.verify!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_simple_function
|
22
|
+
mod = create_square_function_module
|
23
|
+
|
24
|
+
engine = LLVM::MCJITCompiler.new(mod, :opt_level => 0)
|
25
|
+
|
26
|
+
result = engine.run_function(mod.functions['square'], 5)
|
27
|
+
assert_equal 25, result.to_i
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_functions_named
|
31
|
+
mod = LLVM::Module.new('foo').tap do |mod|
|
32
|
+
mod.functions.add(:foo, [], LLVM::Int)
|
33
|
+
mod.verify!
|
34
|
+
end
|
35
|
+
|
36
|
+
engine = LLVM::MCJITCompiler.new(mod, :opt_level => 0)
|
37
|
+
|
38
|
+
['foo', :foo].each do |name|
|
39
|
+
engine.functions[name].tap do |fun|
|
40
|
+
assert fun, "function named #{name.inspect}"
|
41
|
+
assert_equal 'foo', fun.name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_add_module
|
47
|
+
main_mod = LLVM::Module.new('main')
|
48
|
+
|
49
|
+
main_mod.functions.add(:square, [LLVM::Int], LLVM::Int) do |square|
|
50
|
+
main_mod.functions.add(:call_square, [], LLVM::Int) do |call_square|
|
51
|
+
call_square.basic_blocks.append.build do |builder|
|
52
|
+
n = builder.call(square, LLVM::Int(5))
|
53
|
+
builder.ret(n)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
main_mod.verify!
|
59
|
+
|
60
|
+
engine = LLVM::MCJITCompiler.new(main_mod, :opt_level => 0)
|
61
|
+
engine.modules << create_square_function_module
|
62
|
+
|
63
|
+
result = engine.run_function(main_mod.functions['call_square'])
|
64
|
+
assert_equal 25, result.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_remove_module
|
68
|
+
mod1 = LLVM::Module.new('foo')
|
69
|
+
mod2 = LLVM::Module.new('bar')
|
70
|
+
|
71
|
+
foo = mod1.functions.add(:foo, [], LLVM::Int)
|
72
|
+
bar = mod2.functions.add(:bar, [], LLVM::Int)
|
73
|
+
|
74
|
+
engine = LLVM::MCJITCompiler.new(mod1, :opt_level => 0)
|
75
|
+
|
76
|
+
(engine.modules << mod2).tap do |ret|
|
77
|
+
assert_equal engine.modules, ret, '#<< returns self'
|
78
|
+
end
|
79
|
+
|
80
|
+
refute_nil engine.functions[:bar]
|
81
|
+
engine.modules.delete(mod2).tap do |ret|
|
82
|
+
assert_instance_of LLVM::Module, ret, '#delete returns module'
|
83
|
+
assert_equal mod2, ret
|
84
|
+
end
|
85
|
+
assert_nil engine.functions[:bar]
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_accessors
|
89
|
+
main_mod = LLVM::Module.new('main')
|
90
|
+
engine = LLVM::MCJITCompiler.new(main_mod, :opt_level => 0)
|
91
|
+
assert_match(/^e-/, engine.data_layout.to_s)
|
92
|
+
assert_match(/gnu/, engine.target_machine.triple)
|
93
|
+
end
|
94
|
+
end
|