rltk 2.2.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|