ruby-llvm 3.5.0 → 13.0.1

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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +21 -4
  3. data/ext/ruby-llvm-support/Rakefile +17 -6
  4. data/lib/llvm/analysis.rb +2 -0
  5. data/lib/llvm/analysis_ffi.rb +27 -28
  6. data/lib/llvm/config.rb +4 -4
  7. data/lib/llvm/core/bitcode.rb +12 -10
  8. data/lib/llvm/core/bitcode_ffi.rb +89 -65
  9. data/lib/llvm/core/builder.rb +4 -3
  10. data/lib/llvm/core/context.rb +3 -1
  11. data/lib/llvm/core/module.rb +2 -0
  12. data/lib/llvm/core/pass_manager.rb +6 -2
  13. data/lib/llvm/core/type.rb +9 -2
  14. data/lib/llvm/core/value.rb +154 -24
  15. data/lib/llvm/core.rb +47 -2
  16. data/lib/llvm/core_ffi.rb +3863 -3730
  17. data/lib/llvm/execution_engine.rb +39 -35
  18. data/lib/llvm/execution_engine_ffi.rb +238 -276
  19. data/lib/llvm/linker.rb +3 -14
  20. data/lib/llvm/linker_ffi.rb +22 -26
  21. data/lib/llvm/support.rb +2 -0
  22. data/lib/llvm/target.rb +11 -15
  23. data/lib/llvm/target_ffi.rb +301 -293
  24. data/lib/llvm/transforms/builder.rb +3 -1
  25. data/lib/llvm/transforms/builder_ffi.rb +57 -58
  26. data/lib/llvm/transforms/ipo.rb +3 -1
  27. data/lib/llvm/transforms/ipo_ffi.rb +59 -60
  28. data/lib/llvm/transforms/scalar.rb +12 -0
  29. data/lib/llvm/transforms/scalar_ffi.rb +199 -143
  30. data/lib/llvm/transforms/vectorize.rb +2 -0
  31. data/lib/llvm/transforms/vectorize_ffi.rb +15 -16
  32. data/lib/llvm/version.rb +5 -2
  33. data/lib/llvm.rb +2 -0
  34. data/test/array_test.rb +2 -0
  35. data/test/basic_block_test.rb +2 -1
  36. data/test/binary_operations_test.rb +2 -0
  37. data/test/bitcode_test.rb +3 -2
  38. data/test/branch_test.rb +2 -0
  39. data/test/call_test.rb +3 -1
  40. data/test/comparisons_test.rb +2 -0
  41. data/test/conversions_test.rb +2 -0
  42. data/test/double_test.rb +10 -7
  43. data/test/equality_test.rb +4 -4
  44. data/test/function_test.rb +29 -0
  45. data/test/generic_value_test.rb +3 -1
  46. data/test/instruction_test.rb +2 -2
  47. data/test/integer_test.rb +28 -0
  48. data/test/ipo_test.rb +3 -1
  49. data/test/linker_test.rb +2 -9
  50. data/test/mcjit_test.rb +11 -3
  51. data/test/memory_access_test.rb +2 -0
  52. data/test/module_test.rb +18 -1
  53. data/test/parameter_collection_test.rb +2 -0
  54. data/test/pass_manager_builder_test.rb +22 -2
  55. data/test/phi_test.rb +2 -0
  56. data/test/select_test.rb +2 -0
  57. data/test/struct_test.rb +2 -0
  58. data/test/target_test.rb +16 -20
  59. data/test/test_helper.rb +6 -1
  60. data/test/type_test.rb +47 -0
  61. data/test/vector_test.rb +2 -0
  62. metadata +105 -40
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
  require "llvm/core"
3
5
 
@@ -14,9 +16,9 @@ class EqualityTestCase < Minitest::Test
14
16
  def assert_equalities(options)
15
17
  map = {
16
18
  :equal => method(:assert_equal),
17
- :not_equal => lambda {|n, m, name| assert n != m, name },
19
+ :not_equal => lambda {|n, m, name| assert n != m, name },
18
20
  :same => method(:assert_same),
19
- :not_same => lambda {|n, m, name| assert !n.equal?(m), name },
21
+ :not_same => lambda {|n, m, name| assert !n.equal?(m), name },
20
22
  :eql => lambda {|n, m, name| assert n.eql?(m), name },
21
23
  :not_eql => lambda {|n, m, name| assert !n.eql?(m), name },
22
24
  }
@@ -26,7 +28,6 @@ class EqualityTestCase < Minitest::Test
26
28
  callable.call(n, m, name.to_s)
27
29
  end
28
30
  end
29
-
30
31
  end
31
32
 
32
33
  def test_int_value
@@ -88,4 +89,3 @@ class EqualityTestCase < Minitest::Test
88
89
  end
89
90
 
90
91
  end
91
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
  require "llvm/core"
3
5
 
@@ -30,6 +32,33 @@ class FunctionTest < Minitest::Test
30
32
  end
31
33
  end
32
34
 
35
+ def helper_test_attribute(name)
36
+ with_function [], LLVM.Void do |fun|
37
+ assert_equal 0, fun.attribute_count
38
+ assert_equal [], fun.attributes
39
+
40
+ fun.add_attribute(name)
41
+ assert_equal 1, fun.attribute_count
42
+ assert_equal [34], fun.attributes
43
+
44
+ assert_equal false, fun.verify
45
+
46
+ fun.remove_attribute(name)
47
+ assert_equal 0, fun.attribute_count
48
+ assert_equal [], fun.attributes
49
+
50
+ assert_equal false, fun.verify
51
+ end
52
+ end
53
+
54
+ def test_add_attribute_old_name
55
+ helper_test_attribute(:no_unwind_attribute)
56
+ end
57
+
58
+ def test_add_attribute_new_name
59
+ helper_test_attribute(:nounwind)
60
+ end
61
+
33
62
  end
34
63
 
35
64
  class FunctionTypeTest < Minitest::Test
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class GenericValueTestCase < Minitest::Test
@@ -8,7 +10,7 @@ class GenericValueTestCase < Minitest::Test
8
10
 
9
11
  def test_from_i
10
12
  assert_equal 2, LLVM::GenericValue.from_i(2).to_i
11
- assert_equal 2 ,LLVM::GenericValue.from_i(2.2).to_i
13
+ assert_equal 2, LLVM::GenericValue.from_i(2.2).to_i
12
14
  end
13
15
 
14
16
  def test_from_float
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class InstructionTestCase < Minitest::Test
@@ -28,5 +30,3 @@ class InstructionTestCase < Minitest::Test
28
30
  assert_equal entry, inst2.parent
29
31
  end
30
32
  end
31
-
32
-
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class IntegerTestCase < Minitest::Test
6
+
7
+ def test_const_zext
8
+ assert i = LLVM::Int8.from_i(-1)
9
+ assert_equal 'i8 -1', i.to_s
10
+ assert_equal :integer, i.type.kind
11
+ assert_equal 8, i.type.width
12
+ assert zext = i.zext(LLVM::Int64)
13
+ assert_equal 'i64 255', zext.to_s
14
+ assert_equal :integer, zext.type.kind
15
+ assert_equal 64, zext.type.width
16
+ end
17
+
18
+ def test_const_sext
19
+ assert i = LLVM::Int8.from_i(-1)
20
+ assert_equal 'i8 -1', i.to_s
21
+ assert_equal :integer, i.type.kind
22
+ assert_equal 8, i.type.width
23
+ assert sext = i.sext(LLVM::Int64)
24
+ assert_equal 'i64 -1', sext.to_s
25
+ assert_equal :integer, sext.type.kind
26
+ assert_equal 64, sext.type.width
27
+ end
28
+ end
data/test/ipo_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
  require "llvm/core"
3
5
  require 'llvm/transforms/ipo'
@@ -39,7 +41,7 @@ class IPOTestCase < Minitest::Test
39
41
  assert fns.include?(main)
40
42
 
41
43
  # optimize
42
- engine = LLVM::JITCompiler.new(mod)
44
+ engine = LLVM::MCJITCompiler.new(mod)
43
45
  passm = LLVM::PassManager.new(engine)
44
46
 
45
47
  passm.gdce!
data/test/linker_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'llvm/core'
3
5
  require 'llvm/linker'
@@ -34,13 +36,4 @@ class LinkerTestCase < Minitest::Test
34
36
 
35
37
  assert_equal 42, run_function_on_module(@mod1, 'main').to_i
36
38
  end
37
-
38
- def test_link_into_and_destroy
39
- create_modules
40
- @mod2.link_into_and_destroy(@mod1)
41
-
42
- assert_nil @mod2.to_ptr
43
-
44
- assert_equal 42, run_function_on_module(@mod1, 'main').to_i
45
- end
46
39
  end
data/test/mcjit_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class MCJITTestCase < Minitest::Test
@@ -35,6 +37,9 @@ class MCJITTestCase < Minitest::Test
35
37
 
36
38
  engine = LLVM::MCJITCompiler.new(mod, :opt_level => 0)
37
39
 
40
+ # TODO: fix or replace find_function
41
+ skip
42
+
38
43
  ['foo', :foo].each do |name|
39
44
  engine.functions[name].tap do |fun|
40
45
  assert fun, "function named #{name.inspect}"
@@ -77,7 +82,10 @@ class MCJITTestCase < Minitest::Test
77
82
  assert_equal engine.modules, ret, '#<< returns self'
78
83
  end
79
84
 
80
- assert engine.functions[:bar]
85
+ # TODO: fix or replace find_function
86
+ skip
87
+
88
+ refute_nil engine.functions[:bar]
81
89
  engine.modules.delete(mod2).tap do |ret|
82
90
  assert_instance_of LLVM::Module, ret, '#delete returns module'
83
91
  assert_equal mod2, ret
@@ -88,7 +96,7 @@ class MCJITTestCase < Minitest::Test
88
96
  def test_accessors
89
97
  main_mod = LLVM::Module.new('main')
90
98
  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
99
+ assert_match(/^e-/, engine.data_layout.to_s)
100
+ assert_match(/gnu/, engine.target_machine.triple)
93
101
  end
94
102
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class MemoryAccessTestCase < Minitest::Test
data/test/module_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
  require "tempfile"
3
5
 
@@ -54,7 +56,8 @@ class ModuleTestCase < Minitest::Test
54
56
 
55
57
  def test_to_s
56
58
  mod = LLVM::Module.new('test_print')
57
- assert_equal mod.to_s, "; ModuleID = 'test_print'\n"
59
+ assert_equal mod.to_s,
60
+ "; ModuleID = 'test_print'\nsource_filename = \"test_print\"\n"
58
61
  end
59
62
 
60
63
  def test_dump
@@ -75,4 +78,18 @@ class ModuleTestCase < Minitest::Test
75
78
  end
76
79
  end
77
80
 
81
+ def test_module_properties
82
+ mod = LLVM::Module.new('mod')
83
+
84
+ assert_equal '', mod.triple
85
+
86
+ mod.triple = 'x86-linux-gnu'
87
+ assert_equal 'x86-linux-gnu', mod.triple
88
+
89
+ assert_equal '', mod.data_layout
90
+
91
+ mod.data_layout = 'e-p:32:32'
92
+ assert_equal 'e-p:32:32', mod.data_layout
93
+ end
94
+
78
95
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class ParameterCollectionTestCase < Minitest::Test
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'llvm/config'
3
5
  require 'llvm/transforms/builder'
@@ -7,8 +9,7 @@ class PassManagerBuilderTest < Minitest::Test
7
9
  LLVM.init_jit
8
10
  @builder = LLVM::PassManagerBuilder.new
9
11
 
10
- machine = LLVM::Target.by_name('x86-64').create_machine('x86-linux-gnu')
11
- @pass_manager = LLVM::PassManager.new(machine)
12
+ @pass_manager = LLVM::PassManager.new
12
13
  end
13
14
 
14
15
  def teardown
@@ -51,4 +52,23 @@ class PassManagerBuilderTest < Minitest::Test
51
52
  @builder.build_with_lto(@pass_manager, false, 0)
52
53
  end
53
54
  end
55
+
56
+ PASSES = [
57
+ 'always_inline!',
58
+ 'adce!',
59
+ 'tailcallelim!',
60
+ 'fun_attrs!',
61
+ 'mergefunc!',
62
+ ].freeze
63
+
64
+ describe "PassManager Passes" do
65
+ before do
66
+ assert @pass_manager = LLVM::PassManager.new
67
+ end
68
+ PASSES.each do |pass|
69
+ it "should return '#{pass}'" do
70
+ assert_nil @pass_manager.send(pass)
71
+ end
72
+ end
73
+ end
54
74
  end
data/test/phi_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class PhiTest < Minitest::Test
data/test/select_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class SelectTestCase < Minitest::Test
data/test/struct_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class StructTestCase < Minitest::Test
data/test/target_test.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: ascii-8bit
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "test_helper"
4
5
  require 'tempfile'
@@ -56,9 +57,6 @@ class TargetTestCase < Minitest::Test
56
57
  assert_equal 'x86-linux-gnu', mach.triple
57
58
  assert_equal 'i686', mach.cpu
58
59
  assert_equal '', mach.features
59
-
60
- layout = mach.data_layout
61
- assert_equal 'e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128', layout.to_s
62
60
  end
63
61
 
64
62
  def test_emit
@@ -74,29 +72,27 @@ class TargetTestCase < Minitest::Test
74
72
 
75
73
  Tempfile.open('emit') do |tmp|
76
74
  mach.emit(mod, tmp.path)
77
- assert_match %r{xorl\t%eax, %eax}, tmp.read
75
+ data = tmp.read
76
+ assert_match(/xorl\t%eax, %eax/, data)
77
+ assert_equal 218, data.length
78
78
  end
79
79
 
80
+ # despite the above test, in LLVM <= 11 the objdump output was:
81
+ # 00000000 <main>:
82
+ # 0: 66 31 c0 xor %ax,%ax
83
+ # 3: 66 c3 retw
84
+ # In LLVM 13, the objdump output is:
85
+ # 00000000 <main>:
86
+ # 0: 31 c0 xor %eax,%eax
87
+ # 2: c3 ret
80
88
  Tempfile.open('emit') do |tmp|
81
89
  mach.emit(mod, tmp.path, :object)
82
- assert_match %r{\x66\x31\xc0}, File.read(tmp.path, mode: 'rb')
90
+ data = File.read(tmp.path, mode: 'rb')
91
+ assert_match(/\x31\xc0\xc3/, data)
92
+ assert_equal 528, data.length
83
93
  end
84
94
  end
85
95
 
86
- def test_module_properties
87
- mod = LLVM::Module.new('mod')
88
-
89
- assert_equal '', mod.triple
90
-
91
- mod.triple = 'x86-linux-gnu'
92
- assert_equal 'x86-linux-gnu', mod.triple
93
-
94
- assert_equal '', mod.data_layout
95
-
96
- mod.data_layout = 'e-p:32:32'
97
- assert_equal 'e-p:32:32', mod.data_layout
98
- end
99
-
100
96
  def test_data_layout
101
97
  layout_be = LLVM::TargetDataLayout.new('E')
102
98
  assert_equal :big_endian, layout_be.byte_order
@@ -104,7 +100,7 @@ class TargetTestCase < Minitest::Test
104
100
  desc = "e-p:32:32:32-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64"
105
101
  layout = LLVM::TargetDataLayout.new(desc)
106
102
 
107
- assert_equal "e-p:32:32", layout.to_s
103
+ assert_equal desc, layout.to_s
108
104
  assert_equal :little_endian, layout.byte_order
109
105
  assert_equal 4, layout.pointer_size
110
106
  assert_equal 4, layout.pointer_size(0)
data/test/test_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
4
 
3
5
  begin
@@ -17,6 +19,9 @@ rescue LoadError
17
19
  end
18
20
 
19
21
  require "minitest/autorun"
22
+ require 'minitest/reporters'
23
+
24
+ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
20
25
 
21
26
  require "llvm/core"
22
27
  require "llvm/execution_engine"
@@ -46,7 +51,7 @@ def define_function(host_module, function_name, argument_types, return_type)
46
51
  end
47
52
 
48
53
  def run_function_on_module(host_module, function_name, *argument_values)
49
- LLVM::JITCompiler.new(host_module).
54
+ LLVM::MCJITCompiler.new(host_module).
50
55
  run_function(host_module.functions[function_name], *argument_values)
51
56
  end
52
57
 
data/test/type_test.rb CHANGED
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class TypeTestCase < Minitest::Test
4
6
 
7
+ extend MiniTest::Spec::DSL
8
+
5
9
  def test_element_type
6
10
  pointer = LLVM.Pointer(LLVM::Int32.type)
7
11
  pointee = pointer.element_type
@@ -12,4 +16,47 @@ class TypeTestCase < Minitest::Test
12
16
  assert_nil pointee.element_type
13
17
  end
14
18
 
19
+ TO_S_TESTS = [
20
+ [LLVM.Struct(LLVM::Int32, LLVM::Int32), '{ i32, i32 }'],
21
+ [LLVM.Struct(LLVM::Int32, LLVM::Int32, "s1"), '%s1 = type { i32, i32 }'],
22
+ [LLVM::Type.struct([LLVM::Int32, LLVM::Int32], true), '<{ i32, i32 }>'],
23
+ [LLVM::Type.struct([LLVM::Int32, LLVM::Int32], true, "s2"), '%s2 = type <{ i32, i32 }>'],
24
+
25
+ [LLVM.Array(LLVM::Int8), '[0 x i8]'],
26
+ [LLVM.Array(LLVM::Int8, 42), '[42 x i8]'],
27
+ [LLVM::Type.array(LLVM::Int1), '[0 x i1]'],
28
+ [LLVM::Type.array(LLVM::Int1, 42), '[42 x i1]'],
29
+
30
+ [LLVM.Vector(LLVM::Int8, 42), '<42 x i8>'],
31
+ [LLVM::Type.vector(LLVM::Int1, 42), '<42 x i1>'],
32
+
33
+ [LLVM.Void, 'void'],
34
+ [LLVM::Type.void, 'void'],
35
+
36
+ [LLVM.Pointer(LLVM::Int8), 'i8*'],
37
+ [LLVM::Type.pointer(LLVM::Int1), 'i1*'],
38
+
39
+ [LLVM.Function([LLVM::Int8], LLVM.Void), 'void (i8)'],
40
+ [LLVM.Function([LLVM::Int8], LLVM::Int8), 'i8 (i8)'],
41
+ [LLVM.Function([], LLVM::Int8), 'i8 ()'],
42
+ [LLVM.Function([], LLVM.Void), 'void ()'],
43
+ [LLVM::Type.function([LLVM::Int1], LLVM.Void), 'void (i1)'],
44
+ [LLVM::Type.function([LLVM::Int1], LLVM::Int1), 'i1 (i1)'],
45
+ [LLVM::Type.function([], LLVM::Int1), 'i1 ()'],
46
+ [LLVM::Type.function([], LLVM.Void), 'void ()'],
47
+ ].freeze
48
+
49
+ describe "LLVM::Type#to_s" do
50
+ TO_S_TESTS.each do |(type, string)|
51
+ it "should return '#{string}'" do
52
+ assert type.is_a?(LLVM::Type)
53
+ assert_equal string, type.to_s
54
+ end
55
+ end
56
+
57
+ it 'should have 22 dynamic tests' do
58
+ assert_equal 22, TO_S_TESTS.size
59
+ end
60
+ end
61
+
15
62
  end
data/test/vector_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class VectorTestCase < Minitest::Test