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.
- checksums.yaml +7 -0
- data/LICENSE +12 -12
- data/README.md +458 -285
- data/Rakefile +99 -92
- data/lib/rltk/ast.rb +221 -126
- data/lib/rltk/cfg.rb +218 -239
- data/lib/rltk/cg/basic_block.rb +1 -1
- data/lib/rltk/cg/bindings.rb +9 -26
- data/lib/rltk/cg/builder.rb +40 -8
- data/lib/rltk/cg/context.rb +1 -1
- data/lib/rltk/cg/contractor.rb +51 -0
- data/lib/rltk/cg/execution_engine.rb +45 -8
- data/lib/rltk/cg/function.rb +12 -2
- data/lib/rltk/cg/generated_bindings.rb +2541 -575
- data/lib/rltk/cg/generic_value.rb +2 -2
- data/lib/rltk/cg/instruction.rb +104 -83
- data/lib/rltk/cg/llvm.rb +44 -3
- data/lib/rltk/cg/memory_buffer.rb +22 -5
- data/lib/rltk/cg/module.rb +85 -36
- data/lib/rltk/cg/old_generated_bindings.rb +6152 -0
- data/lib/rltk/cg/pass_manager.rb +87 -43
- data/lib/rltk/cg/support.rb +2 -4
- data/lib/rltk/cg/target.rb +158 -28
- data/lib/rltk/cg/triple.rb +8 -8
- data/lib/rltk/cg/type.rb +69 -25
- data/lib/rltk/cg/value.rb +107 -66
- data/lib/rltk/cg.rb +16 -17
- data/lib/rltk/lexer.rb +21 -11
- data/lib/rltk/lexers/calculator.rb +1 -1
- data/lib/rltk/lexers/ebnf.rb +8 -7
- data/lib/rltk/parser.rb +300 -247
- data/lib/rltk/parsers/infix_calc.rb +1 -1
- data/lib/rltk/parsers/postfix_calc.rb +2 -2
- data/lib/rltk/parsers/prefix_calc.rb +2 -2
- data/lib/rltk/token.rb +1 -2
- data/lib/rltk/version.rb +3 -3
- data/lib/rltk.rb +6 -6
- data/test/cg/tc_basic_block.rb +83 -0
- data/test/cg/tc_control_flow.rb +191 -0
- data/test/cg/tc_function.rb +54 -0
- data/test/cg/tc_generic_value.rb +33 -0
- data/test/cg/tc_instruction.rb +256 -0
- data/test/cg/tc_llvm.rb +25 -0
- data/test/cg/tc_math.rb +88 -0
- data/test/cg/tc_module.rb +89 -0
- data/test/cg/tc_transforms.rb +68 -0
- data/test/cg/tc_type.rb +69 -0
- data/test/cg/tc_value.rb +151 -0
- data/test/cg/ts_cg.rb +23 -0
- data/test/tc_ast.rb +105 -8
- data/test/tc_cfg.rb +63 -48
- data/test/tc_lexer.rb +84 -96
- data/test/tc_parser.rb +224 -52
- data/test/tc_token.rb +6 -6
- data/test/ts_rltk.rb +12 -15
- metadata +149 -75
- data/lib/rltk/cg/generated_extended_bindings.rb +0 -287
- data/lib/rltk/util/abstract_class.rb +0 -25
- data/lib/rltk/util/monkeys.rb +0 -129
data/lib/rltk/token.rb
CHANGED
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
|
6
|
+
module RLTK
|
7
7
|
# The version number of the RLTK library.
|
8
|
-
VERSION = '
|
8
|
+
VERSION = '3.0.0'
|
9
9
|
# The version of LLVM targeted by RLTK.
|
10
|
-
LLVM_TARGET_VERSION = '3.
|
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,
|
11
|
-
autoload :CFG,
|
12
|
-
autoload :CG,
|
13
|
-
autoload :Lexer,
|
14
|
-
autoload :Parser,
|
15
|
-
autoload :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
|