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