ytljit 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/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
|