ytljit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +29 -0
- data/Rakefile +22 -0
- data/ext/code_alloc.c +266 -0
- data/ext/extconf.rb +3 -0
- data/ext/ytljit.c +527 -0
- data/ext/ytljit.h +285 -0
- data/lib/ytljit/asm.rb +205 -0
- data/lib/ytljit/asmext.rb +199 -0
- data/lib/ytljit/asmext_x64.rb +212 -0
- data/lib/ytljit/asmext_x86.rb +128 -0
- data/lib/ytljit/asmutil.rb +182 -0
- data/lib/ytljit/codespace.rb +92 -0
- data/lib/ytljit/error.rb +7 -0
- data/lib/ytljit/instruction.rb +138 -0
- data/lib/ytljit/instruction_ia.rb +1298 -0
- data/lib/ytljit/instruction_x64.rb +41 -0
- data/lib/ytljit/instruction_x86.rb +11 -0
- data/lib/ytljit/marshal.rb +133 -0
- data/lib/ytljit/matcher.rb +235 -0
- data/lib/ytljit/rubyvm.rb +63 -0
- data/lib/ytljit/struct.rb +125 -0
- data/lib/ytljit/type.rb +112 -0
- data/lib/ytljit/util.rb +63 -0
- data/lib/ytljit/vm.rb +1649 -0
- data/lib/ytljit/vm_codegen.rb +491 -0
- data/lib/ytljit/vm_inline_method.rb +85 -0
- data/lib/ytljit/vm_inspect.rb +74 -0
- data/lib/ytljit/vm_sendnode.rb +561 -0
- data/lib/ytljit/vm_trans.rb +508 -0
- data/lib/ytljit/vm_type.rb +299 -0
- data/lib/ytljit/vm_type_gen.rb +158 -0
- data/lib/ytljit/vm_typeinf.rb +98 -0
- data/lib/ytljit.rb +46 -0
- data/test/asmsample.rb +117 -0
- data/test/cstest.rb +61 -0
- data/test/marshaltest.rb +27 -0
- data/test/test_assemble.rb +148 -0
- data/test/test_assemble2.rb +286 -0
- data/test/test_codespace.rb +102 -0
- data/test/test_typeinf.rb +21 -0
- data/test/tivmtest.rb +54 -0
- data/test/vmtest.rb +59 -0
- data/test/vmtest2.rb +41 -0
- data/test/vmtest3.rb +22 -0
- data/test/vmtest_compile_only.rb +41 -0
- data/test/vmtest_execute_only.rb +22 -0
- metadata +121 -0
@@ -0,0 +1,299 @@
|
|
1
|
+
module YTLJit
|
2
|
+
module TypeUtil
|
3
|
+
class KlassTree
|
4
|
+
def initialize(defkey = [], defval = [])
|
5
|
+
@node = KlassTreeNode.new(defkey, defval)
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(key, value)
|
9
|
+
cnode = @node
|
10
|
+
snode = @node
|
11
|
+
ocnode = nil
|
12
|
+
while cnode
|
13
|
+
ocnode = cnode
|
14
|
+
if key == cnode.key then
|
15
|
+
return cnode
|
16
|
+
end
|
17
|
+
|
18
|
+
if key.zip(cnode.key).all? {|k, n| k.is_a?(n.class)} then
|
19
|
+
cnode = cnode.same_klass
|
20
|
+
if cnode == nil then
|
21
|
+
ocnode.same_klass = KlassTreeNode.new(key, value)
|
22
|
+
return ocnode.same_klass
|
23
|
+
else
|
24
|
+
snode = cnode
|
25
|
+
end
|
26
|
+
else
|
27
|
+
cnode = cnode.next_klass
|
28
|
+
if cnode == nil then
|
29
|
+
ocnode.next_klass = KlassTreeNode.new(key, value)
|
30
|
+
return ocnode.next_klass
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def search(key)
|
37
|
+
cnode = @node
|
38
|
+
|
39
|
+
while cnode
|
40
|
+
if key == cnode.key then
|
41
|
+
return cnode
|
42
|
+
end
|
43
|
+
|
44
|
+
if key.zip(cnode.key).all? {|a, b|
|
45
|
+
if a then
|
46
|
+
atype = a.ruby_type
|
47
|
+
|
48
|
+
if b then
|
49
|
+
btype = b.ruby_type
|
50
|
+
btype.is_a?(atype.class)
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
else
|
55
|
+
return !b
|
56
|
+
end
|
57
|
+
} then
|
58
|
+
cnode = cnode.same_klass
|
59
|
+
else
|
60
|
+
cnode = cnode.next_klass
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class KlassTreeNode
|
69
|
+
def initialize(key, value)
|
70
|
+
@same_klass = nil
|
71
|
+
@next_klass = nil
|
72
|
+
|
73
|
+
@key = key
|
74
|
+
@value = value
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_accessor :same_klass
|
78
|
+
attr_accessor :next_klass
|
79
|
+
attr :key
|
80
|
+
attr_accessor :value
|
81
|
+
end
|
82
|
+
|
83
|
+
class TypeContainer
|
84
|
+
def initialize
|
85
|
+
@types_tree = KlassTree.new
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_key(context, offset = -1)
|
89
|
+
context.current_method_signature[offset]
|
90
|
+
end
|
91
|
+
|
92
|
+
def search_types(key)
|
93
|
+
@types_tree.search(key)
|
94
|
+
end
|
95
|
+
|
96
|
+
def add_type(key, type)
|
97
|
+
tvs = @types_tree.search(key)
|
98
|
+
if tvs then
|
99
|
+
tvsv = tvs.value
|
100
|
+
if !tvsv.include? type then
|
101
|
+
tvsv.push type
|
102
|
+
end
|
103
|
+
else
|
104
|
+
# inherit types of most similar signature
|
105
|
+
ival = []
|
106
|
+
simnode = @types_tree.add(key, ival)
|
107
|
+
=begin
|
108
|
+
simnode.value.each do |ele|
|
109
|
+
ival.push ele
|
110
|
+
end
|
111
|
+
=end
|
112
|
+
|
113
|
+
if !ival.include? type then
|
114
|
+
ival.push type
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def add_node(key)
|
120
|
+
# inherit types of most similar signature
|
121
|
+
ival = []
|
122
|
+
simnode = @types_tree.add(key, ival)
|
123
|
+
=begin
|
124
|
+
simnode.value.each do |ele|
|
125
|
+
ival.push ele
|
126
|
+
end
|
127
|
+
=end
|
128
|
+
|
129
|
+
simnode
|
130
|
+
end
|
131
|
+
|
132
|
+
def type_list(key)
|
133
|
+
res = search_types(key)
|
134
|
+
if res == nil then
|
135
|
+
res = add_node(key)
|
136
|
+
end
|
137
|
+
|
138
|
+
res
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
module RubyType
|
144
|
+
def self.define_wraped_class(klass, base = RubyTypeBoxed)
|
145
|
+
cn = nil
|
146
|
+
|
147
|
+
if klass then
|
148
|
+
cn = klass.name.to_sym
|
149
|
+
basett, boxtt, unboxtt = BaseType.type_tab
|
150
|
+
if boxtt[cn] == nil then
|
151
|
+
BaseType.related_ruby_class(klass, base)
|
152
|
+
end
|
153
|
+
|
154
|
+
boxobj = boxtt[cn]
|
155
|
+
unboxobj = unboxtt[cn]
|
156
|
+
[boxobj, unboxobj]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class BaseType
|
161
|
+
@@base_type_tab = {}
|
162
|
+
@@boxed_type_tab = {}
|
163
|
+
@@unboxed_type_tab = {}
|
164
|
+
|
165
|
+
def self.type_tab
|
166
|
+
[@@base_type_tab, @@boxed_type_tab, @@unboxed_type_tab]
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.related_ruby_class(klass, base)
|
170
|
+
baseslf = base.new(klass)
|
171
|
+
boxslf = RubyTypeBoxed.new(klass)
|
172
|
+
unboxslf = RubyTypeUnboxed.new(klass)
|
173
|
+
|
174
|
+
klass.ancestors.reverse.each do |curcls|
|
175
|
+
box_unbox = base.name.gsub(/.*::Ruby/, "")
|
176
|
+
mixinname = curcls.name + box_unbox + "CodeGen"
|
177
|
+
begin
|
178
|
+
mixin = VM::TypeCodeGen.const_get(mixinname)
|
179
|
+
baseslf.extend mixin
|
180
|
+
rescue NameError
|
181
|
+
end
|
182
|
+
|
183
|
+
mixinname = curcls.name + "TypeBoxedCodeGen"
|
184
|
+
begin
|
185
|
+
mixin = VM::TypeCodeGen.const_get(mixinname)
|
186
|
+
boxslf.extend mixin
|
187
|
+
rescue NameError
|
188
|
+
end
|
189
|
+
|
190
|
+
mixinname = curcls.name + "TypeUnboxedCodeGen"
|
191
|
+
begin
|
192
|
+
mixin = VM::TypeCodeGen.const_get(mixinname)
|
193
|
+
unboxslf.extend mixin
|
194
|
+
rescue NameError
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
@@base_type_tab[klass] = baseslf
|
199
|
+
@@boxed_type_tab[klass] = boxslf
|
200
|
+
@@unboxed_type_tab[klass] = unboxslf
|
201
|
+
|
202
|
+
[boxslf, unboxslf]
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.from_object(obj)
|
206
|
+
from_ruby_class(obj.class)
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.from_ruby_class(rcls)
|
210
|
+
tobj = @@base_type_tab[rcls]
|
211
|
+
if tobj == nil then
|
212
|
+
DefaultType0.new
|
213
|
+
else
|
214
|
+
tobj.instance
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def initialize(rtype)
|
219
|
+
@asm_type = AsmType::MACHINE_WORD
|
220
|
+
@ruby_type = rtype
|
221
|
+
end
|
222
|
+
|
223
|
+
attr_accessor :asm_type
|
224
|
+
attr_accessor :ruby_type
|
225
|
+
end
|
226
|
+
|
227
|
+
# Same as VALUE type in MRI
|
228
|
+
# Type0 makes you can define "Defalut" class
|
229
|
+
class DefaultType0<BaseType
|
230
|
+
def initialize
|
231
|
+
super(Object)
|
232
|
+
end
|
233
|
+
|
234
|
+
def boxed
|
235
|
+
true
|
236
|
+
end
|
237
|
+
|
238
|
+
def to_unbox
|
239
|
+
self
|
240
|
+
end
|
241
|
+
|
242
|
+
def to_box
|
243
|
+
self
|
244
|
+
end
|
245
|
+
|
246
|
+
def ==(other)
|
247
|
+
if other then
|
248
|
+
self.ruby_type == other.ruby_type and
|
249
|
+
boxed == other.boxed
|
250
|
+
else
|
251
|
+
nil
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
include VM::TypeCodeGen::DefaultTypeCodeGen
|
256
|
+
end
|
257
|
+
|
258
|
+
class RubyTypeBoxed<BaseType
|
259
|
+
def boxed
|
260
|
+
true
|
261
|
+
end
|
262
|
+
|
263
|
+
def to_unbox
|
264
|
+
@@unboxed_type_tab[@ruby_type].instance
|
265
|
+
end
|
266
|
+
|
267
|
+
def to_box
|
268
|
+
self
|
269
|
+
end
|
270
|
+
|
271
|
+
include VM::TypeCodeGen::DefaultTypeCodeGen
|
272
|
+
end
|
273
|
+
|
274
|
+
class RubyTypeUnboxed<BaseType
|
275
|
+
def boxed
|
276
|
+
false
|
277
|
+
end
|
278
|
+
|
279
|
+
def to_box
|
280
|
+
@@boxed_type_tab[@ruby_type].instance
|
281
|
+
end
|
282
|
+
|
283
|
+
def to_unbox
|
284
|
+
self
|
285
|
+
end
|
286
|
+
|
287
|
+
include VM::TypeCodeGen::DefaultTypeCodeGen
|
288
|
+
end
|
289
|
+
|
290
|
+
YTLJit::RubyType::define_wraped_class(NilClass, RubyTypeBoxed)
|
291
|
+
YTLJit::RubyType::define_wraped_class(Fixnum, RubyTypeUnboxed)
|
292
|
+
YTLJit::RubyType::define_wraped_class(Float, RubyTypeUnboxed)
|
293
|
+
YTLJit::RubyType::define_wraped_class(TrueClass, RubyTypeBoxed)
|
294
|
+
YTLJit::RubyType::define_wraped_class(FalseClass, RubyTypeBoxed)
|
295
|
+
YTLJit::RubyType::define_wraped_class(String, RubyTypeBoxed)
|
296
|
+
YTLJit::RubyType::define_wraped_class(Array, RubyTypeBoxed)
|
297
|
+
YTLJit::RubyType::define_wraped_class(Hash, RubyTypeBoxed)
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module YTLJit
|
2
|
+
module VM
|
3
|
+
module TypeCodeGen
|
4
|
+
module DefaultTypeCodeGen
|
5
|
+
def instance
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def init_type
|
10
|
+
end
|
11
|
+
|
12
|
+
def have_element?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def gen_boxing(context)
|
17
|
+
context
|
18
|
+
end
|
19
|
+
|
20
|
+
def gen_unboxing(context)
|
21
|
+
context
|
22
|
+
end
|
23
|
+
|
24
|
+
def gen_copy(context)
|
25
|
+
context
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
"{ #{boxed ? "BOXED" : "UNBOXED"} #{@ruby_type}}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module FixnumTypeUnboxedCodeGen
|
34
|
+
include AbsArch
|
35
|
+
|
36
|
+
def gen_boxing(context)
|
37
|
+
asm = context.assembler
|
38
|
+
val = context.ret_reg
|
39
|
+
vnode = context.ret_node
|
40
|
+
asm.with_retry do
|
41
|
+
if val != TMPR then
|
42
|
+
asm.mov(TMPR, val)
|
43
|
+
end
|
44
|
+
asm.add(TMPR, TMPR)
|
45
|
+
asm.add(TMPR, OpImmidiate8.new(1))
|
46
|
+
end
|
47
|
+
|
48
|
+
context.set_reg_content(TMPR, vnode)
|
49
|
+
context.ret_reg = TMPR
|
50
|
+
context
|
51
|
+
end
|
52
|
+
|
53
|
+
def gen_unboxing(context)
|
54
|
+
context
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module FixnumTypeBoxedCodeGen
|
59
|
+
include AbsArch
|
60
|
+
|
61
|
+
def gen_boxing(context)
|
62
|
+
context
|
63
|
+
end
|
64
|
+
|
65
|
+
def gen_unboxing(context)
|
66
|
+
asm = context.assembler
|
67
|
+
val = context.ret_reg
|
68
|
+
vnode = context.ret_node
|
69
|
+
asm.with_retry do
|
70
|
+
if val != TMPR then
|
71
|
+
asm.mov(TMPR, val)
|
72
|
+
end
|
73
|
+
asm.sar(TMPR)
|
74
|
+
end
|
75
|
+
context.set_reg_content(TMPR, vnode)
|
76
|
+
context.ret_reg = TMPR
|
77
|
+
context
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module FloatTypeBoxedCodeGen
|
82
|
+
include AbsArch
|
83
|
+
|
84
|
+
def gen_boxing(context)
|
85
|
+
p "boxingaaa"
|
86
|
+
context
|
87
|
+
end
|
88
|
+
|
89
|
+
def gen_unboxing(context)
|
90
|
+
p "inboxing"
|
91
|
+
context
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module FloatTypeUnboxedCodeGen
|
96
|
+
include AbsArch
|
97
|
+
|
98
|
+
def gen_boxing(context)
|
99
|
+
asm = context.assembler
|
100
|
+
val = context.ret_reg
|
101
|
+
vnode = context.ret_node
|
102
|
+
context.start_using_reg(FUNC_FLOAT_ARG[0])
|
103
|
+
rbfloatnew = OpMemAddress.new(address_of("rb_float_new"))
|
104
|
+
asm.with_retry do
|
105
|
+
asm.mov(FUNC_FLOAT_ARG[0], val)
|
106
|
+
asm.call_with_arg(rbfloatnew, 1)
|
107
|
+
end
|
108
|
+
context.end_using_reg(FUNC_FLOAT_ARG[0])
|
109
|
+
context.ret_reg = RETR
|
110
|
+
context
|
111
|
+
end
|
112
|
+
|
113
|
+
def gen_unboxing(context)
|
114
|
+
p "unboxing"
|
115
|
+
context
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
module ArrayTypeBoxedCodeGen
|
120
|
+
include AbsArch
|
121
|
+
|
122
|
+
def instance
|
123
|
+
ni = self.dup
|
124
|
+
ni.instance_eval { extend ArrayTypeBoxedCodeGen }
|
125
|
+
ni.init
|
126
|
+
ni
|
127
|
+
end
|
128
|
+
|
129
|
+
def init
|
130
|
+
@element_type = nil
|
131
|
+
end
|
132
|
+
|
133
|
+
attr_accessor :element_type
|
134
|
+
|
135
|
+
def have_element?
|
136
|
+
true
|
137
|
+
end
|
138
|
+
|
139
|
+
def gen_copy(context)
|
140
|
+
p "copy"
|
141
|
+
context
|
142
|
+
end
|
143
|
+
|
144
|
+
def ==(other)
|
145
|
+
other.is_a?(self.class) and
|
146
|
+
self.class == other.class and
|
147
|
+
@element_type == other.element_type
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
module ArrayTypeUnboxedCodeGen
|
152
|
+
def have_element?
|
153
|
+
true
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module YTLJit
|
2
|
+
module VM
|
3
|
+
module Node
|
4
|
+
class TISelfRefNode<SelfRefNode
|
5
|
+
def initialize(parent)
|
6
|
+
super(parent)
|
7
|
+
end
|
8
|
+
|
9
|
+
def compile_main(context)
|
10
|
+
slf = context.slf
|
11
|
+
slfval = lambda { slf.address }
|
12
|
+
slfadd = OpVarImmdiateAddress.new(slfval)
|
13
|
+
asm = context.assembler
|
14
|
+
asm.with_retry do
|
15
|
+
asm.mov(RETR, slfadd)
|
16
|
+
end
|
17
|
+
|
18
|
+
context.ret_reg = RETR
|
19
|
+
context
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class TIInstanceVarRefNode<InstanceVarRefNode
|
24
|
+
def initialize(parent, name)
|
25
|
+
super(parent, name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile_main(context)
|
29
|
+
slf = context.slf
|
30
|
+
ivval = lambda { slf.instance_var_address_of(@name) }
|
31
|
+
ivadd = OpVarImmidiateAddress.new(ivval)
|
32
|
+
asm = context.assembler
|
33
|
+
asm.with_retry do
|
34
|
+
asm.mov(TMPR, ivadd)
|
35
|
+
asm.mov(RETR, INDIRECT_TMPR)
|
36
|
+
end
|
37
|
+
|
38
|
+
context.ret_reg = RETR
|
39
|
+
context
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class TIInstanceVarAssignNode<InstanceVarAssignNode
|
44
|
+
def initialize(parent, name, val)
|
45
|
+
super(parent, name, val)
|
46
|
+
end
|
47
|
+
|
48
|
+
def compile_main(context)
|
49
|
+
context = @val.compile(context)
|
50
|
+
valr = context.ret_reg
|
51
|
+
slf = context.slf
|
52
|
+
ivval = lambda { slf.instance_var_address_of(@name) }
|
53
|
+
ivadd = OpVarImmdiateAddress.new(ivval)
|
54
|
+
asm = context.assembler
|
55
|
+
asm.with_retry do
|
56
|
+
asm.mov(TMPR, ivadd)
|
57
|
+
asm.mov(INDIRECT_TMPR, valr)
|
58
|
+
end
|
59
|
+
|
60
|
+
context.ret_reg = RETR
|
61
|
+
context
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module YARVTranslatorTypeInferenceMixin
|
67
|
+
include Node
|
68
|
+
|
69
|
+
def initialize(parent)
|
70
|
+
super(parent)
|
71
|
+
end
|
72
|
+
|
73
|
+
def visit_putself(code, ins, context)
|
74
|
+
curnode = context.current_node
|
75
|
+
nnode = TISelfRefNode.new(curnode)
|
76
|
+
context.expstack.push nnode
|
77
|
+
end
|
78
|
+
|
79
|
+
def visit_getinstancevariable(code, ins, context)
|
80
|
+
curnode = context.current_node
|
81
|
+
node = TIInstanceVarRefNode.new(curnode, ins[1])
|
82
|
+
context.expstack.push node
|
83
|
+
end
|
84
|
+
|
85
|
+
def visit_setinstancevariable(code, ins, context)
|
86
|
+
val = context.expstack.pop
|
87
|
+
curnode = context.current_node
|
88
|
+
node = TiInstanceVarAssignNode.new(curnode, ins[1], val)
|
89
|
+
curnode.body = node
|
90
|
+
context.current_node = node
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class YARVTranslatorTypeInference<YARVTranslatorSimple
|
95
|
+
include YARVTranslatorTypeInferenceMixin
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/ytljit.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
require 'rbconfig'
|
5
|
+
require 'pp'
|
6
|
+
if $ruby_platform == nil then
|
7
|
+
$ruby_platform = RUBY_PLATFORM
|
8
|
+
end
|
9
|
+
# $ruby_platform = "x86_64" # You can select CPU type for debug.
|
10
|
+
|
11
|
+
require 'iseq'
|
12
|
+
|
13
|
+
require "ytljit_ext"
|
14
|
+
|
15
|
+
require 'ytljit/codespace'
|
16
|
+
|
17
|
+
require 'ytljit/marshal'
|
18
|
+
require 'ytljit/util'
|
19
|
+
require 'ytljit/error'
|
20
|
+
|
21
|
+
require 'ytljit/asm'
|
22
|
+
require 'ytljit/instruction'
|
23
|
+
require 'ytljit/instruction_x86'
|
24
|
+
require 'ytljit/instruction_x64'
|
25
|
+
require 'ytljit/instruction_ia'
|
26
|
+
require 'ytljit/type'
|
27
|
+
require 'ytljit/struct'
|
28
|
+
require 'ytljit/asmutil'
|
29
|
+
require 'ytljit/asmext_x86'
|
30
|
+
require 'ytljit/asmext_x64'
|
31
|
+
require 'ytljit/asmext'
|
32
|
+
|
33
|
+
require 'ytljit/rubyvm'
|
34
|
+
|
35
|
+
require 'ytljit/vm_codegen'
|
36
|
+
require 'ytljit/vm_inspect'
|
37
|
+
require 'ytljit/vm'
|
38
|
+
|
39
|
+
require 'ytljit/vm_inline_method'
|
40
|
+
require 'ytljit/vm_sendnode'
|
41
|
+
|
42
|
+
require 'ytljit/vm_trans'
|
43
|
+
require 'ytljit/vm_type_gen'
|
44
|
+
require 'ytljit/vm_type'
|
45
|
+
|
46
|
+
require 'ytljit/vm_typeinf'
|
data/test/asmsample.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'ytljit.rb'
|
2
|
+
|
3
|
+
include YTLJit
|
4
|
+
|
5
|
+
# sample for file output
|
6
|
+
def file_output
|
7
|
+
File.open("foo.bin", "w") {|fp|
|
8
|
+
asm = Assembler.new(FileOutputStream.new(fp))
|
9
|
+
|
10
|
+
# registor definition
|
11
|
+
eax = OpEAX.instance
|
12
|
+
ecx = OpECX.instance
|
13
|
+
|
14
|
+
asm.mov(eax, OpImmidiate32.new(0))
|
15
|
+
loop = asm.var_current_address
|
16
|
+
asm.add(eax, OpImmidiate8.new(1))
|
17
|
+
asm.jo(loop)
|
18
|
+
arynew = address_of("rb_ary_new")
|
19
|
+
asm.call(arynew)
|
20
|
+
asm.ret
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Hello World
|
25
|
+
include AbsArch
|
26
|
+
def hello
|
27
|
+
asm = Assembler.new(cs = CodeSpace.new)
|
28
|
+
|
29
|
+
# registor definition
|
30
|
+
hello = "Hello World".address
|
31
|
+
asm.step_mode = true
|
32
|
+
asm.with_retry do
|
33
|
+
asm.mov(FUNC_ARG[0], hello)
|
34
|
+
rbp = address_of("rb_p")
|
35
|
+
asm.call_with_arg(rbp, 1)
|
36
|
+
asm.ret
|
37
|
+
end
|
38
|
+
cs.fill_disasm_cache
|
39
|
+
cs.disassemble
|
40
|
+
cs.call(cs.base_address)
|
41
|
+
end
|
42
|
+
hello
|
43
|
+
|
44
|
+
# Hello World (Use puts)
|
45
|
+
def hello2
|
46
|
+
csentry = CodeSpace.new
|
47
|
+
asm = Assembler.new(cs = CodeSpace.new)
|
48
|
+
|
49
|
+
# registor definition
|
50
|
+
hello ="Hello World11234".address
|
51
|
+
# asm.step_mode = true
|
52
|
+
InternalRubyType::rstring_ptr(hello, csentry, cs)
|
53
|
+
asm.with_retry do
|
54
|
+
asm.mov(FUNC_ARG[0], TMPR)
|
55
|
+
rbp = address_of("puts")
|
56
|
+
asm.call_with_arg(rbp, 1)
|
57
|
+
asm.ret
|
58
|
+
end
|
59
|
+
cs.disassemble
|
60
|
+
csentry.disassemble
|
61
|
+
csentry.call(csentry.base_address)
|
62
|
+
end
|
63
|
+
hello2
|
64
|
+
|
65
|
+
# Fib number
|
66
|
+
def fib(n)
|
67
|
+
cs0 = CodeSpace.new
|
68
|
+
cs1 = CodeSpace.new
|
69
|
+
cs2 = CodeSpace.new
|
70
|
+
|
71
|
+
asm = Assembler.new(cs0)
|
72
|
+
# asm.step_mode = true
|
73
|
+
ent = nil
|
74
|
+
asm.with_retry do
|
75
|
+
ent = cs1.var_base_address
|
76
|
+
asm.mov(TMPR, OpImmidiate32.new(n))
|
77
|
+
asm.call(ent)
|
78
|
+
asm.add(TMPR, TMPR)
|
79
|
+
asm.add(TMPR, OpImmidiate8.new(1))
|
80
|
+
asm.ret
|
81
|
+
end
|
82
|
+
|
83
|
+
asm = Assembler.new(cs1)
|
84
|
+
# asm.step_mode = true
|
85
|
+
asm.with_retry do
|
86
|
+
asm.cmp(TMPR, OpImmidiate32.new(2))
|
87
|
+
asm.jl(cs2.var_base_address)
|
88
|
+
asm.sub(TMPR, OpImmidiate32.new(1))
|
89
|
+
asm.push(TMPR)
|
90
|
+
asm.call(ent)
|
91
|
+
asm.pop(TMPR2)
|
92
|
+
asm.sub(TMPR2, OpImmidiate32.new(1))
|
93
|
+
asm.push(TMPR)
|
94
|
+
asm.mov(TMPR, TMPR2)
|
95
|
+
asm.call(ent)
|
96
|
+
asm.pop(TMPR2)
|
97
|
+
asm.add(TMPR, TMPR2)
|
98
|
+
asm.ret
|
99
|
+
end
|
100
|
+
|
101
|
+
asm = Assembler.new(cs2)
|
102
|
+
# asm.step_mode = true
|
103
|
+
asm.with_retry do
|
104
|
+
asm.mov(TMPR, OpImmidiate32.new(1))
|
105
|
+
asm.ret
|
106
|
+
end
|
107
|
+
|
108
|
+
# cs0.disassemble
|
109
|
+
# cs1.disassemble
|
110
|
+
# cs2.disassemble
|
111
|
+
|
112
|
+
cs0.call(cs0.base_address)
|
113
|
+
end
|
114
|
+
|
115
|
+
(1..20).each do |i|
|
116
|
+
p fib(i)
|
117
|
+
end
|