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