rltk 2.2.1 → 3.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 (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