rltk 2.2.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +12 -12
  3. data/README.md +458 -285
  4. data/Rakefile +99 -92
  5. data/lib/rltk/ast.rb +221 -126
  6. data/lib/rltk/cfg.rb +218 -239
  7. data/lib/rltk/cg/basic_block.rb +1 -1
  8. data/lib/rltk/cg/bindings.rb +9 -26
  9. data/lib/rltk/cg/builder.rb +40 -8
  10. data/lib/rltk/cg/context.rb +1 -1
  11. data/lib/rltk/cg/contractor.rb +51 -0
  12. data/lib/rltk/cg/execution_engine.rb +45 -8
  13. data/lib/rltk/cg/function.rb +12 -2
  14. data/lib/rltk/cg/generated_bindings.rb +2541 -575
  15. data/lib/rltk/cg/generic_value.rb +2 -2
  16. data/lib/rltk/cg/instruction.rb +104 -83
  17. data/lib/rltk/cg/llvm.rb +44 -3
  18. data/lib/rltk/cg/memory_buffer.rb +22 -5
  19. data/lib/rltk/cg/module.rb +85 -36
  20. data/lib/rltk/cg/old_generated_bindings.rb +6152 -0
  21. data/lib/rltk/cg/pass_manager.rb +87 -43
  22. data/lib/rltk/cg/support.rb +2 -4
  23. data/lib/rltk/cg/target.rb +158 -28
  24. data/lib/rltk/cg/triple.rb +8 -8
  25. data/lib/rltk/cg/type.rb +69 -25
  26. data/lib/rltk/cg/value.rb +107 -66
  27. data/lib/rltk/cg.rb +16 -17
  28. data/lib/rltk/lexer.rb +21 -11
  29. data/lib/rltk/lexers/calculator.rb +1 -1
  30. data/lib/rltk/lexers/ebnf.rb +8 -7
  31. data/lib/rltk/parser.rb +300 -247
  32. data/lib/rltk/parsers/infix_calc.rb +1 -1
  33. data/lib/rltk/parsers/postfix_calc.rb +2 -2
  34. data/lib/rltk/parsers/prefix_calc.rb +2 -2
  35. data/lib/rltk/token.rb +1 -2
  36. data/lib/rltk/version.rb +3 -3
  37. data/lib/rltk.rb +6 -6
  38. data/test/cg/tc_basic_block.rb +83 -0
  39. data/test/cg/tc_control_flow.rb +191 -0
  40. data/test/cg/tc_function.rb +54 -0
  41. data/test/cg/tc_generic_value.rb +33 -0
  42. data/test/cg/tc_instruction.rb +256 -0
  43. data/test/cg/tc_llvm.rb +25 -0
  44. data/test/cg/tc_math.rb +88 -0
  45. data/test/cg/tc_module.rb +89 -0
  46. data/test/cg/tc_transforms.rb +68 -0
  47. data/test/cg/tc_type.rb +69 -0
  48. data/test/cg/tc_value.rb +151 -0
  49. data/test/cg/ts_cg.rb +23 -0
  50. data/test/tc_ast.rb +105 -8
  51. data/test/tc_cfg.rb +63 -48
  52. data/test/tc_lexer.rb +84 -96
  53. data/test/tc_parser.rb +224 -52
  54. data/test/tc_token.rb +6 -6
  55. data/test/ts_rltk.rb +12 -15
  56. metadata +149 -75
  57. data/lib/rltk/cg/generated_extended_bindings.rb +0 -287
  58. data/lib/rltk/util/abstract_class.rb +0 -25
  59. data/lib/rltk/util/monkeys.rb +0 -129
@@ -14,7 +14,7 @@ require 'rltk/parser'
14
14
  # Classes and Modules #
15
15
  #######################
16
16
 
17
- module RLTK # :nodoc:
17
+ module RLTK
18
18
 
19
19
  # The RLTK::Parsers module contains the parsers that are included as part
20
20
  # of the RLKT project.
@@ -14,8 +14,8 @@ require 'rltk/parser'
14
14
  # Classes and Modules #
15
15
  #######################
16
16
 
17
- module RLTK # :nodoc:
18
- module Parsers # :nodoc:
17
+ module RLTK
18
+ module Parsers
19
19
 
20
20
  # A parser for a simple post-fix calculator.
21
21
  class PostfixCalc < Parser
@@ -14,8 +14,8 @@ require 'rltk/parser'
14
14
  # Classes and Modules #
15
15
  #######################
16
16
 
17
- module RLTK # :nodoc:
18
- module Parsers # :nodoc:
17
+ module RLTK
18
+ module Parsers
19
19
 
20
20
  # A parser for a simple prefix calculator.
21
21
  class PrefixCalc < Parser
data/lib/rltk/token.rb CHANGED
@@ -7,8 +7,7 @@
7
7
  # Classes and Modules #
8
8
  #######################
9
9
 
10
- module RLTK # :nodoc:
11
-
10
+ module RLTK
12
11
  # The StreamPosition class is used to indicate the position of a token or
13
12
  # other text inside a stream.
14
13
  class StreamPosition
data/lib/rltk/version.rb CHANGED
@@ -3,9 +3,9 @@
3
3
  # Date: 2012/03/08
4
4
  # Description: This file specifies the version number of RLTK.
5
5
 
6
- module RLTK # :nodoc:
6
+ module RLTK
7
7
  # The version number of the RLTK library.
8
- VERSION = '2.2.1'
8
+ VERSION = '3.0.0'
9
9
  # The version of LLVM targeted by RLTK.
10
- LLVM_TARGET_VERSION = '3.0'
10
+ LLVM_TARGET_VERSION = '3.4'
11
11
  end
data/lib/rltk.rb CHANGED
@@ -7,10 +7,10 @@
7
7
  # context-free grammars and code generation. This includes a class for
8
8
  # representing CFGs, lexers, parsers, and generating code using LLVM.
9
9
  module RLTK
10
- autoload :AST, 'rltk/ast'
11
- autoload :CFG, 'rltk/cfg'
12
- autoload :CG, 'rltk/cg'
13
- autoload :Lexer, 'rltk/lexer'
14
- autoload :Parser, 'rltk/parser'
15
- autoload :Token, 'rltk/token'
10
+ autoload :AST, 'rltk/ast'
11
+ autoload :CFG, 'rltk/cfg'
12
+ autoload :CG, 'rltk/cg'
13
+ autoload :Lexer, 'rltk/lexer'
14
+ autoload :Parser, 'rltk/parser'
15
+ autoload :Token, 'rltk/token'
16
16
  end
@@ -0,0 +1,83 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/13
4
+ # Description: This file contains unit tests for the RLTK::CG::BasicBlock
5
+ # class.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Gems
12
+ require 'minitest/autorun'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/cg/llvm'
16
+ require 'rltk/cg/module'
17
+
18
+ class BasicBlockTester < Minitest::Test
19
+ def setup
20
+ RLTK::CG::LLVM.init(:X86)
21
+
22
+ @mod = RLTK::CG::Module.new('Testing Module')
23
+ end
24
+
25
+ def test_basic_block
26
+ fun = @mod.functions.add('basic_block_tester', RLTK::CG::VoidType, [])
27
+ bb0 = fun.blocks.append
28
+ bb1 = fun.blocks.append
29
+
30
+ assert_equal(fun, bb0.parent)
31
+ assert_equal(fun, bb1.parent)
32
+
33
+ assert_equal(bb1, bb0.next)
34
+ assert_equal(bb0, bb1.previous)
35
+
36
+ bb0.build { br(bb1) }
37
+ bb1.build { ret_void }
38
+
39
+ assert_equal(bb0.instructions.first, bb0.instructions.last)
40
+ assert_equal(bb1.instructions.first, bb1.instructions.last)
41
+ end
42
+
43
+ def test_basic_block_collection
44
+ fun = @mod.functions.add('basic_block_collection_tester', RLTK::CG::VoidType, [])
45
+ bb0 = fun.blocks.append
46
+
47
+ assert_instance_of(RLTK::CG::BasicBlock, bb0)
48
+
49
+ assert_equal(1, fun.blocks.size)
50
+ assert_equal(fun.blocks.first, fun.blocks.last)
51
+ assert_equal(fun.blocks.first, fun.blocks.entry)
52
+
53
+ bb1 = fun.blocks.append
54
+
55
+ assert_equal(2, fun.blocks.size)
56
+ assert_equal(bb0, fun.blocks.first)
57
+ assert_equal(bb1, fun.blocks.last)
58
+
59
+ [fun.blocks.each.to_a, fun.blocks.to_a].each do |blocks|
60
+ assert_equal(2, blocks.size)
61
+ assert_equal(bb0, blocks[0])
62
+ assert_equal(bb1, blocks[1])
63
+ end
64
+ end
65
+
66
+ def test_basic_block_enumeration
67
+ fun = @mod.functions.add('basic_block_enumeration_tester', RLTK::CG::DoubleType, [RLTK::CG::DoubleType])
68
+ bb0 = fun.blocks.append
69
+
70
+ [bb0.instructions.each.to_a, bb0.instructions.to_a].each do |insts|
71
+ assert_equal(0, insts.size)
72
+ end
73
+
74
+ bb0.build { ret(fadd(fun.params[0], RLTK::CG::Double.new(1.0))) }
75
+
76
+ [bb0.instructions.each.to_a, bb0.instructions.to_a].each do |insts|
77
+ assert_equal(2, insts.size)
78
+
79
+ assert_equal(bb0.instructions.first, insts[0])
80
+ assert_equal(bb0.instructions.last, insts[1])
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,191 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/09
4
+ # Description: This file contains unit tests for control flow instructions.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Gems
11
+ require 'minitest/autorun'
12
+
13
+ # Ruby Language Toolkit
14
+ require 'rltk/cg/llvm'
15
+ require 'rltk/cg/execution_engine'
16
+ require 'rltk/cg/module'
17
+ require 'rltk/cg/function'
18
+ require 'rltk/cg/type'
19
+
20
+ class ControlFlowTester < Minitest::Test
21
+ def setup
22
+ RLTK::CG::LLVM.init(:X86)
23
+
24
+ @mod = RLTK::CG::Module.new('Testing Module')
25
+ @jit = RLTK::CG::JITCompiler.new(@mod)
26
+ end
27
+
28
+ ##############
29
+ # Call Tests #
30
+ ##############
31
+
32
+ def test_external_call
33
+ extern = @mod.functions.add('abs', RLTK::CG::NativeIntType, [RLTK::CG::NativeIntType])
34
+
35
+ fun = @mod.functions.add('external_call_tester', RLTK::CG::NativeIntType, [RLTK::CG::NativeIntType]) do |fun|
36
+ blocks.append { ret call(extern, fun.params[0]) }
37
+ end
38
+
39
+ assert_equal(10, @jit.run_function(fun, -10).to_i)
40
+ end
41
+
42
+ def test_external_string_call
43
+ global = @mod.globals.add(RLTK::CG::ArrayType.new(RLTK::CG::Int8Type, 5), "path")
44
+ global.linkage = :internal
45
+ global.initializer = RLTK::CG::ConstantString.new('PATH')
46
+
47
+ external = @mod.functions.add('getenv', RLTK::CG::PointerType.new(RLTK::CG::Int8Type), [RLTK::CG::PointerType.new(RLTK::CG::Int8Type)])
48
+
49
+ fun = @mod.functions.add('external_string_call_tester', RLTK::CG::PointerType.new(RLTK::CG::Int8Type), []) do
50
+ blocks.append do
51
+ param = gep(global, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(0)])
52
+
53
+ ret call(external, param)
54
+ end
55
+ end
56
+
57
+ assert_equal(ENV['PATH'], @jit.run_function(fun).ptr.read_pointer.read_string)
58
+ end
59
+
60
+ def test_nested_call
61
+ fun0 = @mod.functions.add('simple_call_tester0', RLTK::CG::NativeIntType, []) do
62
+ blocks.append { ret RLTK::CG::NativeInt.new(1) }
63
+ end
64
+
65
+ fun1 = @mod.functions.add('simple_call_tester1', RLTK::CG::NativeIntType, []) do
66
+ blocks.append { ret call(fun0) }
67
+ end
68
+
69
+ assert_equal(1, @jit.run_function(fun1).to_i)
70
+ end
71
+
72
+ def test_recursive_call
73
+ fun = @mod.functions.add('recursive_call_tester', RLTK::CG::NativeIntType, [RLTK::CG::NativeIntType]) do |fun|
74
+ entry = blocks.append
75
+ recurse = blocks.append
76
+ exit = blocks.append
77
+
78
+ entry.build do
79
+ cond(icmp(:uge, fun.params[0], RLTK::CG::NativeInt.new(5)), exit, recurse)
80
+ end
81
+
82
+ result =
83
+ recurse.build do
84
+ call(fun, add(fun.params[0], RLTK::CG::NativeInt.new(1))).tap { br exit }
85
+ end
86
+
87
+ exit.build do
88
+ ret(phi(RLTK::CG::NativeIntType, {entry => fun.params[0], recurse => result}))
89
+ end
90
+ end
91
+
92
+ assert_equal(5, @jit.run_function(fun, 1).to_i)
93
+ assert_equal(6, @jit.run_function(fun, 6).to_i)
94
+ end
95
+
96
+ ##############
97
+ # Jump Tests #
98
+ ##############
99
+
100
+ def test_cond_jump
101
+ fun = @mod.functions.add('direct_jump_tester', RLTK::CG::NativeIntType, []) do |fun|
102
+ entry = blocks.append
103
+
104
+ bb0 = blocks.append { ret RLTK::CG::NativeInt.new(1) }
105
+ bb1 = blocks.append { ret RLTK::CG::NativeInt.new(0) }
106
+
107
+ entry.build do
108
+ cond(icmp(:eq, RLTK::CG::NativeInt.new(1), RLTK::CG::NativeInt.new(2)), bb0, bb1)
109
+ end
110
+ end
111
+
112
+ assert_equal(0, @jit.run_function(fun).to_i)
113
+ end
114
+
115
+ def test_direct_jump
116
+ fun = @mod.functions.add('direct_jump_tester', RLTK::CG::NativeIntType, []) do |fun|
117
+ entry = blocks.append
118
+
119
+ bb0 = blocks.append { ret(RLTK::CG::NativeInt.new(1)) }
120
+ bb1 = blocks.append { ret(RLTK::CG::NativeInt.new(0)) }
121
+
122
+ entry.build { br bb1 }
123
+ end
124
+
125
+ assert_equal(0, @jit.run_function(fun).to_i)
126
+ end
127
+
128
+ def test_switched_jump
129
+ fun = @mod.functions.add('direct_jump_tester', RLTK::CG::NativeIntType, []) do |fun|
130
+ entry = blocks.append
131
+
132
+ bb0 = blocks.append { ret RLTK::CG::NativeInt.new(1) }
133
+ bb1 = blocks.append { ret RLTK::CG::NativeInt.new(0) }
134
+
135
+ entry.build do
136
+ switch(RLTK::CG::NativeInt.new(1), bb0, {RLTK::CG::NativeInt.new(1) => bb1})
137
+ end
138
+ end
139
+
140
+ assert_equal(0, @jit.run_function(fun).to_i)
141
+ end
142
+
143
+ ##############
144
+ # Misc Tests #
145
+ ##############
146
+
147
+ def test_select
148
+ fun = @mod.functions.add('select_tester', RLTK::CG::Int1Type, [RLTK::CG::NativeIntType]) do |fun|
149
+ blocks.append do
150
+ ret select(fun.params[0], RLTK::CG::Int1.new(0), RLTK::CG::Int1.new(1))
151
+ end
152
+ end
153
+
154
+ assert_equal(0, @jit.run_function(fun, 1).to_i(false))
155
+ assert_equal(1, @jit.run_function(fun, 0).to_i(false))
156
+ end
157
+
158
+ #############
159
+ # Phi Tests #
160
+ #############
161
+
162
+ def test_phi
163
+ fun = @mod.functions.add('phi_tester', RLTK::CG::NativeIntType, [RLTK::CG::NativeIntType]) do |fun|
164
+ entry = blocks.append('entry')
165
+ block0 = blocks.append('block0')
166
+ block1 = blocks.append('block1')
167
+ exit = blocks.append('exit')
168
+
169
+ entry.build do
170
+ cond(icmp(:eq, fun.params[0], RLTK::CG::NativeInt.new(0)), block0, block1)
171
+ end
172
+
173
+ result0 =
174
+ block0.build do
175
+ add(fun.params[0], RLTK::CG::NativeInt.new(1)).tap { br(exit) }
176
+ end
177
+
178
+ result1 =
179
+ block1.build do
180
+ sub(fun.params[0], RLTK::CG::NativeInt.new(1)).tap { br(exit) }
181
+ end
182
+
183
+ exit.build do
184
+ ret(phi(RLTK::CG::NativeIntType, {block0 => result0, block1 => result1}))
185
+ end
186
+ end
187
+
188
+ assert_equal(1, @jit.run_function(fun, 0).to_i)
189
+ assert_equal(0, @jit.run_function(fun, 1).to_i)
190
+ end
191
+ end
@@ -0,0 +1,54 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/09
4
+ # Description: This file contains unit tests for the RLTK::CG::Function class.
5
+
6
+ ############
7
+ # Requires #
8
+ ############
9
+
10
+ # Gems
11
+ require 'minitest/autorun'
12
+
13
+ # Ruby Language Toolkit
14
+ require 'rltk/cg/llvm'
15
+ require 'rltk/cg/module'
16
+ require 'rltk/cg/function'
17
+ require 'rltk/cg/type'
18
+
19
+ class FunctionTester < Minitest::Test
20
+ def setup
21
+ @mod = RLTK::CG::Module.new('Testing Module')
22
+ @fun = @mod.functions.add('testing_function', RLTK::CG::NativeIntType, [RLTK::CG::NativeIntType, RLTK::CG::NativeIntType])
23
+
24
+ @fun.params[0].name = 'foo'
25
+ @fun.params[1].name = 'bar'
26
+ end
27
+
28
+ def test_equality
29
+ fun0 = @mod.functions.add('fun0', RLTK::CG::NativeIntType, [])
30
+ fun1 = @mod.functions.add('fun0', RLTK::CG::FloatType, [])
31
+ fun2 = RLTK::CG::Function.new(fun0.ptr)
32
+
33
+ assert_equal(fun0, fun2)
34
+ refute_equal(fun0, fun1)
35
+ end
36
+
37
+ def test_positive_index_in_range
38
+ assert_equal('foo', @fun.params[0].name)
39
+ assert_equal('bar', @fun.params[1].name)
40
+ end
41
+
42
+ def test_negative_index_in_range
43
+ assert_equal('bar', @fun.params[-1].name)
44
+ assert_equal('foo', @fun.params[-2].name)
45
+ end
46
+
47
+ def test_positive_index_out_of_range
48
+ assert_nil(@fun.params[2])
49
+ end
50
+
51
+ def test_negative_index_out_of_range
52
+ assert_nil(@fun.params[-3])
53
+ end
54
+ end
@@ -0,0 +1,33 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/09
4
+ # Description: This file contains unit tests for the RLTK::CG::GenericValue
5
+ # class.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Gems
12
+ require 'minitest/autorun'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/cg/generic_value'
16
+
17
+ class GenericValueTester < Minitest::Test
18
+ def setup
19
+ RLTK::CG::LLVM.init(:X86)
20
+ end
21
+
22
+ def test_integer
23
+ assert_equal(2, RLTK::CG::GenericValue.new(2).to_i)
24
+ end
25
+
26
+ def test_float
27
+ assert_in_delta(3.1415926, RLTK::CG::GenericValue.new(3.1415926).to_f, 1e-6)
28
+ end
29
+
30
+ def test_double
31
+ assert_in_delta(3.1415926, RLTK::CG::GenericValue.new(3.1415926, RLTK::CG::DoubleType).to_f(RLTK::CG::DoubleType), 1e-6)
32
+ end
33
+ end
@@ -0,0 +1,256 @@
1
+ # Author: Chris Wailes <chris.wailes@gmail.com>
2
+ # Project: Ruby Language Toolkit
3
+ # Date: 2012/05/09
4
+ # Description: This file contains unit tests for the RLTK::CG::Instruction
5
+ # class.
6
+
7
+ ############
8
+ # Requires #
9
+ ############
10
+
11
+ # Gems
12
+ require 'minitest/autorun'
13
+
14
+ # Ruby Language Toolkit
15
+ require 'rltk/cg/llvm'
16
+ require 'rltk/cg/module'
17
+ require 'rltk/cg/instruction'
18
+
19
+ class InstructionTester < Minitest::Test
20
+ def setup
21
+ RLTK::CG::LLVM.init(:X86)
22
+
23
+ @mod = RLTK::CG::Module.new('Testing Module')
24
+ @jit = RLTK::CG::JITCompiler.new(@mod)
25
+ end
26
+
27
+ def test_float_comparison
28
+ fcmp_assert(:oeq, 1.0, 1.0, true )
29
+ fcmp_assert(:one, 1.0, 1.0, false)
30
+ fcmp_assert(:ogt, 2.0, 2.0, false)
31
+ fcmp_assert(:oge, 2.0, 1.0, true )
32
+ fcmp_assert(:olt, 1.0, 1.0, false)
33
+ fcmp_assert(:ole, 1.0, 2.0, true )
34
+ fcmp_assert(:ord, 1.0, 2.0, true )
35
+ fcmp_assert(:ueq, 1.0, 1.0, true )
36
+ fcmp_assert(:une, 1.0, 1.0, false)
37
+ fcmp_assert(:ugt, 2.0, 2.0, false)
38
+ fcmp_assert(:uge, 2.0, 1.0, true )
39
+ fcmp_assert(:ult, 1.0, 1.0, false)
40
+ fcmp_assert(:ule, 1.0, 2.0, true )
41
+ fcmp_assert(:uno, 1.0, 2.0, false)
42
+ end
43
+
44
+ def test_instruction
45
+ fun = @mod.functions.add('instruction_tester', RLTK::CG::DoubleType, [RLTK::CG::DoubleType]) do |fun|
46
+ blocks.append do
47
+ ret(fadd(fun.params[0], RLTK::CG::Double.new(3.0)))
48
+ end
49
+ end
50
+
51
+ entry = fun.blocks.entry
52
+
53
+ inst0 = entry.instructions.first
54
+ inst1 = entry.instructions.last
55
+
56
+ assert_kind_of(RLTK::CG::Instruction, inst0)
57
+ assert_kind_of(RLTK::CG::Instruction, inst1)
58
+
59
+ assert_equal(inst1, inst0.next)
60
+ assert_equal(inst0, inst1.previous)
61
+
62
+ assert_equal(entry, inst0.parent)
63
+ assert_equal(entry, inst1.parent)
64
+ end
65
+
66
+ def test_integer_comparison
67
+ icmp_assert(:eq, 1, 1, true, true )
68
+ icmp_assert(:ne, 1, 1, true, false)
69
+ icmp_assert(:ugt, 2, 2, false, false)
70
+ icmp_assert(:uge, 2, 1, false, true )
71
+ icmp_assert(:ult, 1, 1, false, false)
72
+ icmp_assert(:ule, 1, 2, false, true )
73
+ icmp_assert(:sgt, -2, 2, true, false)
74
+ icmp_assert(:sge, -2, 1, true, false)
75
+ icmp_assert(:slt, -1, 2, true, true )
76
+ icmp_assert(:sle, -1, 2, true, true )
77
+ end
78
+
79
+ def test_array_memory_access
80
+ fun = @mod.functions.add('array_memory_access_tester', RLTK::CG::NativeIntType,
81
+ [RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
82
+
83
+ blocks.append do
84
+ ptr = array_alloca(RLTK::CG::NativeIntType, RLTK::CG::NativeInt.new(2))
85
+
86
+ store(fun.params[0], gep(ptr, [RLTK::CG::NativeInt.new(0)]))
87
+ store(fun.params[1], gep(ptr, [RLTK::CG::NativeInt.new(1)]))
88
+
89
+ ret(add(load(gep(ptr, [RLTK::CG::NativeInt.new(0)])), load(gep(ptr, [RLTK::CG::NativeInt.new(1)]))))
90
+ end
91
+ end
92
+
93
+ assert_equal(3, @jit.run_function(fun, 1, 2).to_i)
94
+ end
95
+
96
+ def test_simple_memory_access
97
+ fun = @mod.functions.add('simple_memory_access_tester', RLTK::CG::NativeIntType,
98
+ [RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
99
+
100
+ blocks.append do
101
+ p0 = alloca(RLTK::CG::NativeIntType)
102
+ p1 = alloca(RLTK::CG::NativeIntType)
103
+
104
+ store(fun.params[0], p0)
105
+ store(fun.params[1], p1)
106
+
107
+ ret(add(load(p0), load(p1)))
108
+ end
109
+ end
110
+
111
+ assert_equal(3, @jit.run_function(fun, 1, 2).to_i)
112
+ end
113
+
114
+ def test_struct_access
115
+ fun = @mod.functions.add('struct_access_tester', RLTK::CG::FloatType, [RLTK::CG::NativeIntType, RLTK::CG::FloatType]) do |fun|
116
+ blocks.append do
117
+ st0 = RLTK::CG::StructType.new([RLTK::CG::NativeIntType, RLTK::CG::FloatType])
118
+ st1 = RLTK::CG::StructType.new([RLTK::CG::FloatType, st0, RLTK::CG::NativeIntType])
119
+
120
+ ptr = alloca(st1)
121
+
122
+ store(fun.params[0], gep(ptr, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1), RLTK::CG::NativeInt.new(0)]))
123
+ store(fun.params[1], gep(ptr, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1), RLTK::CG::NativeInt.new(1)]))
124
+
125
+ addr0 = gep(ptr, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1), RLTK::CG::NativeInt.new(0)])
126
+ addr1 = gep(ptr, [RLTK::CG::NativeInt.new(0), RLTK::CG::NativeInt.new(1), RLTK::CG::NativeInt.new(1)])
127
+
128
+ ret(fadd(ui2fp(load(addr0), RLTK::CG::FloatType), load(addr1)))
129
+ end
130
+ end
131
+
132
+ assert_in_delta(5.3, @jit.run_function(fun, 2, 3.3).to_f, 0.001)
133
+ end
134
+
135
+ def test_struct_values
136
+ fun = @mod.functions.add('struct_values_tester', RLTK::CG::NativeIntType, [RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]) do |fun|
137
+ blocks.append do
138
+ ptr = alloca(RLTK::CG::StructType.new([RLTK::CG::NativeIntType, RLTK::CG::NativeIntType]))
139
+
140
+ struct = load(ptr)
141
+ struct = insert_value(struct, fun.params[0], 0)
142
+ struct = insert_value(struct, fun.params[1], 1)
143
+
144
+ ret(add(extract_value(struct, 0), extract_value(struct, 1)))
145
+ end
146
+ end
147
+
148
+ assert_equal(5, @jit.run_function(fun, 2, 3).to_i)
149
+ end
150
+
151
+ ####################
152
+ # Conversion Tests #
153
+ ####################
154
+
155
+ def test_bitcast
156
+ difftype_assert(:bitcast, RLTK::CG::Int8.new(255), RLTK::CG::Int8Type, :integer, -1)
157
+ end
158
+
159
+ def test_fp2ui
160
+ difftype_assert(:fp2ui, RLTK::CG::Double.new(123.3), RLTK::CG::Int32Type, :integer, 123)
161
+ difftype_assert(:fp2ui, RLTK::CG::Double.new(0.7), RLTK::CG::Int32Type, :integer, 0)
162
+ difftype_assert(:fp2ui, RLTK::CG::Double.new(1.7), RLTK::CG::Int32Type, :integer, 1)
163
+ end
164
+
165
+ def test_fp2si
166
+ difftype_assert(:fp2si, RLTK::CG::Double.new(-123.3), RLTK::CG::Int32Type, :integer, -123)
167
+ difftype_assert(:fp2si, RLTK::CG::Double.new(0.7), RLTK::CG::Int32Type, :integer, 0)
168
+ difftype_assert(:fp2si, RLTK::CG::Double.new(1.7), RLTK::CG::Int32Type, :integer, 1)
169
+ end
170
+
171
+ def test_fpext
172
+ fconv_assert(:fp_ext, RLTK::CG::Float.new(123.0), RLTK::CG::DoubleType, 123.0)
173
+ fconv_assert(:fp_ext, RLTK::CG::Float.new(123.0), RLTK::CG::FloatType, 123.0)
174
+ end
175
+
176
+ def test_fptrunc
177
+ fconv_assert(:fp_trunc, RLTK::CG::Double.new(123.0), RLTK::CG::FloatType, 123.0)
178
+ end
179
+
180
+ def test_int64
181
+ iconv_assert(:zext, RLTK::CG::Int64.new( 2**62 + 123), RLTK::CG::Int64Type, true, 2**62 + 123)
182
+ iconv_assert(:zext, RLTK::CG::Int64.new(-2**62 - 123), RLTK::CG::Int64Type, true, -2**62 - 123)
183
+ iconv_assert(:zext, RLTK::CG::Int64.new( 2**63 + 123), RLTK::CG::Int64Type, false, 2**63 + 123)
184
+ end
185
+
186
+ def test_sext
187
+ iconv_assert(:sext, RLTK::CG::Int1.new(1), RLTK::CG::Int32Type, true, -1)
188
+ iconv_assert(:sext, RLTK::CG::Int8.new(-1), RLTK::CG::Int16Type, false, 65535)
189
+ end
190
+
191
+ def test_si2fp
192
+ difftype_assert(:si2fp, RLTK::CG::Int32.new(257), RLTK::CG::FloatType, :float, 257.0)
193
+ difftype_assert(:si2fp, RLTK::CG::Int8.new(-1), RLTK::CG::DoubleType, :float, -1.0)
194
+ end
195
+
196
+ def test_truncate
197
+ iconv_assert(:trunc, RLTK::CG::Int32.new(257), RLTK::CG::Int8Type, false, 1)
198
+ iconv_assert(:trunc, RLTK::CG::Int32.new(123), RLTK::CG::Int1Type, false, 1)
199
+ iconv_assert(:trunc, RLTK::CG::Int32.new(122), RLTK::CG::Int1Type, false, 0)
200
+ end
201
+
202
+ def test_ui2fp
203
+ difftype_assert(:ui2fp, RLTK::CG::Int32.new(257), RLTK::CG::FloatType, :float, 257.0)
204
+ difftype_assert(:ui2fp, RLTK::CG::Int8.new(-1), RLTK::CG::DoubleType, :float, 255.0)
205
+ end
206
+
207
+ def test_zext
208
+ iconv_assert(:zext, RLTK::CG::Int16.new(257), RLTK::CG::Int32Type, false, 257)
209
+ end
210
+
211
+ ##################
212
+ # Helper Methods #
213
+ ##################
214
+
215
+ def difftype_assert(op, operand, ret_type, assert_type, expected)
216
+ res = run_convert(op, operand, ret_type)
217
+
218
+ if assert_type == :integer then assert_equal(expected, res.to_i) else assert_in_delta(expected, res.to_f(ret_type), 0.001) end
219
+ end
220
+
221
+ def fcmp_assert(mode, operand0, operand1, expected)
222
+ res = run_cmp(:fcmp, mode, RLTK::CG::Float.new(operand0), RLTK::CG::Float.new(operand1), RLTK::CG::Int1Type).to_i(false)
223
+ assert_equal(expected.to_i, res)
224
+ end
225
+
226
+ def icmp_assert(mode, operand0, operand1, signed, expected)
227
+ res = run_cmp(:icmp, mode, RLTK::CG::NativeInt.new(operand0, signed),
228
+ RLTK::CG::NativeInt.new(operand1, signed), RLTK::CG::Int1Type).to_i(false)
229
+
230
+ assert_equal(expected.to_i, res)
231
+ end
232
+
233
+ def fconv_assert(op, operand, ret_type, expected)
234
+ assert_in_delta(expected, run_convert(op, operand, ret_type).to_f(ret_type), 0.001)
235
+ end
236
+
237
+ def iconv_assert(op, operand, ret_type, signed, expected)
238
+ assert_equal(expected, run_convert(op, operand, ret_type).to_i(signed))
239
+ end
240
+
241
+ def run_cmp(op, mode, operand0, operand1, ret_type)
242
+ fun = @mod.functions.add("#{op}_#{mode}_tester", ret_type, []) do
243
+ blocks.append { ret(self.send(op, mode, operand0, operand1)) }
244
+ end
245
+
246
+ @jit.run_function(fun)
247
+ end
248
+
249
+ def run_convert(op, operand, ret_type)
250
+ fun = @mod.functions.add("#{op}_tester", ret_type, []) do
251
+ blocks.append { ret(self.send(op, operand, ret_type)) }
252
+ end
253
+
254
+ @jit.run_function(fun)
255
+ end
256
+ end