plessl-llvmruby 0.0.3
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 +299 -0
- data/ext/llvm_function.cpp +48 -0
- data/ext/llvm_instruction.cpp +259 -0
- data/ext/llvm_module.cpp +189 -0
- data/ext/llvm_use.cpp +9 -0
- data/ext/llvm_user.cpp +71 -0
- data/ext/llvm_value.cpp +254 -0
- data/ext/llvmruby.c +328 -0
- data/ext/llvmruby.h +73 -0
- data/lib/llvm.rb +146 -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 +340 -0
- data/test/test_basic_block.rb +80 -0
- data/test/test_instructions.rb +112 -0
- data/test/test_read_bitcode.rb +38 -0
- data/test/test_ruby_vm.rb +172 -0
- data/test/test_user.rb +72 -0
- data/test/test_value.rb +63 -0
- metadata +87 -0
@@ -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
|
data/test/test_user.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'llvm'
|
3
|
+
|
4
|
+
include LLVM
|
5
|
+
|
6
|
+
class UserTests < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@assembly_byteswap=<<-EOF
|
10
|
+
; ModuleID = 'byteswap.bc'
|
11
|
+
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"
|
12
|
+
target triple = "i386-apple-darwin9"
|
13
|
+
|
14
|
+
define i32 @bswap(i32 %x) nounwind {
|
15
|
+
entry:
|
16
|
+
%tmp3 = shl i32 %x, 24 ; <i32> [#uses=1]
|
17
|
+
%tmp5 = shl i32 %x, 8 ; <i32> [#uses=1]
|
18
|
+
%tmp6 = and i32 %tmp5, 16711680 ; <i32> [#uses=1]
|
19
|
+
%tmp9 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
20
|
+
%tmp1018 = and i32 %tmp9, 65280 ; <i32> [#uses=1]
|
21
|
+
%tmp7 = or i32 %tmp1018, %tmp3 ; <i32> [#uses=1]
|
22
|
+
%tmp11 = or i32 %tmp7, %tmp6 ; <i32> [#uses=1]
|
23
|
+
ret i32 %tmp11
|
24
|
+
}
|
25
|
+
EOF
|
26
|
+
|
27
|
+
m = LLVM::Module.read_assembly(@assembly_byteswap)
|
28
|
+
bswap = m.get_function("bswap")
|
29
|
+
bbs = bswap.get_basic_block_list
|
30
|
+
@ins = bbs[0].get_instruction_list
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_get_operand_list
|
34
|
+
olist = @ins[0].get_operand_list
|
35
|
+
assert_equal(2, olist.size)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_number_of_operands
|
39
|
+
assert_equal(2, @ins[0].get_num_operands) # shl instruction
|
40
|
+
assert_equal(1, @ins[7].get_num_operands) # ret instruction
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: find a way for testing this function
|
44
|
+
def test_get_operand
|
45
|
+
op0 = @ins[0].get_operand(0)
|
46
|
+
op1 = @ins[1].get_operand(1)
|
47
|
+
assert_equal("x",op0.name)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_set_operand
|
51
|
+
ins_before = @ins[0].inspect
|
52
|
+
assert_match(/\%tmp3 = shl i32 \%x, 24/, ins_before)
|
53
|
+
@ins[0].set_operand(0,42.llvm)
|
54
|
+
ins_after = @ins[0].inspect
|
55
|
+
assert_match(/\%tmp3 = shl i32 42, 24/, ins_after)
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO find a way for testing this function
|
59
|
+
def test_drop_all_references
|
60
|
+
@ins[0].drop_all_references()
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_replace_uses_of_with
|
64
|
+
ins_before = @ins[0].inspect
|
65
|
+
assert_match(/\%tmp3 = shl i32 \%x, 24/, ins_before)
|
66
|
+
@ins[0].replace_uses_of_with(24.llvm,1234.llvm)
|
67
|
+
ins_after = @ins[0].inspect
|
68
|
+
assert_match(/\%tmp3 = shl i32 \%x, 1234/, ins_after)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
data/test/test_value.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'llvm'
|
3
|
+
|
4
|
+
include LLVM
|
5
|
+
|
6
|
+
class ValueTests < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@assembly=<<-EOF
|
10
|
+
; ModuleID = 'constants.o'
|
11
|
+
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"
|
12
|
+
target triple = "i386-apple-darwin9"
|
13
|
+
@CONST_PI = constant float 0x400921FA00000000 ; <float*> [#uses=0]
|
14
|
+
|
15
|
+
define float @circle_area(float %radius) nounwind {
|
16
|
+
entry:
|
17
|
+
%tmp2 = mul float %radius, 0x400921FA00000000 ; <float> [#uses=1]
|
18
|
+
%tmp4 = mul float %tmp2, %radius ; <float> [#uses=1]
|
19
|
+
ret float %tmp4
|
20
|
+
}
|
21
|
+
|
22
|
+
define i32 @add_42(i32 %x) nounwind {
|
23
|
+
entry:
|
24
|
+
%tmp2 = add i32 %x, 42 ; <i32> [#uses=1]
|
25
|
+
ret i32 %tmp2
|
26
|
+
}
|
27
|
+
EOF
|
28
|
+
|
29
|
+
@m = LLVM::Module.read_assembly(@assembly)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_check_value_is_constant
|
33
|
+
add42 = @m.get_function("add_42")
|
34
|
+
assert(add42)
|
35
|
+
ins = add42.get_basic_block_list[0].get_instruction_list
|
36
|
+
add_ins = ins[0]
|
37
|
+
assert_equal(false,add_ins.get_operand(0).is_constant())
|
38
|
+
assert_equal(true,add_ins.get_operand(1).is_constant())
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_get_integer_constant_values
|
42
|
+
add42 = @m.get_function("add_42")
|
43
|
+
assert(add42)
|
44
|
+
ins = add42.get_basic_block_list[0].get_instruction_list
|
45
|
+
add_ins = ins[0]
|
46
|
+
assert(add_ins.get_operand(1).is_constant())
|
47
|
+
assert(add_ins.get_operand(1).is_int_constant())
|
48
|
+
assert_equal(42,add_ins.get_operand(1).get_int_constant_value())
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_get_float_constant_values
|
52
|
+
circle_area = @m.get_function("circle_area")
|
53
|
+
assert(circle_area)
|
54
|
+
ins = circle_area.get_basic_block_list[0].get_instruction_list
|
55
|
+
add_ins = ins[0]
|
56
|
+
assert_equal(false,add_ins.get_operand(0).is_constant())
|
57
|
+
assert_equal(true,add_ins.get_operand(1).is_constant())
|
58
|
+
assert_equal(true,add_ins.get_operand(1).is_float_constant())
|
59
|
+
assert_in_delta(3.14159, add_ins.get_operand(1).get_float_constant_value(), 2 ** -20)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: plessl-llvmruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Bagby
|
8
|
+
- Christian Plessl
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2008-10-27 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description:
|
18
|
+
email:
|
19
|
+
- tomatobagby@gmail.com
|
20
|
+
- christian@plesslweb.ch
|
21
|
+
executables: []
|
22
|
+
|
23
|
+
extensions:
|
24
|
+
- ext/extconf.rb
|
25
|
+
extra_rdoc_files:
|
26
|
+
- README
|
27
|
+
- COPYING
|
28
|
+
files:
|
29
|
+
- README
|
30
|
+
- COPYING
|
31
|
+
- Rakefile
|
32
|
+
- lib/llvm.rb
|
33
|
+
- lib/ruby_vm.rb
|
34
|
+
- lib/version.rb
|
35
|
+
- ext/llvm_basicblock.cpp
|
36
|
+
- ext/llvm_function.cpp
|
37
|
+
- ext/llvm_instruction.cpp
|
38
|
+
- ext/llvm_module.cpp
|
39
|
+
- ext/llvm_use.cpp
|
40
|
+
- ext/llvm_user.cpp
|
41
|
+
- ext/llvm_value.cpp
|
42
|
+
- ext/llvmruby.c
|
43
|
+
- ext/llvmruby.h
|
44
|
+
- ext/extconf.rb
|
45
|
+
- test/test_basic.rb
|
46
|
+
- test/test_basic_block.rb
|
47
|
+
- test/test_instructions.rb
|
48
|
+
- test/test_read_bitcode.rb
|
49
|
+
- test/test_ruby_vm.rb
|
50
|
+
- test/test_user.rb
|
51
|
+
- test/test_value.rb
|
52
|
+
- test/byteswap.bc
|
53
|
+
- test/static.o
|
54
|
+
has_rdoc: true
|
55
|
+
homepage:
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.2.0
|
77
|
+
signing_key:
|
78
|
+
specification_version: 2
|
79
|
+
summary: Ruby bindings to LLVM
|
80
|
+
test_files:
|
81
|
+
- test/test_basic.rb
|
82
|
+
- test/test_basic_block.rb
|
83
|
+
- test/test_instructions.rb
|
84
|
+
- test/test_read_bitcode.rb
|
85
|
+
- test/test_ruby_vm.rb
|
86
|
+
- test/test_user.rb
|
87
|
+
- test/test_value.rb
|