ruby-llvm-next 10.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +30 -0
  3. data/README.md +67 -0
  4. data/ext/ruby-llvm-support/Rakefile +110 -0
  5. data/ext/ruby-llvm-support/support.cpp +32 -0
  6. data/lib/llvm.rb +29 -0
  7. data/lib/llvm/analysis.rb +49 -0
  8. data/lib/llvm/analysis_ffi.rb +77 -0
  9. data/lib/llvm/config.rb +10 -0
  10. data/lib/llvm/core.rb +97 -0
  11. data/lib/llvm/core/bitcode.rb +84 -0
  12. data/lib/llvm/core/bitcode_ffi.rb +132 -0
  13. data/lib/llvm/core/builder.rb +944 -0
  14. data/lib/llvm/core/context.rb +24 -0
  15. data/lib/llvm/core/module.rb +240 -0
  16. data/lib/llvm/core/pass_manager.rb +80 -0
  17. data/lib/llvm/core/type.rb +210 -0
  18. data/lib/llvm/core/value.rb +1005 -0
  19. data/lib/llvm/core_ffi.rb +6021 -0
  20. data/lib/llvm/execution_engine.rb +323 -0
  21. data/lib/llvm/execution_engine_ffi.rb +421 -0
  22. data/lib/llvm/linker.rb +16 -0
  23. data/lib/llvm/linker_ffi.rb +44 -0
  24. data/lib/llvm/support.rb +38 -0
  25. data/lib/llvm/target.rb +318 -0
  26. data/lib/llvm/target_ffi.rb +628 -0
  27. data/lib/llvm/transforms/builder.rb +107 -0
  28. data/lib/llvm/transforms/builder_ffi.rb +117 -0
  29. data/lib/llvm/transforms/ipo.rb +78 -0
  30. data/lib/llvm/transforms/ipo_ffi.rb +127 -0
  31. data/lib/llvm/transforms/scalar.rb +152 -0
  32. data/lib/llvm/transforms/scalar_ffi.rb +344 -0
  33. data/lib/llvm/transforms/vectorize.rb +22 -0
  34. data/lib/llvm/transforms/vectorize_ffi.rb +38 -0
  35. data/lib/llvm/version.rb +5 -0
  36. data/test/array_test.rb +38 -0
  37. data/test/basic_block_test.rb +87 -0
  38. data/test/binary_operations_test.rb +58 -0
  39. data/test/bitcode_test.rb +24 -0
  40. data/test/branch_test.rb +57 -0
  41. data/test/call_test.rb +82 -0
  42. data/test/comparisons_test.rb +66 -0
  43. data/test/conversions_test.rb +92 -0
  44. data/test/double_test.rb +34 -0
  45. data/test/equality_test.rb +89 -0
  46. data/test/function_test.rb +100 -0
  47. data/test/generic_value_test.rb +22 -0
  48. data/test/instruction_test.rb +30 -0
  49. data/test/ipo_test.rb +53 -0
  50. data/test/linker_test.rb +37 -0
  51. data/test/mcjit_test.rb +94 -0
  52. data/test/memory_access_test.rb +38 -0
  53. data/test/module_test.rb +93 -0
  54. data/test/parameter_collection_test.rb +28 -0
  55. data/test/pass_manager_builder_test.rb +53 -0
  56. data/test/phi_test.rb +33 -0
  57. data/test/select_test.rb +22 -0
  58. data/test/struct_test.rb +98 -0
  59. data/test/target_test.rb +113 -0
  60. data/test/test_helper.rb +62 -0
  61. data/test/type_test.rb +15 -0
  62. data/test/vector_test.rb +64 -0
  63. metadata +240 -0
@@ -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
@@ -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
@@ -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
@@ -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