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,38 @@
1
+ require "test_helper"
2
+
3
+ class MemoryAccessTestCase < Minitest::Test
4
+
5
+ def setup
6
+ LLVM.init_jit
7
+ end
8
+
9
+ def test_memory_access
10
+ assert_equal 1 + 2, simple_memory_access_function(1, 2).to_i
11
+ assert_equal 3 + 4, array_memory_access_function(3, 4).to_i
12
+ end
13
+
14
+ def simple_memory_access_function(value1, value2)
15
+ run_function([LLVM::Int, LLVM::Int], [value1, value2], LLVM::Int) do |builder, function, *arguments|
16
+ entry = function.basic_blocks.append
17
+ builder.position_at_end(entry)
18
+ pointer1 = builder.alloca(LLVM::Int)
19
+ pointer2 = builder.alloca(LLVM::Int)
20
+ builder.store(arguments.first, pointer1)
21
+ builder.store(arguments.last, pointer2)
22
+ builder.ret(builder.add(builder.load(pointer1), builder.load(pointer2)))
23
+ end
24
+ end
25
+
26
+ def array_memory_access_function(value1, value2)
27
+ run_function([LLVM::Int, LLVM::Int], [value1, value2], LLVM::Int) do |builder, function, *arguments|
28
+ entry = function.basic_blocks.append
29
+ builder.position_at_end(entry)
30
+ pointer = builder.array_alloca(LLVM::Int, LLVM::Int(2))
31
+ builder.store(arguments.first, builder.gep(pointer, [LLVM::Int(0)]))
32
+ builder.store(arguments.last, builder.gep(pointer, [LLVM::Int(1)]))
33
+ builder.ret(builder.add(builder.load(builder.gep(pointer, [LLVM::Int(0)])),
34
+ builder.load(builder.gep(pointer, [LLVM::Int(1)]))))
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,93 @@
1
+ require "test_helper"
2
+ require "tempfile"
3
+
4
+ class ModuleTestCase < Minitest::Test
5
+
6
+ def setup
7
+ LLVM.init_jit
8
+ end
9
+
10
+ def simple_function
11
+ run_function([], [], LLVM::Int) do |builder, function, *arguments|
12
+ entry = function.basic_blocks.append
13
+ builder.position_at_end(entry)
14
+ builder.ret(LLVM::Int(1))
15
+ end
16
+ end
17
+
18
+ def test_simple_module
19
+ assert_equal 1, simple_function().to_i
20
+ end
21
+
22
+ def test_global_variable
23
+ yielded = false
24
+
25
+ define_module('test_globals_add') do |mod|
26
+ mod.globals.add(LLVM::Int32, 'i') do |var|
27
+ yielded = true
28
+
29
+ assert var.kind_of?(LLVM::GlobalVariable)
30
+
31
+ # unnamed_addr
32
+ assert !var.unnamed_addr?
33
+ var.unnamed_addr = true
34
+ assert var.unnamed_addr?
35
+
36
+ assert (var.dll_storage_class == :default)
37
+ var.dll_storage_class = :dll_import
38
+ assert (var.dll_storage_class == :dll_import)
39
+
40
+ # global_constant
41
+ assert !var.global_constant?
42
+ var.global_constant = true
43
+ assert var.global_constant?
44
+
45
+ assert_output("", "Warning: Passing Integer value to LLVM::GlobalValue#global_constant=(Boolean) is deprecated.\n") do
46
+ var.global_constant = 0
47
+ end
48
+ assert !var.global_constant?
49
+ end
50
+ end
51
+
52
+ assert yielded, 'LLVM::Module::GlobalCollection#add takes block'
53
+ end
54
+
55
+ def test_to_s
56
+ mod = LLVM::Module.new('test_print')
57
+ assert_equal mod.to_s,
58
+ "; ModuleID = 'test_print'\nsource_filename = \"test_print\"\n"
59
+ end
60
+
61
+ def test_dump
62
+ mod = LLVM::Module.new('test_print')
63
+ expected_pattern = /^; ModuleID = 'test_print'$/
64
+
65
+ Tempfile.open('test_dump.1') do |tmpfile|
66
+ # debug stream (stderr)
67
+ stderr_old = $stderr.dup
68
+ $stderr.reopen(tmpfile.path, 'a')
69
+ begin
70
+ mod.dump
71
+ $stderr.flush
72
+ assert_match expected_pattern, File.read(tmpfile.path)
73
+ ensure
74
+ $stderr.reopen(stderr_old)
75
+ end
76
+ end
77
+ end
78
+
79
+ def test_module_properties
80
+ mod = LLVM::Module.new('mod')
81
+
82
+ assert_equal '', mod.triple
83
+
84
+ mod.triple = 'x86-linux-gnu'
85
+ assert_equal 'x86-linux-gnu', mod.triple
86
+
87
+ assert_equal '', mod.data_layout
88
+
89
+ mod.data_layout = 'e-p:32:32'
90
+ assert_equal 'e-p:32:32', mod.data_layout
91
+ end
92
+
93
+ end
@@ -0,0 +1,28 @@
1
+ require "test_helper"
2
+
3
+ class ParameterCollectionTestCase < Minitest::Test
4
+ def setup
5
+ @mod = LLVM::Module.new('test')
6
+ @fun = @mod.functions.add('fun', [LLVM::Int, LLVM::Int], LLVM::Int)
7
+ @fun.params[0].name = 'foo'
8
+ @fun.params[1].name = 'bar'
9
+ end
10
+
11
+ def test_positive_index_in_range
12
+ assert_equal 'foo', @fun.params[0].name
13
+ assert_equal 'bar', @fun.params[1].name
14
+ end
15
+
16
+ def test_negative_index_in_range
17
+ assert_equal 'foo', @fun.params[-2].name
18
+ assert_equal 'bar', @fun.params[-1].name
19
+ end
20
+
21
+ def test_positive_index_out_of_range
22
+ assert_nil @fun.params[2]
23
+ end
24
+
25
+ def test_negative_index_out_of_range
26
+ assert_nil @fun.params[-3]
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+ require 'llvm/config'
3
+ require 'llvm/transforms/builder'
4
+
5
+ class PassManagerBuilderTest < Minitest::Test
6
+ def setup
7
+ LLVM.init_jit
8
+ @builder = LLVM::PassManagerBuilder.new
9
+
10
+ @pass_manager = LLVM::PassManager.new
11
+ end
12
+
13
+ def teardown
14
+ @builder.dispose
15
+ @pass_manager.dispose
16
+ end
17
+
18
+ def test_init
19
+ assert_equal 0, @builder.size_level
20
+ assert_equal 0, @builder.opt_level
21
+ assert_equal false, @builder.unit_at_a_time
22
+ assert_equal false, @builder.unroll_loops
23
+ assert_equal false, @builder.simplify_lib_calls
24
+ assert_equal 0, @builder.inliner_threshold
25
+ end
26
+
27
+ def test_opt_level
28
+ @builder.opt_level = 3
29
+ assert_equal 3, @builder.opt_level
30
+ end
31
+
32
+ def test_build
33
+ @builder.build(@pass_manager)
34
+ end
35
+
36
+ def test_build_with_lto
37
+ assert_output('', '') do
38
+ @builder.build_with_lto(@pass_manager)
39
+ end
40
+ end
41
+
42
+ def test_build_with_lto_deprecated_internalize_param
43
+ assert_output("", "Warning: Passing Integer value to LLVM::PassManagerBuilder#build_with_lto is deprecated.\n") do
44
+ @builder.build_with_lto(@pass_manager, 0)
45
+ end
46
+ end
47
+
48
+ def test_build_with_lto_deprecated_run_inliner_param
49
+ assert_output("", "Warning: Passing Integer value to LLVM::PassManagerBuilder#build_with_lto is deprecated.\n") do
50
+ @builder.build_with_lto(@pass_manager, false, 0)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ require "test_helper"
2
+
3
+ class PhiTest < Minitest::Test
4
+ def setup
5
+ LLVM.init_jit
6
+ end
7
+
8
+ def test_phi
9
+ assert_equal 1, run_phi_function(0).to_i
10
+ assert_equal 0, run_phi_function(1).to_i
11
+ end
12
+
13
+ def run_phi_function(argument)
14
+ run_function([LLVM::Int], argument, LLVM::Int) do |builder, function, *arguments|
15
+ entry = function.basic_blocks.append
16
+ block1 = function.basic_blocks.append
17
+ block2 = function.basic_blocks.append
18
+ exit = function.basic_blocks.append
19
+ builder.position_at_end(entry)
20
+ builder.cond(builder.icmp(:eq, arguments.first, LLVM::Int(0)), block1, block2)
21
+ builder.position_at_end(block1)
22
+ result1 = builder.add(arguments.first, LLVM::Int(1))
23
+ builder.br(exit)
24
+ builder.position_at_end(block2)
25
+ result2 = builder.sub(arguments.first, LLVM::Int(1))
26
+ builder.br(exit)
27
+ builder.position_at_end(exit)
28
+ builder.ret(builder.phi(LLVM::Int,
29
+ block1 => result1,
30
+ block2 => result2))
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ class SelectTestCase < Minitest::Test
4
+
5
+ def setup
6
+ LLVM.init_jit
7
+ end
8
+
9
+ def test_select
10
+ assert_equal 0, select_function(1).to_i
11
+ assert_equal 1, select_function(0).to_i
12
+ end
13
+
14
+ def select_function(value)
15
+ run_function([LLVM::Int1], [value], LLVM::Int) do |builder, function, *arguments|
16
+ entry = function.basic_blocks.append
17
+ builder.position_at_end(entry)
18
+ builder.ret(builder.select(arguments.first, LLVM::Int(0), LLVM::Int(1)))
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,98 @@
1
+ require "test_helper"
2
+
3
+ class StructTestCase < Minitest::Test
4
+
5
+ LLVM_UNPACKED = false
6
+ LLVM_PACKED = true
7
+
8
+ def setup
9
+ LLVM.init_jit
10
+ end
11
+
12
+ def test_simple_struct
13
+ struct = LLVM::Struct(LLVM::Int, LLVM::Float)
14
+ assert_instance_of LLVM::StructType, struct
15
+ assert_equal 2, struct.element_types.size
16
+ assert_equal LLVM::Int.type, struct.element_types[0]
17
+ assert_equal LLVM::Float.type, struct.element_types[1]
18
+ end
19
+
20
+ def test_named_struct
21
+ struct = LLVM::Struct(LLVM::Int, LLVM::Float, "struct100")
22
+ assert_instance_of LLVM::StructType, struct
23
+ assert_equal "struct100", struct.name
24
+ end
25
+
26
+ def test_deferred_element_type_setting
27
+ struct = LLVM::Struct("struct200")
28
+ struct.element_types = [LLVM::Int, LLVM::Float]
29
+ assert_equal 2, struct.element_types.size
30
+ end
31
+
32
+ def test_unpacked_constant_struct_from_size
33
+ struct = LLVM::ConstantStruct.const(2, LLVM_UNPACKED) { |i| LLVM::Int(i) }
34
+ assert_instance_of LLVM::ConstantStruct, struct
35
+ assert_equal 2, struct.operands.size
36
+ end
37
+
38
+ def test_unpacked_constant_struct_from_struct
39
+ struct = LLVM::ConstantStruct.const([LLVM::Int(0), LLVM::Int(1)], LLVM_UNPACKED)
40
+ assert_instance_of LLVM::ConstantStruct, struct
41
+ assert_equal 2, struct.operands.size
42
+ end
43
+
44
+ def test_packed_constant_struct_from_size
45
+ struct = LLVM::ConstantStruct.const(2, LLVM_PACKED) { |i| LLVM::Int(i) }
46
+ assert_instance_of LLVM::ConstantStruct, struct
47
+ assert_equal 2, struct.operands.size
48
+ end
49
+
50
+ def test_packed_constant_struct_from_struct
51
+ struct = LLVM::ConstantStruct.const([LLVM::Int(0), LLVM::Int(1)], LLVM_PACKED)
52
+ assert_instance_of LLVM::ConstantStruct, struct
53
+ assert_equal 2, struct.operands.size
54
+ end
55
+
56
+ def test_constant_named_struct
57
+ struct_ty = LLVM::Struct(LLVM::Int, "struct300")
58
+ struct = LLVM::ConstantStruct.named_const(struct_ty, [ LLVM::Int(1) ])
59
+ assert_instance_of LLVM::ConstantStruct, struct
60
+ assert_equal 1, struct.operands.size
61
+ assert_equal struct_ty, struct.type
62
+ end
63
+
64
+ def test_struct_values
65
+ assert_equal 2 + 3, run_struct_values(2, 3).to_i
66
+ end
67
+
68
+ def test_struct_access
69
+ assert_in_delta 2 + 3.3, run_struct_access(LLVM::Float, 2, 3.3).to_f, 0.001
70
+ end
71
+
72
+ def run_struct_values(value1, value2)
73
+ run_function([LLVM::Int, LLVM::Int], [value1, value2], LLVM::Int) do |builder, function, *arguments|
74
+ entry = function.basic_blocks.append
75
+ builder.position_at_end(entry)
76
+ pointer = builder.alloca(LLVM::Struct(LLVM::Int, LLVM::Int))
77
+ struct = builder.load(pointer)
78
+ struct = builder.insert_value(struct, arguments.first, 0)
79
+ struct = builder.insert_value(struct, arguments.last, 1)
80
+ builder.ret(builder.add(builder.extract_value(struct, 0),
81
+ builder.extract_value(struct, 1)))
82
+ end
83
+ end
84
+
85
+ def run_struct_access(return_type, value1, value2)
86
+ run_function([LLVM::Int, LLVM::Float], [value1, value2], return_type) do |builder, function, *arguments|
87
+ entry = function.basic_blocks.append
88
+ builder.position_at_end(entry)
89
+ pointer = builder.alloca(LLVM::Struct(LLVM::Float, LLVM::Struct(LLVM::Int, LLVM::Float), LLVM::Int))
90
+ builder.store(arguments.first, builder.gep(pointer, [LLVM::Int(0), LLVM::Int32.from_i(1), LLVM::Int32.from_i(0)]))
91
+ builder.store(arguments.last, builder.gep(pointer, [LLVM::Int(0), LLVM::Int32.from_i(1), LLVM::Int32.from_i(1)]))
92
+ address1 = builder.gep(pointer, [LLVM::Int(0), LLVM::Int32.from_i(1), LLVM::Int32.from_i(0)])
93
+ address2 = builder.gep(pointer, [LLVM::Int(0), LLVM::Int32.from_i(1), LLVM::Int32.from_i(1)])
94
+ builder.ret(builder.fadd(builder.ui2fp(builder.load(address1), LLVM::Float), builder.load(address2)))
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,113 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require "test_helper"
4
+ require 'tempfile'
5
+ require 'llvm/version'
6
+ require 'llvm/config'
7
+
8
+ class TargetTestCase < Minitest::Test
9
+
10
+ def setup
11
+ LLVM::Target.init('X86', true)
12
+
13
+ @x86 = LLVM::Target.by_name('x86')
14
+ end
15
+
16
+ def test_init_native
17
+ LLVM::Target.init_native
18
+ LLVM::Target.init_native(true)
19
+ end
20
+
21
+ if LLVM::CONFIG::TARGETS_BUILT.include?('ARM')
22
+ def test_init_arm
23
+ LLVM::Target.init('ARM')
24
+ LLVM::Target.init('ARM', true)
25
+
26
+ arm_target = LLVM::Target.by_name('arm')
27
+ assert_equal 'arm', arm_target.name
28
+ end
29
+ end
30
+
31
+ def test_init_all
32
+ LLVM::Target.init_all
33
+ LLVM::Target.init_all(true)
34
+ end
35
+
36
+ def test_each
37
+ targets = LLVM::Target.each
38
+
39
+ assert_instance_of Enumerator, targets
40
+ assert targets.count > 0
41
+ end
42
+
43
+ def test_target
44
+ assert_equal 'x86', @x86.name
45
+ assert_equal "32-bit X86: Pentium-Pro and above", @x86.description
46
+ assert_equal true, @x86.jit?
47
+ assert_equal true, @x86.target_machine?
48
+ assert_equal true, @x86.asm_backend?
49
+ end
50
+
51
+ def test_target_machine
52
+ @x86 = LLVM::Target.by_name('x86')
53
+ mach = @x86.create_machine('x86-linux-gnu', 'i686')
54
+
55
+ assert_equal @x86, mach.target
56
+ assert_equal 'x86-linux-gnu', mach.triple
57
+ assert_equal 'i686', mach.cpu
58
+ assert_equal '', mach.features
59
+ end
60
+
61
+ def test_emit
62
+ mach = @x86.create_machine('x86-linux-gnu')
63
+
64
+ mod = define_module('test') do |mod|
65
+ define_function(mod, 'main', [], LLVM::Int) do |builder, fun|
66
+ entry = fun.basic_blocks.append
67
+ builder.position_at_end(entry)
68
+ builder.ret(LLVM::Int(0))
69
+ end
70
+ end
71
+
72
+ Tempfile.open('emit') do |tmp|
73
+ mach.emit(mod, tmp.path)
74
+ assert_match(/xorl\t%eax, %eax/, tmp.read)
75
+ end
76
+
77
+ Tempfile.open('emit') do |tmp|
78
+ mach.emit(mod, tmp.path, :object)
79
+ assert_match(/\x66\x31\xc0/, File.read(tmp.path, mode: 'rb'))
80
+ end
81
+ end
82
+
83
+ def test_data_layout
84
+ layout_be = LLVM::TargetDataLayout.new('E')
85
+ assert_equal :big_endian, layout_be.byte_order
86
+
87
+ 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"
88
+ layout = LLVM::TargetDataLayout.new(desc)
89
+
90
+ assert_equal desc, layout.to_s
91
+ assert_equal :little_endian, layout.byte_order
92
+ assert_equal 4, layout.pointer_size
93
+ assert_equal 4, layout.pointer_size(0)
94
+ assert_equal LLVM::Int32.type, layout.int_ptr_type
95
+ assert_equal LLVM::Int32.type, layout.int_ptr_type(0)
96
+
97
+ assert_equal 19, layout.bit_size_of(LLVM::Int19.type)
98
+ assert_equal 3, layout.storage_size_of(LLVM::Int19.type)
99
+ assert_equal 4, layout.abi_size_of(LLVM::Int19.type)
100
+ assert_equal 4, layout.abi_alignment_of(LLVM::Int19.type)
101
+ assert_equal 4, layout.call_frame_alignment_of(LLVM::Int19.type)
102
+ assert_equal 4, layout.preferred_alignment_of(LLVM::Int19.type)
103
+
104
+ struct = LLVM.Struct(LLVM::Int8, LLVM::Int32)
105
+
106
+ assert_equal 0, layout.offset_of_element(struct, 0)
107
+ assert_equal 4, layout.offset_of_element(struct, 1)
108
+
109
+ assert_equal 0, layout.element_at_offset(struct, 0)
110
+ assert_equal 0, layout.element_at_offset(struct, 3)
111
+ assert_equal 1, layout.element_at_offset(struct, 4)
112
+ end
113
+ end