tombagby-llvmruby 0.0.1
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.
- data/COPYING +21 -0
- data/README +76 -0
- data/Rakefile +31 -0
- data/ext/extconf.rb +14 -0
- data/ext/llvm_basicblock.cpp +296 -0
- data/ext/llvm_function.cpp +48 -0
- data/ext/llvm_instruction.cpp +125 -0
- data/ext/llvm_module.cpp +189 -0
- data/ext/llvm_value.cpp +128 -0
- data/ext/llvmruby.c +214 -0
- data/ext/llvmruby.h +60 -0
- data/lib/llvm.rb +142 -0
- data/lib/ruby_vm.rb +352 -0
- data/lib/version.rb +11 -0
- data/test/byteswap.bc +0 -0
- data/test/test_basic.rb +323 -0
- data/test/test_basic_block.rb +65 -0
- data/test/test_instructions.rb +46 -0
- data/test/test_read_bitcode.rb +38 -0
- data/test/test_ruby_vm.rb +172 -0
- metadata +79 -0
data/test/test_basic.rb
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'llvm'
|
|
3
|
+
|
|
4
|
+
include LLVM
|
|
5
|
+
|
|
6
|
+
class BasicTests < Test::Unit::TestCase
|
|
7
|
+
def function_tester(expected)
|
|
8
|
+
m = LLVM::Module.new("test_module")
|
|
9
|
+
type = Type::function(MACHINE_WORD, [])
|
|
10
|
+
f = m.get_or_insert_function("test", type)
|
|
11
|
+
yield(f)
|
|
12
|
+
ExecutionEngine.get(m);
|
|
13
|
+
assert_equal(expected, ExecutionEngine.run_autoconvert(f))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_module
|
|
17
|
+
function_tester(5) do |f|
|
|
18
|
+
b = f.create_block.builder
|
|
19
|
+
v = b.add(2.llvm, 3.llvm)
|
|
20
|
+
b.return(v)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def bin_op(op, v1, v2, expected)
|
|
25
|
+
function_tester(expected) do |f|
|
|
26
|
+
b = f.create_block.builder
|
|
27
|
+
ret = b.bin_op(op, v1.llvm, v2.llvm)
|
|
28
|
+
b.return(ret)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_bin_ops
|
|
33
|
+
bin_op(Instruction::Add, 2, 3, 5)
|
|
34
|
+
bin_op(Instruction::Sub, 5, 3, 2)
|
|
35
|
+
bin_op(Instruction::Mul, 2, 3, 6)
|
|
36
|
+
bin_op(Instruction::UDiv, 42, 6, 7)
|
|
37
|
+
bin_op(Instruction::SDiv, 42, 6, 7)
|
|
38
|
+
#bin_op(Instruction::FDiv, 23.0, 5, 0.23)
|
|
39
|
+
bin_op(Instruction::URem, 23, 5, 3)
|
|
40
|
+
bin_op(Instruction::SRem, 23, 5, 3)
|
|
41
|
+
#bin_op(Instruction::FRem, 23.0, 5, 0.23)
|
|
42
|
+
|
|
43
|
+
bin_op(Instruction::Shl, 2, 1, 4)
|
|
44
|
+
bin_op(Instruction::LShr, 8, 1, 4)
|
|
45
|
+
#bin_op(Instruction::AShr, 8, 1, 4)
|
|
46
|
+
bin_op(Instruction::And, 8, 15, 8)
|
|
47
|
+
bin_op(Instruction::Or, 8, 15, 15)
|
|
48
|
+
bin_op(Instruction::Xor, 8, 15, 7)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def builder_bin_op(op, v1, v2, expected)
|
|
52
|
+
function_tester(expected) do |f|
|
|
53
|
+
b = f.create_block.builder
|
|
54
|
+
ret = b.send(op, v1.llvm, v2.llvm)
|
|
55
|
+
b.return(ret)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_builder_bin_ops
|
|
60
|
+
builder_bin_op(:add, 23, 42, 65)
|
|
61
|
+
builder_bin_op(:sub, 69, 13, 56)
|
|
62
|
+
builder_bin_op(:mul, 23, 5, 115)
|
|
63
|
+
builder_bin_op(:udiv, 23, 5, 4)
|
|
64
|
+
builder_bin_op(:sdiv, 99, 33, 3)
|
|
65
|
+
#builder_bin_op(:fdiv, 23, 42, 65)
|
|
66
|
+
builder_bin_op(:urem, 23, 42, 23)
|
|
67
|
+
builder_bin_op(:srem, 77, 5, 2)
|
|
68
|
+
#builder_bin_op(:frem, 23, 42, 65)
|
|
69
|
+
builder_bin_op(:shl, 15, 1, 30)
|
|
70
|
+
builder_bin_op(:lshr, 32, 2, 8)
|
|
71
|
+
#builder_bin_op(:ashr, 23, 42, 65)
|
|
72
|
+
builder_bin_op(:and, 32, 37, 32)
|
|
73
|
+
builder_bin_op(:or, 15, 8, 15)
|
|
74
|
+
builder_bin_op(:xor, 33, 15, 46)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_insert_point
|
|
78
|
+
function_tester(2) do |f|
|
|
79
|
+
b1 = f.create_block
|
|
80
|
+
b2 = f.create_block
|
|
81
|
+
builder = b1.builder
|
|
82
|
+
builder.br(b2)
|
|
83
|
+
builder.set_insert_point(b2)
|
|
84
|
+
builder.return(2.llvm)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_builder_utils
|
|
89
|
+
function_tester(5) do |f|
|
|
90
|
+
b = f.create_block.builder
|
|
91
|
+
b.write do
|
|
92
|
+
ret = add(2.llvm, 3.llvm)
|
|
93
|
+
self.return(ret)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_cmps
|
|
99
|
+
m = LLVM::Module.new("test_cmps")
|
|
100
|
+
type = Type.function(MACHINE_WORD, [])
|
|
101
|
+
f = m.get_or_insert_function("sgt", type)
|
|
102
|
+
|
|
103
|
+
entry_block = f.create_block
|
|
104
|
+
exit_block_true = f.create_block
|
|
105
|
+
exit_block_false = f.create_block
|
|
106
|
+
|
|
107
|
+
b = entry_block.builder
|
|
108
|
+
cmp = b.icmp_sgt(-1.llvm, 1.llvm)
|
|
109
|
+
b.cond_br(cmp, exit_block_true, exit_block_false)
|
|
110
|
+
|
|
111
|
+
b = exit_block_true.builder
|
|
112
|
+
b.return(1.llvm)
|
|
113
|
+
|
|
114
|
+
b = exit_block_false.builder
|
|
115
|
+
b.return(0.llvm)
|
|
116
|
+
|
|
117
|
+
ExecutionEngine.get(m)
|
|
118
|
+
result = ExecutionEngine.run_autoconvert(f)
|
|
119
|
+
assert_equal(0, result)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def test_fcmps
|
|
123
|
+
m = LLVM::Module.new('test_fcmps')
|
|
124
|
+
type = Type.function(MACHINE_WORD, [])
|
|
125
|
+
f = m.get_or_insert_function('ult', type)
|
|
126
|
+
|
|
127
|
+
entry_block = f.create_block
|
|
128
|
+
exit_block_true = f.create_block
|
|
129
|
+
exit_block_false = f.create_block
|
|
130
|
+
|
|
131
|
+
b = entry_block.builder
|
|
132
|
+
cmp = b.fcmp_ult(1.0.llvm, 2.0.llvm)
|
|
133
|
+
b.cond_br(cmp, exit_block_true, exit_block_false)
|
|
134
|
+
|
|
135
|
+
b = exit_block_true.builder
|
|
136
|
+
b.return(0.llvm)
|
|
137
|
+
|
|
138
|
+
b = exit_block_false.builder
|
|
139
|
+
b.return(1.llvm)
|
|
140
|
+
|
|
141
|
+
ExecutionEngine.get(m)
|
|
142
|
+
result = ExecutionEngine.run_autoconvert(f)
|
|
143
|
+
assert_equal(0, result)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_function_calls
|
|
147
|
+
m = LLVM::Module.new('test_module')
|
|
148
|
+
type = Type::function(MACHINE_WORD, [])
|
|
149
|
+
f_caller = m.get_or_insert_function("caller", type)
|
|
150
|
+
type = Type::function(MACHINE_WORD, [MACHINE_WORD, MACHINE_WORD])
|
|
151
|
+
f_callee = m.get_or_insert_function("callee", type)
|
|
152
|
+
|
|
153
|
+
b = f_callee.create_block.builder
|
|
154
|
+
x, y = f_callee.arguments
|
|
155
|
+
sum = b.add(x, y)
|
|
156
|
+
b.return(sum)
|
|
157
|
+
|
|
158
|
+
b = f_caller.create_block.builder
|
|
159
|
+
ret = b.call(f_callee, 2.llvm, 3.llvm)
|
|
160
|
+
b.return(ret)
|
|
161
|
+
|
|
162
|
+
ExecutionEngine.get(m)
|
|
163
|
+
result = ExecutionEngine.run_autoconvert(f_caller)
|
|
164
|
+
assert_equal(5, result)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def test_phi_node
|
|
168
|
+
m = LLVM::Module.new('test_module')
|
|
169
|
+
type = Type::function(MACHINE_WORD, [])
|
|
170
|
+
f = m.get_or_insert_function('phi_node', type)
|
|
171
|
+
|
|
172
|
+
entry_block = f.create_block
|
|
173
|
+
loop_block = f.create_block
|
|
174
|
+
exit_block = f.create_block
|
|
175
|
+
|
|
176
|
+
b = entry_block.builder
|
|
177
|
+
b.br(loop_block)
|
|
178
|
+
|
|
179
|
+
b = loop_block.builder
|
|
180
|
+
phi = b.phi(MACHINE_WORD)
|
|
181
|
+
phi.add_incoming(0.llvm, entry_block)
|
|
182
|
+
count = b.add(phi, 1.llvm)
|
|
183
|
+
phi.add_incoming(count, loop_block)
|
|
184
|
+
cmp = b.icmp_ult(count, 10.llvm)
|
|
185
|
+
b.cond_br(cmp, loop_block, exit_block)
|
|
186
|
+
|
|
187
|
+
b = exit_block.builder
|
|
188
|
+
b.return(phi)
|
|
189
|
+
|
|
190
|
+
ExecutionEngine.get(m)
|
|
191
|
+
result = ExecutionEngine.run_autoconvert(f)
|
|
192
|
+
assert_equal(9, result)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_bitcode_writer
|
|
196
|
+
m = LLVM::Module.new('static_module')
|
|
197
|
+
# create main function
|
|
198
|
+
type = Type.function(Type::Int32Ty, [
|
|
199
|
+
Type::Int32Ty,
|
|
200
|
+
Type.pointer(Type.pointer(Type::Int8Ty))
|
|
201
|
+
])
|
|
202
|
+
f = m.get_or_insert_function('main', type)
|
|
203
|
+
b = f.create_block.builder
|
|
204
|
+
b.return(666.llvm(Type::Int32Ty))
|
|
205
|
+
|
|
206
|
+
m.write_bitcode("test/static.o")
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def test_type_errors
|
|
210
|
+
m = LLVM::Module.new('type_errors')
|
|
211
|
+
ftype = Type.function(Type::Int32Ty, [])
|
|
212
|
+
assert_raise(TypeError) { f = LLVM::Module.new(5) }
|
|
213
|
+
assert_raise(TypeError) { m.get_or_insert_function(5, ftype) }
|
|
214
|
+
assert_raise(TypeError) { m.get_or_insert_function('bad_arg', 5) }
|
|
215
|
+
assert_raise(TypeError) { ExecutionEngine.get(5) }
|
|
216
|
+
assert_raise(TypeError) { m.external_function(5, ftype) }
|
|
217
|
+
assert_raise(TypeError) { m.external_function('fname', 5) }
|
|
218
|
+
assert_raise(TypeError) { m.write_bitcode(5) }
|
|
219
|
+
assert_raise(ArgumentError) { ExecutionEngine.run_function }
|
|
220
|
+
assert_raise(TypeError) { ExecutionEngine.run_function(5) }
|
|
221
|
+
assert_raise(TypeError) { ExecutionEngine.run_function(5, 5) }
|
|
222
|
+
|
|
223
|
+
f = m.get_or_insert_function('test', ftype)
|
|
224
|
+
block1 = f.create_block
|
|
225
|
+
block2 = f.create_block
|
|
226
|
+
b = block1.builder
|
|
227
|
+
assert_raise(TypeError) { b.set_insert_point(5) }
|
|
228
|
+
assert_raise(TypeError) { b.phi(5) }
|
|
229
|
+
phi = b.phi(Type::Int32Ty)
|
|
230
|
+
assert_raise(TypeError) { phi.add_incoming(5, 5) }
|
|
231
|
+
assert_raise(TypeError) { phi.add_incoming(5.llvm(Type::Int32Ty), 5) }
|
|
232
|
+
assert_raise(TypeError) { b.bin_op([], 2.llvm, 3.llvm) }
|
|
233
|
+
assert_raise(TypeError) { b.bin_op(Instruction::Add, 5, 3.llvm) }
|
|
234
|
+
assert_raise(TypeError) { b.bin_op(Instruction::Add, 3.llvm, 5) }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def test_inspectors
|
|
238
|
+
m = LLVM::Module.new('example')
|
|
239
|
+
ftype = Type.function(Type::Int32Ty, [])
|
|
240
|
+
f = m.get_or_insert_function('inspect', ftype)
|
|
241
|
+
b = f.create_block.builder
|
|
242
|
+
b.return(5.llvm(Type::Int32Ty))
|
|
243
|
+
|
|
244
|
+
assert_match(/define i32 @inspect\(\)/, m.inspect)
|
|
245
|
+
assert_match(/define i32 @inspect\(\)/, f.inspect)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def test_global_strings
|
|
249
|
+
m = LLVM::Module.new('globalstrings')
|
|
250
|
+
ftype = Type.function(Type::Int32Ty, [])
|
|
251
|
+
f = m.get_or_insert_function('use_global_strings', ftype)
|
|
252
|
+
b = f.create_block.builder
|
|
253
|
+
v = b.create_global_string_ptr("SHAKA KHAN")
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def test_var_arg_ftypes
|
|
257
|
+
ftype = Type.function(Type::Int32Ty, [], true)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def test_struct_constants
|
|
261
|
+
int_t = Type::Int32Ty
|
|
262
|
+
struct_type = Type.struct([int_t, int_t, int_t])
|
|
263
|
+
struct_const = Value.get_struct_constant(struct_type, 2.llvm(int_t), 3.llvm(int_t), 5.llvm(int_t))
|
|
264
|
+
assert_kind_of(Value, struct_const)
|
|
265
|
+
|
|
266
|
+
m = LLVM::Module.new('globals')
|
|
267
|
+
gv = m.global_variable(struct_type, struct_const)
|
|
268
|
+
assert_kind_of(Value, gv)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def test_malloc_free
|
|
272
|
+
function_tester(23) do |f|
|
|
273
|
+
b = f.create_block.builder
|
|
274
|
+
new_space = b.malloc(MACHINE_WORD, 1)
|
|
275
|
+
b.store(23.llvm(MACHINE_WORD), new_space)
|
|
276
|
+
v = b.load(new_space)
|
|
277
|
+
b.free(new_space)
|
|
278
|
+
b.return(v)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def test_cast
|
|
283
|
+
function_tester(5) do |f|
|
|
284
|
+
b = f.create_block.builder
|
|
285
|
+
b.return(b.cast(Instruction::FPToSI, 5.0.llvm, MACHINE_WORD))
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def test_switch
|
|
290
|
+
function_tester(23) do |f|
|
|
291
|
+
b = f.create_block.builder
|
|
292
|
+
default = f.create_block
|
|
293
|
+
on5 = f.create_block
|
|
294
|
+
switch = b.switch(5.llvm, default)
|
|
295
|
+
switch.add_case(5.llvm, on5)
|
|
296
|
+
assert_instance_of(SwitchInst, switch)
|
|
297
|
+
assert_equal(2, switch.get_num_cases);
|
|
298
|
+
|
|
299
|
+
b = default.builder
|
|
300
|
+
b.return(7.llvm(MACHINE_WORD))
|
|
301
|
+
|
|
302
|
+
b = on5.builder
|
|
303
|
+
b.return(23.llvm)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def test_vector
|
|
308
|
+
function_tester(666) do |f|
|
|
309
|
+
b = f.create_block.builder
|
|
310
|
+
vt = Type.vector(MACHINE_WORD, 3)
|
|
311
|
+
vp = b.alloca(vt, 0)
|
|
312
|
+
v = b.load(vp)
|
|
313
|
+
v2 = b.insert_element(v, 666.llvm(MACHINE_WORD), 0.llvm(Type::Int32Ty))
|
|
314
|
+
r = b.extract_element(v2, 0.llvm(Type::Int32Ty))
|
|
315
|
+
b.return(r)
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def test_pass_manager_run
|
|
320
|
+
m = LLVM::Module.new('test')
|
|
321
|
+
assert PassManager.new.run(m)
|
|
322
|
+
end
|
|
323
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'llvm'
|
|
3
|
+
|
|
4
|
+
include LLVM
|
|
5
|
+
|
|
6
|
+
class BasicBlockTests < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
|
|
10
|
+
@assembly_gcd=<<-EOF
|
|
11
|
+
; ModuleID = 'gcd.o'
|
|
12
|
+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
|
13
|
+
target triple = "i386-apple-darwin9"
|
|
14
|
+
|
|
15
|
+
define i32 @gcd(i32 %a, i32 %b) nounwind {
|
|
16
|
+
entry:
|
|
17
|
+
%tmp2 = icmp eq i32 %a, 0 ; <i1> [#uses=1]
|
|
18
|
+
br i1 %tmp2, label %bb26, label %bb19
|
|
19
|
+
|
|
20
|
+
bb5: ; preds = %bb19, %bb11
|
|
21
|
+
%indvar48 = phi i32 [ %indvar.next49, %bb11 ], [ 0, %bb19 ] ; <i32> [#uses=2]
|
|
22
|
+
%tmp50 = sub i32 0, %b_addr.0 ; <i32> [#uses=1]
|
|
23
|
+
%tmp51 = mul i32 %indvar48, %tmp50 ; <i32> [#uses=1]
|
|
24
|
+
%a_addr.0.reg2mem.0 = add i32 %tmp51, %a_addr.0 ; <i32> [#uses=3]
|
|
25
|
+
%tmp8 = icmp sgt i32 %a_addr.0.reg2mem.0, %b_addr.0 ; <i1> [#uses=1]
|
|
26
|
+
br i1 %tmp8, label %bb11, label %bb15.split
|
|
27
|
+
|
|
28
|
+
bb11: ; preds = %bb5
|
|
29
|
+
%indvar.next49 = add i32 %indvar48, 1 ; <i32> [#uses=1]
|
|
30
|
+
br label %bb5
|
|
31
|
+
|
|
32
|
+
bb15.split: ; preds = %bb5
|
|
33
|
+
%tmp18 = sub i32 %b_addr.0, %a_addr.0.reg2mem.0 ; <i32> [#uses=1]
|
|
34
|
+
br label %bb19
|
|
35
|
+
|
|
36
|
+
bb19: ; preds = %bb15.split, %entry
|
|
37
|
+
%b_addr.0 = phi i32 [ %tmp18, %bb15.split ], [ %b, %entry ] ; <i32> [#uses=4]
|
|
38
|
+
%a_addr.0 = phi i32 [ %a_addr.0.reg2mem.0, %bb15.split ], [ %a, %entry ] ; <i32> [#uses=2]
|
|
39
|
+
%tmp21 = icmp eq i32 %b_addr.0, 0 ; <i1> [#uses=1]
|
|
40
|
+
br i1 %tmp21, label %bb26, label %bb5
|
|
41
|
+
|
|
42
|
+
bb26: ; preds = %bb19, %entry
|
|
43
|
+
%tmp.0 = phi i32 [ %b, %entry ], [ %a_addr.0, %bb19 ] ; <i32> [#uses=1]
|
|
44
|
+
ret i32 %tmp.0
|
|
45
|
+
}
|
|
46
|
+
EOF
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_count_intructions_in_basic_block
|
|
52
|
+
m = LLVM::Module.read_assembly(@assembly_gcd)
|
|
53
|
+
gcd = m.get_function("gcd")
|
|
54
|
+
assert(gcd)
|
|
55
|
+
|
|
56
|
+
bbs = gcd.get_basic_block_list
|
|
57
|
+
expected = { 'entry' => 2, 'bb5' => 6, 'bb11' => 2, 'bb15.split' => 2, 'bb19' => 4, 'bb26' => 2 }
|
|
58
|
+
res = Hash.new
|
|
59
|
+
bbs.each { |b|
|
|
60
|
+
res[b.get_name] = b.size
|
|
61
|
+
}
|
|
62
|
+
assert_equal(expected,res)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'llvm'
|
|
3
|
+
|
|
4
|
+
include LLVM
|
|
5
|
+
|
|
6
|
+
class InstructionTests < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
|
|
10
|
+
@assembly_byteswap=<<-EOF
|
|
11
|
+
; ModuleID = 'byteswap.bc'
|
|
12
|
+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
|
13
|
+
target triple = "i386-apple-darwin9"
|
|
14
|
+
|
|
15
|
+
define i32 @bswap(i32 %x) nounwind {
|
|
16
|
+
entry:
|
|
17
|
+
%tmp3 = shl i32 %x, 24 ; <i32> [#uses=1]
|
|
18
|
+
%tmp5 = shl i32 %x, 8 ; <i32> [#uses=1]
|
|
19
|
+
%tmp6 = and i32 %tmp5, 16711680 ; <i32> [#uses=1]
|
|
20
|
+
%tmp9 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
|
21
|
+
%tmp1018 = and i32 %tmp9, 65280 ; <i32> [#uses=1]
|
|
22
|
+
%tmp7 = or i32 %tmp1018, %tmp3 ; <i32> [#uses=1]
|
|
23
|
+
%tmp11 = or i32 %tmp7, %tmp6 ; <i32> [#uses=1]
|
|
24
|
+
ret i32 %tmp11
|
|
25
|
+
}
|
|
26
|
+
EOF
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_count_intructions_in_basic_block
|
|
31
|
+
m = LLVM::Module.read_assembly(@assembly_byteswap)
|
|
32
|
+
bswap = m.get_function("bswap")
|
|
33
|
+
assert(bswap)
|
|
34
|
+
|
|
35
|
+
bbs = bswap.get_basic_block_list
|
|
36
|
+
assert_equal(1,bbs.size)
|
|
37
|
+
b = bbs[0]
|
|
38
|
+
assert_equal(8,b.size)
|
|
39
|
+
|
|
40
|
+
expected_opcodes_in_bswap = ["shl", "shl", "and", "lshr", "and", "lshr", "and", "or", "or", "ret"]
|
|
41
|
+
ins = b.get_instruction_list
|
|
42
|
+
actual_opcodes_in_bswap = ins.map { |i| i.get_opcode_name}
|
|
43
|
+
assert(expected_opcodes_in_bswap, actual_opcodes_in_bswap)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'llvm'
|
|
3
|
+
|
|
4
|
+
include LLVM
|
|
5
|
+
|
|
6
|
+
class BitcodeReadTests < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
def test_read_bitcode
|
|
9
|
+
bc = File.open("test/byteswap.bc").read
|
|
10
|
+
m = LLVM::Module.read_bitcode(bc)
|
|
11
|
+
assert_match(/define i32 @bswap\(i32 \%x\) nounwind/, m.inspect)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_read_assembly
|
|
15
|
+
assembly =<<-END_ASSEMBLY
|
|
16
|
+
; ModuleID = 'test/byteswap.bc'
|
|
17
|
+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
|
|
18
|
+
2:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
|
19
|
+
target triple = "i386-apple-darwin9"
|
|
20
|
+
|
|
21
|
+
define i32 @bswap(i32 %x) nounwind {
|
|
22
|
+
entry:
|
|
23
|
+
%tmp3 = shl i32 %x, 24 ; <i32> [#uses=1]
|
|
24
|
+
%tmp5 = shl i32 %x, 8 ; <i32> [#uses=1]
|
|
25
|
+
%tmp6 = and i32 %tmp5, 16711680 ; <i32> [#uses=1]
|
|
26
|
+
%tmp9 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
|
27
|
+
%tmp1018 = and i32 %tmp9, 65280 ; <i32> [#uses=1]
|
|
28
|
+
%tmp7 = or i32 %tmp1018, %tmp3 ; <i32> [#uses=1]
|
|
29
|
+
%tmp11 = or i32 %tmp7, %tmp6 ; <i32> [#uses=1]
|
|
30
|
+
ret i32 %tmp11
|
|
31
|
+
}
|
|
32
|
+
END_ASSEMBLY
|
|
33
|
+
m = LLVM::Module.read_assembly(assembly)
|
|
34
|
+
assert_match(/define i32 @bswap\(i32 \%x\) nounwind/, m.inspect)
|
|
35
|
+
assert(m.get_function("bswap"))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'llvm'
|
|
3
|
+
require 'ruby_vm'
|
|
4
|
+
|
|
5
|
+
include LLVM
|
|
6
|
+
RubyVM.start
|
|
7
|
+
|
|
8
|
+
class RubyVMTests < Test::Unit::TestCase
|
|
9
|
+
def test_getinstancevariable
|
|
10
|
+
bytecode = [
|
|
11
|
+
[:putobject, nil.immediate],
|
|
12
|
+
[:getinstancevariable, :@shaka]
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
obj = Object.new
|
|
16
|
+
obj.instance_variable_set(:@shaka, 'khan')
|
|
17
|
+
compiled_method = RubyVM.compile_bytecode(bytecode)
|
|
18
|
+
assert_equal('khan', RubyVM.method_send(obj, compiled_method))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_setinstancevariable
|
|
22
|
+
bytecode = [
|
|
23
|
+
[:putobject, 'puter'],
|
|
24
|
+
[:setinstancevariable, :@fem]
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
obj = Object.new
|
|
28
|
+
compiled_method = RubyVM.compile_bytecode(bytecode)
|
|
29
|
+
RubyVM.method_send(obj, compiled_method)
|
|
30
|
+
assert_equal('puter', obj.instance_variable_get(:@fem))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_opt_aset
|
|
34
|
+
bytecode = [
|
|
35
|
+
[:newarray],
|
|
36
|
+
[:dup],
|
|
37
|
+
[:putobject, 0.immediate],
|
|
38
|
+
[:putobject, 'shaka'.immediate],
|
|
39
|
+
[:opt_aset],
|
|
40
|
+
[:pop]
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
ret = RubyVM.call_bytecode(bytecode, nil)
|
|
44
|
+
assert_equal(ret, ['shaka'])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def opt_cmp_tester(op, truth_table)
|
|
48
|
+
truth_table.each do |x, y, z|
|
|
49
|
+
bytecode = [
|
|
50
|
+
[:putobject, x.immediate],
|
|
51
|
+
[:putobject, y.immediate],
|
|
52
|
+
[op]
|
|
53
|
+
]
|
|
54
|
+
ret = RubyVM.call_bytecode(bytecode, nil)
|
|
55
|
+
assert_equal(z, ret)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_opt_lt
|
|
60
|
+
opt_cmp_tester(:opt_lt, [
|
|
61
|
+
[0, 1, true],
|
|
62
|
+
[1, 0, false],
|
|
63
|
+
[1, 1, false]
|
|
64
|
+
])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_opt_gt
|
|
68
|
+
opt_cmp_tester(:opt_gt, [
|
|
69
|
+
[0, 1, false],
|
|
70
|
+
[1, 0, true],
|
|
71
|
+
[1, 1, false]
|
|
72
|
+
])
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_opt_ge
|
|
76
|
+
opt_cmp_tester(:opt_ge, [
|
|
77
|
+
[0, 1, false],
|
|
78
|
+
[1, 0, true],
|
|
79
|
+
[1, 1, true]
|
|
80
|
+
])
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_opt_length
|
|
84
|
+
bytecode = [
|
|
85
|
+
[:opt_length]
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
ret1 = RubyVM.call_bytecode(bytecode, [])
|
|
89
|
+
assert_equal(0, ret1)
|
|
90
|
+
|
|
91
|
+
ret2 = RubyVM.call_bytecode(bytecode, [1,2,3,4,5])
|
|
92
|
+
assert_equal(5, ret2)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_simple_loop
|
|
96
|
+
bytecode = [
|
|
97
|
+
[:putobject, 1.immediate],
|
|
98
|
+
[:opt_plus],
|
|
99
|
+
[:dup],
|
|
100
|
+
[:putobject, 10.immediate],
|
|
101
|
+
[:opt_lt],
|
|
102
|
+
[:branchif, 0]
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
ret = RubyVM.call_bytecode(bytecode, 6)
|
|
106
|
+
assert_equal(10, ret)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_array_loop
|
|
110
|
+
bytecode = [
|
|
111
|
+
[:dup],
|
|
112
|
+
[:setlocal, 0],
|
|
113
|
+
[:opt_length],
|
|
114
|
+
[:putobject, 1.immediate],
|
|
115
|
+
[:opt_minus],
|
|
116
|
+
[:dup],
|
|
117
|
+
[:getlocal, 0],
|
|
118
|
+
[:swap],
|
|
119
|
+
[:opt_aref],
|
|
120
|
+
[:putobject, 2.immediate],
|
|
121
|
+
[:opt_mult],
|
|
122
|
+
[:setlocal, 1],
|
|
123
|
+
[:dup],
|
|
124
|
+
[:getlocal, 0],
|
|
125
|
+
[:swap],
|
|
126
|
+
[:getlocal, 1],
|
|
127
|
+
[:opt_aset],
|
|
128
|
+
[:pop],
|
|
129
|
+
[:dup],
|
|
130
|
+
[:putobject, 0.immediate],
|
|
131
|
+
[:opt_gt],
|
|
132
|
+
[:branchif, 3],
|
|
133
|
+
[:getlocal, 0]
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
ret = RubyVM.call_bytecode(bytecode, [1,2,3,4,5,6])
|
|
137
|
+
assert_equal([2,4,6,8,10,12], ret)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_send
|
|
141
|
+
bytecode = [
|
|
142
|
+
[:send]
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
ret = RubyVM.call_bytecode(bytecode, nil)
|
|
146
|
+
assert_equal('nil', ret)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_putself
|
|
150
|
+
bytecode = [
|
|
151
|
+
[:putobject, 5.immediate],
|
|
152
|
+
[:putself]
|
|
153
|
+
]
|
|
154
|
+
compiled_method = RubyVM.compile_bytecode(bytecode)
|
|
155
|
+
ret = RubyVM.method_send('me', compiled_method)
|
|
156
|
+
assert_equal('me', ret)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_newhash
|
|
160
|
+
bytecode = [
|
|
161
|
+
[:putobject, 'one'.immediate],
|
|
162
|
+
[:putobject, 1.immediate],
|
|
163
|
+
[:putobject, 'two'.immediate],
|
|
164
|
+
[:putobject, 2.immediate],
|
|
165
|
+
[:putobject, 'three'.immediate],
|
|
166
|
+
[:putobject, 3.immediate],
|
|
167
|
+
[:newhash, 6]
|
|
168
|
+
]
|
|
169
|
+
ret = RubyVM.call_bytecode(bytecode, nil)
|
|
170
|
+
assert_equal({'one' => 1, 'two' => 2, 'three' => 3}, ret)
|
|
171
|
+
end
|
|
172
|
+
end
|