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,41 @@
|
|
1
|
+
module YTLJit
|
2
|
+
module AssemblerUtilX64
|
3
|
+
def rex(dst, src)
|
4
|
+
rrex = 0
|
5
|
+
if dst.is_a?(OpReg64) then
|
6
|
+
rrex |= 0b1000
|
7
|
+
if dst.reg_no >= 8 then
|
8
|
+
rrex |= 0b1
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
if src.is_a?(OpReg64) then
|
13
|
+
rrex |= 0b1000
|
14
|
+
if src.reg_no >= 8 then
|
15
|
+
rrex |= 0b100
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if src.is_a?(OpImmidiate64) then
|
20
|
+
rrex |= 0b1000
|
21
|
+
end
|
22
|
+
|
23
|
+
if rrex != 0 then
|
24
|
+
[[0x40 + rrex], "C"]
|
25
|
+
else
|
26
|
+
[[], ""]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def immidiate_call(addr, offset)
|
31
|
+
if offset.abs > 0x7fff_ffff then
|
32
|
+
addrent = @asm.add_value_entry(addr)
|
33
|
+
offset = addrent.value - @asm.current_address - 7
|
34
|
+
modseq, modfmt = modrm(:call, 2, offset, nil, addr)
|
35
|
+
[0x48, 0xff, *modseq, offset].pack("CC#{modfmt}L")
|
36
|
+
else
|
37
|
+
[0xe8, offset].pack("CL")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
class Proc
|
2
|
+
@@iseq_cache = {}
|
3
|
+
|
4
|
+
def self._alloc
|
5
|
+
Proc.new {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def _dump_data
|
9
|
+
orgiseq = self.to_iseq
|
10
|
+
piseq = @@iseq_cache[orgiseq]
|
11
|
+
if !piseq then
|
12
|
+
piseq = @@iseq_cache[orgiseq] = patch_iseq(orgiseq.to_a)
|
13
|
+
end
|
14
|
+
|
15
|
+
[piseq, self.binding.to_a]
|
16
|
+
end
|
17
|
+
|
18
|
+
def _load_data(obj)
|
19
|
+
iseq, env = obj
|
20
|
+
slf = env[0][0]
|
21
|
+
$_proc_para = [env, slf]
|
22
|
+
prc = lambda {
|
23
|
+
$_proc_para[1].instance_eval {
|
24
|
+
lambda {|env|
|
25
|
+
_lambda_replace
|
26
|
+
}
|
27
|
+
}.call($_proc_para[0].map {|ele| ele.reverse})
|
28
|
+
}
|
29
|
+
|
30
|
+
prc2 = VMLib::InstSeqTree.new(nil, prc.to_iseq.to_a)
|
31
|
+
iv = VMLib::InstSeqTree.new(nil, prc2.body[7][3])
|
32
|
+
lam = VMLib::InstSeqTree.new(nil, iv.body[5][3])
|
33
|
+
lam.body[4][1] = :lambda
|
34
|
+
lam.body[4][3] = iseq
|
35
|
+
|
36
|
+
prc2.header['type'] = :top
|
37
|
+
|
38
|
+
self.copy(ISeq.load(prc2.to_a).eval)
|
39
|
+
end
|
40
|
+
|
41
|
+
def patch_iseq(iseq, dbase = 0)
|
42
|
+
rbody = []
|
43
|
+
iseq2 = VMLib::InstSeqTree.new(nil, iseq)
|
44
|
+
|
45
|
+
iseq2.body.each do |ele|
|
46
|
+
rbody.push ele
|
47
|
+
if ele.is_a?(Array) then
|
48
|
+
case ele[0]
|
49
|
+
when :send
|
50
|
+
if ele[3] then
|
51
|
+
ele[3] = patch_iseq(VMLib::InstSeqTree.new(iseq, ele[3]), dbase + 1)
|
52
|
+
end
|
53
|
+
|
54
|
+
when :getdynamic
|
55
|
+
off = ele[1]
|
56
|
+
dep = ele[2]
|
57
|
+
if dep > dbase then
|
58
|
+
rbody.pop
|
59
|
+
rbody.push [:getdynamic, 3, 1 + dbase]
|
60
|
+
rbody.push [:putobject, dep - 1 - dbase]
|
61
|
+
rbody.push [:opt_aref, 0]
|
62
|
+
rbody.push [:putobject, off]
|
63
|
+
rbody.push [:opt_aref, 0]
|
64
|
+
end
|
65
|
+
|
66
|
+
when :setdynamic
|
67
|
+
off = ele[1]
|
68
|
+
dep = ele[2]
|
69
|
+
if dep > dbase then
|
70
|
+
rbody.pop
|
71
|
+
rbody.push [:getdynamic, 3, 1 + dbase]
|
72
|
+
rbody.push [:putobject, dep - 1 - dbase]
|
73
|
+
rbody.push [:opt_aref, 0]
|
74
|
+
rbody.push [:putobject, off]
|
75
|
+
rbody.push [:topn, 2]
|
76
|
+
rbody.push [:send, :[]=, 2, nil, 0, 0]
|
77
|
+
rbody.push [:swap]
|
78
|
+
rbody.push [:pop]
|
79
|
+
end
|
80
|
+
|
81
|
+
when :getlocal
|
82
|
+
off = ele[1]
|
83
|
+
rbody.pop
|
84
|
+
rbody.push [:getdynamic, 2, 1 + dbase]
|
85
|
+
rbody.push [:dup]
|
86
|
+
rbody.push [:opt_length]
|
87
|
+
rbody.push [:putobject, 1]
|
88
|
+
rbody.push [:opt_sub]
|
89
|
+
rbody.push [:putobject, dbase]
|
90
|
+
rbody.push [:opt_add]
|
91
|
+
rbody.push [:opt_aref, 0]
|
92
|
+
rbody.push [:putobject, off]
|
93
|
+
rbody.push [:opt_aref, 0]
|
94
|
+
|
95
|
+
when :setlocal
|
96
|
+
off = ele[1]
|
97
|
+
rbody.pop
|
98
|
+
rbody.push [:getdynamic, 2, 1 + dbase]
|
99
|
+
rbody.push [:dup]
|
100
|
+
rbody.push [:opt_length]
|
101
|
+
rbody.push [:putobject, 1]
|
102
|
+
rbody.push [:opt_sub]
|
103
|
+
rbody.push [:putobject, dbase]
|
104
|
+
rbody.push [:opt_add]
|
105
|
+
rbody.push [:opt_aref, 0]
|
106
|
+
rbody.push [:putobject, off]
|
107
|
+
rbody.push [:topn, 2]
|
108
|
+
rbody.push [:send, :[]=, 2, nil, 0, 0]
|
109
|
+
rbody.push [:swap]
|
110
|
+
rbody.push [:pop]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
iseq2.body = rbody
|
116
|
+
iseq2.to_a
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
module YTLJit
|
121
|
+
class CodeSpace
|
122
|
+
def _dump_data
|
123
|
+
[@refer_operands, current_pos, code]
|
124
|
+
end
|
125
|
+
|
126
|
+
def _load_data(obj)
|
127
|
+
self[0] = obj.pop
|
128
|
+
current_pos = obj.pop
|
129
|
+
@org_base_address = base_address
|
130
|
+
@refer_operands = obj.pop
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# Pattern matcher
|
2
|
+
# Usage
|
3
|
+
# When pattern matched, block is yielded with argument is hash that maps
|
4
|
+
# symbol to value.
|
5
|
+
#
|
6
|
+
# mat = Matcher.new
|
7
|
+
# mat.pattern([:a, :b]) {|hash|
|
8
|
+
# p hash
|
9
|
+
# }
|
10
|
+
# mat.match([1, 2])
|
11
|
+
#
|
12
|
+
# Output "{:a => 1, :b => 2}"
|
13
|
+
#
|
14
|
+
# [Class_Name, Symbol] is special case.
|
15
|
+
# Match when class of corresponding value is Class_Name. And bind
|
16
|
+
# Symbol in argument hash of block.
|
17
|
+
#
|
18
|
+
# mat.pattern([:a, [Array, :d]]) {|hash|
|
19
|
+
# p hash
|
20
|
+
# }
|
21
|
+
# mat.match([1, [3, 4, 5]])
|
22
|
+
#
|
23
|
+
# Output "{:a=>1, :d=>[3, 4, 5]}"
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# You can use multiple patterns
|
27
|
+
# When multiple patterns matched execute a block for 1 pattern. But
|
28
|
+
# execution pattern is undefined.
|
29
|
+
#
|
30
|
+
# mat = Matcher.new
|
31
|
+
# mat.pattern([:a, :b]) {|hash|
|
32
|
+
# p hash
|
33
|
+
# }
|
34
|
+
# mat.pattern(:a) {|hash|
|
35
|
+
# p hash
|
36
|
+
# }
|
37
|
+
# mat.pattern([:a, [:b, :d]]) {|hash|
|
38
|
+
# p hash
|
39
|
+
# }
|
40
|
+
# mat.pattern([:a, [Array, :d], :c]) {|hash|
|
41
|
+
# p hash
|
42
|
+
# }
|
43
|
+
# mat.match([1, [2, 3]]) # => {:a=>1, :b=>[2, 3]}
|
44
|
+
# mat.match([1, [2, 3], 4]) # => {:a=>1, :d=>[2, 3], :c=>4}
|
45
|
+
# mat.match([1, [2, 3], 4, 5]) # => {:a=>[1, [2, 3], 4, 5]}
|
46
|
+
#
|
47
|
+
|
48
|
+
#
|
49
|
+
class QuotedObj
|
50
|
+
def self.quote(obj)
|
51
|
+
self.new(obj)
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize(obj)
|
55
|
+
@obj = obj
|
56
|
+
end
|
57
|
+
|
58
|
+
attr :obj
|
59
|
+
end
|
60
|
+
|
61
|
+
class Matcher
|
62
|
+
def initialize
|
63
|
+
@cache = {}
|
64
|
+
@code = nil
|
65
|
+
@pattern = []
|
66
|
+
end
|
67
|
+
|
68
|
+
def match(src)
|
69
|
+
unless @code
|
70
|
+
compile
|
71
|
+
end
|
72
|
+
@src = src
|
73
|
+
@code.eval
|
74
|
+
end
|
75
|
+
|
76
|
+
def pattern(pat, &block)
|
77
|
+
unless @code
|
78
|
+
@pattern.push [pat, block]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def compile
|
83
|
+
info = {}
|
84
|
+
@pattern.each do |pat|
|
85
|
+
env = {}
|
86
|
+
cond = compile_aux(pat[0], [], env, [])[0]
|
87
|
+
info[cond] = [env, pat[1]]
|
88
|
+
end
|
89
|
+
@code = code_gen(info)
|
90
|
+
end
|
91
|
+
|
92
|
+
def compile_aux(pat, stack, env, cond)
|
93
|
+
status = :normal
|
94
|
+
case pat
|
95
|
+
when Array
|
96
|
+
if pat[0].is_a?(Class) then
|
97
|
+
cond.push "(#{get_patref(stack)}.is_a?(#{pat[0]}))"
|
98
|
+
env[pat[1]] = "#{get_patref(stack)}"
|
99
|
+
else
|
100
|
+
cond.push "(#{get_patref(stack)}.is_a?(Array))"
|
101
|
+
stack.push 0
|
102
|
+
pat.each_with_index do |ele, i|
|
103
|
+
stack[-1] = i
|
104
|
+
cond, st = compile_aux(ele, stack, env, cond)
|
105
|
+
if st == :return then
|
106
|
+
stack.pop
|
107
|
+
return [cond, status]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
stack[-1] = pat.size
|
111
|
+
cond.push "(#{get_patref(stack)} == nil)"
|
112
|
+
stack.pop
|
113
|
+
end
|
114
|
+
|
115
|
+
when Symbol
|
116
|
+
patstr = pat.to_s
|
117
|
+
if patstr[0] == '_' then
|
118
|
+
npat = patstr[1..-1].to_sym
|
119
|
+
if env[npat] then
|
120
|
+
cond.push "#{get_patref_rest(stack)} == #{env[npat]}"
|
121
|
+
else
|
122
|
+
env[npat] = get_patref_rest(stack)
|
123
|
+
end
|
124
|
+
status = :return
|
125
|
+
else
|
126
|
+
if env[pat] then
|
127
|
+
cond.push "(#{get_patref(stack)}.is_a?(Symbol) or #{get_patref(stack)} == #{env[pat]})"
|
128
|
+
else
|
129
|
+
env[pat] = get_patref(stack).to_s
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
when QuotedObj
|
134
|
+
cond.push "(#{get_patref(stack)} == #{pat.obj.inspect})"
|
135
|
+
|
136
|
+
else
|
137
|
+
cond.push "(#{get_patref(stack)} == #{pat})"
|
138
|
+
end
|
139
|
+
|
140
|
+
return [cond, status]
|
141
|
+
end
|
142
|
+
|
143
|
+
def get_patref(stack)
|
144
|
+
code = "@src"
|
145
|
+
stack.each do |n|
|
146
|
+
code += "[#{n}]"
|
147
|
+
end
|
148
|
+
code
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_patref_rest(stack)
|
152
|
+
code = "@src"
|
153
|
+
top = stack.pop
|
154
|
+
stack.each do |n|
|
155
|
+
code += "[#{n}]"
|
156
|
+
end
|
157
|
+
code += "[#{top}.. -1]"
|
158
|
+
stack.push top
|
159
|
+
code
|
160
|
+
end
|
161
|
+
|
162
|
+
def code_gen(info)
|
163
|
+
ct = {}
|
164
|
+
info.each do |carr, val|
|
165
|
+
cursor = ct
|
166
|
+
carr.each do |cele|
|
167
|
+
cursor[cele] ||= {}
|
168
|
+
cursor = cursor[cele]
|
169
|
+
end
|
170
|
+
cursor[nil] = val
|
171
|
+
end
|
172
|
+
|
173
|
+
code = <<-EOS
|
174
|
+
org_self = self
|
175
|
+
ObjectSpace._id2ref(#{self.object_id}).instance_eval do
|
176
|
+
#{cond_gen(ct, 0)}
|
177
|
+
end
|
178
|
+
EOS
|
179
|
+
RubyVM::InstructionSequence.compile(code)
|
180
|
+
end
|
181
|
+
|
182
|
+
def cond_gen(tr, level)
|
183
|
+
code = ""
|
184
|
+
tr.each do |cond, nxt|
|
185
|
+
if cond then
|
186
|
+
code << "if #{cond} then \n"
|
187
|
+
code << cond_gen(nxt, level + 1)
|
188
|
+
code << "end\n"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
if tr[nil] then
|
192
|
+
code << "#{exec_gen(tr[nil])} \n"
|
193
|
+
end
|
194
|
+
code
|
195
|
+
end
|
196
|
+
|
197
|
+
def exec_gen(para)
|
198
|
+
hash = "{"
|
199
|
+
para[0].each do |key, value|
|
200
|
+
hash << ":#{key} => #{value},"
|
201
|
+
end
|
202
|
+
hash << "}"
|
203
|
+
|
204
|
+
proc = para[1]
|
205
|
+
"break ObjectSpace._id2ref(#{proc.object_id}).call(#{hash})"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
if __FILE__ == $0 then
|
210
|
+
mat = Matcher.new
|
211
|
+
mat.pattern([:a, :b]) {|hash|
|
212
|
+
p hash
|
213
|
+
}
|
214
|
+
mat.pattern([:a, :_b]) {|hash|
|
215
|
+
p hash
|
216
|
+
}
|
217
|
+
mat.pattern(:a) {|hash|
|
218
|
+
p hash
|
219
|
+
}
|
220
|
+
mat.pattern([:a, [:b, :_c], 1]) {|hash|
|
221
|
+
p hash
|
222
|
+
}
|
223
|
+
mat.pattern([:a, [Array, :d], :c]) {|hash|
|
224
|
+
p hash
|
225
|
+
}
|
226
|
+
mat.pattern([QuotedObj.quote(:a), [Array, :d], :c]) {|hash|
|
227
|
+
p hash
|
228
|
+
}
|
229
|
+
mat.match([1, [2, 3]])
|
230
|
+
mat.match([1, [2, 3, 4], 4, :a])
|
231
|
+
mat.match([1, [2, 3, 4], 1])
|
232
|
+
mat.match([1, [2, 3], 4, 5])
|
233
|
+
mat.match([:a, [2, 3], 2 ])
|
234
|
+
end
|
235
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- coding: cp932 -*-
|
2
|
+
#
|
3
|
+
# rubyvm.rb - structured bytecode library
|
4
|
+
#
|
5
|
+
#
|
6
|
+
module VMLib
|
7
|
+
class InstSeqTree
|
8
|
+
Headers = %w(magic major_version minor_version format_type
|
9
|
+
misc name filename filepath line type locals args
|
10
|
+
exception_table)
|
11
|
+
|
12
|
+
# call-seq:
|
13
|
+
# VMLib::InstSeqTree.new(parent, iseq)
|
14
|
+
# parent Partent of InstSeqTree
|
15
|
+
# For example, when you will construct InstSeqTree of
|
16
|
+
# the method body, you must 'parent' is InstSeqTree of definition
|
17
|
+
# code of the method.
|
18
|
+
# If parent is none, 'parent' is nil.
|
19
|
+
# iseq Instruction Sequence, Normally the result of
|
20
|
+
# VM::InstructionSequence.compile(...) or
|
21
|
+
# VM::InstructionSequence.compile_file(...)
|
22
|
+
def initialize(parent = nil, iseq = nil)
|
23
|
+
@lblock = {}
|
24
|
+
@lblock_list = [nil]
|
25
|
+
|
26
|
+
@header = {}
|
27
|
+
@body = nil
|
28
|
+
@parent = parent
|
29
|
+
|
30
|
+
Headers.each do |name|
|
31
|
+
@header[name] = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
if iseq then
|
35
|
+
init_from_ary(iseq.to_a)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
attr :header
|
40
|
+
attr_accessor :body
|
41
|
+
attr :parent
|
42
|
+
|
43
|
+
def init_from_ary(ary)
|
44
|
+
i = 0
|
45
|
+
Headers.each do |name|
|
46
|
+
@header[name] = ary[i]
|
47
|
+
i = i + 1
|
48
|
+
end
|
49
|
+
|
50
|
+
@body = ary[i]
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_a
|
54
|
+
res = []
|
55
|
+
Headers.each do |name|
|
56
|
+
res.push @header[name]
|
57
|
+
end
|
58
|
+
|
59
|
+
res.push @body
|
60
|
+
res
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module YTLJit
|
2
|
+
module AsmType
|
3
|
+
class StructMember<TypeCommon
|
4
|
+
def initialize(type, offset)
|
5
|
+
@type = type
|
6
|
+
@offset = offset
|
7
|
+
end
|
8
|
+
|
9
|
+
attr :offset
|
10
|
+
|
11
|
+
def size
|
12
|
+
@type.size
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](name)
|
16
|
+
@type[name, @offset]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Struct<TypeCommon
|
21
|
+
def initialize(*spec)
|
22
|
+
@member = []
|
23
|
+
@size = nil
|
24
|
+
stat = 0
|
25
|
+
curvar = []
|
26
|
+
spec.each do |token|
|
27
|
+
case stat
|
28
|
+
when 0
|
29
|
+
curvar.push token
|
30
|
+
stat = 1
|
31
|
+
|
32
|
+
when 1
|
33
|
+
curvar.push token
|
34
|
+
stat = 2
|
35
|
+
|
36
|
+
when 2
|
37
|
+
if token.is_a?(Integer) then
|
38
|
+
curvar.push token
|
39
|
+
@member.push curvar
|
40
|
+
curvar = []
|
41
|
+
stat = 0
|
42
|
+
else
|
43
|
+
@member.push curvar
|
44
|
+
if token then
|
45
|
+
curvar = [token]
|
46
|
+
stat = 1
|
47
|
+
else
|
48
|
+
curvar = []
|
49
|
+
stat = 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
# assert(stat == 0)
|
54
|
+
end
|
55
|
+
@member.push curvar
|
56
|
+
end
|
57
|
+
|
58
|
+
def offset_of(name, base = 0)
|
59
|
+
offset = 0
|
60
|
+
@member.each do |e|
|
61
|
+
if e[1] == name then
|
62
|
+
return offset + base
|
63
|
+
end
|
64
|
+
offset += e[2] ? e[2] : e[0].size
|
65
|
+
end
|
66
|
+
raise "No such member #{name} in #{self}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def type_of(name)
|
70
|
+
offset = 0
|
71
|
+
@member.each do |e|
|
72
|
+
if e[1] == name then
|
73
|
+
return e[0]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
raise "No such member #{name} in #{self}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def size
|
80
|
+
if @size then
|
81
|
+
@size
|
82
|
+
else
|
83
|
+
@size = 0
|
84
|
+
@member.each do |e|
|
85
|
+
@size += e[2] ? e[2] : e[0].size
|
86
|
+
end
|
87
|
+
@size
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def [](name, base = 0)
|
92
|
+
offset = 0
|
93
|
+
@member.each do |e|
|
94
|
+
if e[1] == name then
|
95
|
+
return StructMember.new(e[0], offset + base)
|
96
|
+
end
|
97
|
+
offset += e[2] ? e[2] : e[0].size
|
98
|
+
end
|
99
|
+
raise "No such member #{name} in #{self}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Union<Struct
|
104
|
+
def offset_of(name, base = 0)
|
105
|
+
base
|
106
|
+
end
|
107
|
+
|
108
|
+
def size
|
109
|
+
if @size then
|
110
|
+
@size
|
111
|
+
else
|
112
|
+
@size = 0
|
113
|
+
@member.each do |e|
|
114
|
+
@size = [@size, e[2] ? e[2] : e[0].size].max
|
115
|
+
end
|
116
|
+
@size
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def [](name, base = 0)
|
121
|
+
StructMember.new(type_of(name), base)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/ytljit/type.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
module YTLJit
|
2
|
+
|
3
|
+
module AsmType
|
4
|
+
class TypeCommon
|
5
|
+
def initialize
|
6
|
+
@type = nil
|
7
|
+
@size = nil
|
8
|
+
@alignment = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
attr :type
|
12
|
+
attr :size
|
13
|
+
attr :alignment
|
14
|
+
end
|
15
|
+
|
16
|
+
class Scalar<TypeCommon
|
17
|
+
def initialize(size, align = 4, kind = :int)
|
18
|
+
@size = size
|
19
|
+
@alignment = align
|
20
|
+
@kind = kind
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class PointedData<TypeCommon
|
25
|
+
def initialize(type, index, offset)
|
26
|
+
@type = type
|
27
|
+
@index = index
|
28
|
+
@offset = offset
|
29
|
+
end
|
30
|
+
|
31
|
+
attr :index
|
32
|
+
attr :offset
|
33
|
+
|
34
|
+
def size
|
35
|
+
@reftype.size
|
36
|
+
end
|
37
|
+
|
38
|
+
def alignment
|
39
|
+
@reftype.alignment
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Pointer<TypeCommon
|
44
|
+
def initialize(type)
|
45
|
+
@type = type
|
46
|
+
end
|
47
|
+
|
48
|
+
def size
|
49
|
+
MACHINE_WORD.size
|
50
|
+
end
|
51
|
+
|
52
|
+
def alignment
|
53
|
+
MACHINE_WORD.alignment
|
54
|
+
end
|
55
|
+
|
56
|
+
def [](n = 0, offset = 0)
|
57
|
+
PointedData.new(@reftype, n, offset)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Array<TypeCommon
|
62
|
+
def initialize(type, size)
|
63
|
+
@type = type
|
64
|
+
@size = size
|
65
|
+
end
|
66
|
+
|
67
|
+
def size
|
68
|
+
@size * @type.size
|
69
|
+
end
|
70
|
+
|
71
|
+
def alignment
|
72
|
+
@type.alignment
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](n = 0, offset = 0)
|
76
|
+
PointedData.new(@reftype, n, offset)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
@@type_table = {}
|
81
|
+
def self.deftype(name, tinfo)
|
82
|
+
type = Scalar.new(*tinfo)
|
83
|
+
const_set(name.to_s.upcase, type)
|
84
|
+
@@type_table[name] = type
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.type_table
|
88
|
+
@@type_table
|
89
|
+
end
|
90
|
+
|
91
|
+
deftype :void, [0, 1]
|
92
|
+
deftype :int8, [1, 1]
|
93
|
+
deftype :sint8, [1, 1]
|
94
|
+
deftype :uint8, [1, 1]
|
95
|
+
deftype :int16, [2, 2]
|
96
|
+
deftype :uint16, [2, 2]
|
97
|
+
deftype :int32, [4, 4]
|
98
|
+
deftype :uint32, [4, 4]
|
99
|
+
deftype :int64, [8, 8]
|
100
|
+
deftype :uint64, [8, 8]
|
101
|
+
deftype :double, [8, 8]
|
102
|
+
deftype :float, [4, 4]
|
103
|
+
|
104
|
+
case $ruby_platform
|
105
|
+
when /i.86/
|
106
|
+
deftype :machine_word, [4, 4]
|
107
|
+
|
108
|
+
when /x86_64/
|
109
|
+
deftype :machine_word, [8, 8]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|