cast_off 0.2.0
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 +578 -0
- data/README.en +256 -0
- data/bin/CastOff +145 -0
- data/cast_off.gemspec +25 -0
- data/ext/cast_off/cast_off.c.rb +1386 -0
- data/ext/cast_off/cast_off.h +24 -0
- data/ext/cast_off/depend +70 -0
- data/ext/cast_off/extconf.rb +19 -0
- data/ext/cast_off/generated_c_include/inline_api.h +507 -0
- data/ext/cast_off/generated_c_include/iter_api.h +595 -0
- data/ext/cast_off/generated_c_include/unbox_api.h.rb +76 -0
- data/ext/cast_off/generated_c_include/vm_api.h +751 -0
- data/ext/cast_off/ruby_source/atomic.h +56 -0
- data/ext/cast_off/ruby_source/constant.h +34 -0
- data/ext/cast_off/ruby_source/debug.h +41 -0
- data/ext/cast_off/ruby_source/eval_intern.h +234 -0
- data/ext/cast_off/ruby_source/gc.h +98 -0
- data/ext/cast_off/ruby_source/id.h +175 -0
- data/ext/cast_off/ruby_source/insns.inc +179 -0
- data/ext/cast_off/ruby_source/insns_info.inc +695 -0
- data/ext/cast_off/ruby_source/internal.h +227 -0
- data/ext/cast_off/ruby_source/iseq.h +125 -0
- data/ext/cast_off/ruby_source/manual_update.h +135 -0
- data/ext/cast_off/ruby_source/method.h +105 -0
- data/ext/cast_off/ruby_source/node.h +503 -0
- data/ext/cast_off/ruby_source/thread_pthread.h +51 -0
- data/ext/cast_off/ruby_source/thread_win32.h +40 -0
- data/ext/cast_off/ruby_source/vm_core.h +756 -0
- data/ext/cast_off/ruby_source/vm_exec.h +184 -0
- data/ext/cast_off/ruby_source/vm_insnhelper.c +1748 -0
- data/ext/cast_off/ruby_source/vm_insnhelper.h +220 -0
- data/ext/cast_off/ruby_source/vm_opts.h +51 -0
- data/lib/cast_off.rb +15 -0
- data/lib/cast_off/compile.rb +629 -0
- data/lib/cast_off/compile/basicblock.rb +144 -0
- data/lib/cast_off/compile/cfg.rb +391 -0
- data/lib/cast_off/compile/code_manager.rb +284 -0
- data/lib/cast_off/compile/configuration.rb +2368 -0
- data/lib/cast_off/compile/dependency.rb +240 -0
- data/lib/cast_off/compile/information.rb +775 -0
- data/lib/cast_off/compile/instruction.rb +446 -0
- data/lib/cast_off/compile/ir/call_ir.rb +2348 -0
- data/lib/cast_off/compile/ir/guard_ir.rb +423 -0
- data/lib/cast_off/compile/ir/jump_ir.rb +223 -0
- data/lib/cast_off/compile/ir/operand.rb +934 -0
- data/lib/cast_off/compile/ir/param_ir.rb +98 -0
- data/lib/cast_off/compile/ir/return_ir.rb +92 -0
- data/lib/cast_off/compile/ir/simple_ir.rb +808 -0
- data/lib/cast_off/compile/ir/sub_ir.rb +212 -0
- data/lib/cast_off/compile/iseq.rb +454 -0
- data/lib/cast_off/compile/method_information.rb +1384 -0
- data/lib/cast_off/compile/namespace/namespace.rb +556 -0
- data/lib/cast_off/compile/namespace/uuid.rb +323 -0
- data/lib/cast_off/compile/stack.rb +65 -0
- data/lib/cast_off/compile/translator.rb +1562 -0
- data/lib/cast_off/suggestion.rb +98 -0
- data/lib/cast_off/util.rb +58 -0
- metadata +107 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
module CastOff::Compiler
|
4
|
+
module SimpleIR
|
5
|
+
class ParamIR < IR
|
6
|
+
attr_reader :param_value, :variables_without_result, :variables, :result_variable, :values
|
7
|
+
def initialize(val, insn, cfg)
|
8
|
+
super(insn, cfg)
|
9
|
+
@param_value = val
|
10
|
+
@values = [@param_value]
|
11
|
+
@variables = []
|
12
|
+
@variables_without_result = []
|
13
|
+
if @param_value.is_a?(Variable)
|
14
|
+
@variables << @param_value
|
15
|
+
@variables_without_result << @param_value
|
16
|
+
end
|
17
|
+
@result_variable = nil
|
18
|
+
@need_guard = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
### unboxing begin ###
|
22
|
+
def unboxing_prelude()
|
23
|
+
# nothing to do
|
24
|
+
end
|
25
|
+
|
26
|
+
def propergate_value_which_can_not_unbox(defs)
|
27
|
+
change = false
|
28
|
+
|
29
|
+
# forward
|
30
|
+
change |= defs.can_not_unbox_variable_resolve_forward(@param_value)
|
31
|
+
|
32
|
+
# backward
|
33
|
+
if @param_value.can_not_unbox?
|
34
|
+
change |= defs.can_not_unbox_variable_resolve_backward(@param_value)
|
35
|
+
end
|
36
|
+
|
37
|
+
change
|
38
|
+
end
|
39
|
+
|
40
|
+
def propergate_box_value(defs)
|
41
|
+
change = false
|
42
|
+
|
43
|
+
# forward
|
44
|
+
change |= defs.box_value_resolve_forward(@param_value)
|
45
|
+
|
46
|
+
# backward
|
47
|
+
if @param_value.boxed?
|
48
|
+
change |= defs.box_value_resolve_backward(@param_value)
|
49
|
+
end
|
50
|
+
|
51
|
+
change
|
52
|
+
end
|
53
|
+
|
54
|
+
def propergate_unbox_value(defs)
|
55
|
+
return false if @param_value.can_not_unbox?
|
56
|
+
defs.unbox_value_resolve(@param_value)
|
57
|
+
end
|
58
|
+
### unboxing end ###
|
59
|
+
|
60
|
+
def propergate_exact_class(defs)
|
61
|
+
defs.exact_class_resolve(@param_value)
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_c()
|
65
|
+
bug()
|
66
|
+
end
|
67
|
+
|
68
|
+
def type_propergation(defs)
|
69
|
+
defs.type_resolve(@param_value)
|
70
|
+
end
|
71
|
+
|
72
|
+
def need_guard(bool)
|
73
|
+
@need_guard = !!bool
|
74
|
+
end
|
75
|
+
|
76
|
+
def reset()
|
77
|
+
@need_guard = nil
|
78
|
+
super()
|
79
|
+
end
|
80
|
+
|
81
|
+
def standard_guard_target()
|
82
|
+
need_guard? ? @param_value : nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def mark(defs)
|
86
|
+
alive? && defs.mark(@param_value)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def need_guard?()
|
92
|
+
bug() if @need_guard.nil?
|
93
|
+
@need_guard
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
module CastOff::Compiler
|
4
|
+
module SimpleIR
|
5
|
+
class ReturnIR < IR
|
6
|
+
attr_reader :return_value, :variables_without_result, :variables, :result_variable, :values
|
7
|
+
|
8
|
+
class ThrowObj
|
9
|
+
attr_reader :type, :raw_state, :state
|
10
|
+
|
11
|
+
def initialize(type, raw_state, state, flag, level)
|
12
|
+
@type = type
|
13
|
+
@raw_state = raw_state
|
14
|
+
@state = state
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(retval, throwobj, insn, cfg)
|
19
|
+
super(insn, cfg)
|
20
|
+
@throwobj = throwobj
|
21
|
+
@return_value = retval
|
22
|
+
@values = [@return_value]
|
23
|
+
@variables = []
|
24
|
+
@variables_without_result = []
|
25
|
+
if @return_value.is_a?(Variable)
|
26
|
+
@variables << @return_value
|
27
|
+
@variables_without_result << @return_value
|
28
|
+
end
|
29
|
+
@result_variable = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
### unboxing begin ###
|
33
|
+
def unboxing_prelude()
|
34
|
+
@return_value.can_not_unbox()
|
35
|
+
end
|
36
|
+
|
37
|
+
def propergate_value_which_can_not_unbox(defs)
|
38
|
+
bug() unless @return_value.can_not_unbox?
|
39
|
+
defs.can_not_unbox_variable_resolve_backward(@return_value)
|
40
|
+
end
|
41
|
+
|
42
|
+
def propergate_box_value(defs)
|
43
|
+
bug() unless @return_value.boxed?
|
44
|
+
defs.box_value_resolve_backward(@return_value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def propergate_unbox_value(defs)
|
48
|
+
bug() unless @return_value.can_not_unbox?
|
49
|
+
false
|
50
|
+
end
|
51
|
+
### unboxing end ###
|
52
|
+
|
53
|
+
def propergate_exact_class(defs)
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_c()
|
58
|
+
if @insn.iseq.catch_exception?
|
59
|
+
prereturn = " TH_POP_TAG2();\n"
|
60
|
+
else
|
61
|
+
prereturn = ''
|
62
|
+
end
|
63
|
+
case @throwobj
|
64
|
+
when ThrowObj
|
65
|
+
if @translator.inline_block?
|
66
|
+
return prereturn + " return_from_execute(#{@throwobj.raw_state}, #{@return_value});"
|
67
|
+
else
|
68
|
+
return prereturn + " return return_block(#{@throwobj.raw_state}, #{@return_value}, lambda_p);"
|
69
|
+
end
|
70
|
+
when NilClass
|
71
|
+
return prereturn + " return #{@return_value};"
|
72
|
+
end
|
73
|
+
bug()
|
74
|
+
end
|
75
|
+
|
76
|
+
def type_propergation(defs)
|
77
|
+
defs.type_resolve(@return_value)
|
78
|
+
end
|
79
|
+
|
80
|
+
def mark(defs)
|
81
|
+
if !alive?
|
82
|
+
alive()
|
83
|
+
defs.mark(@return_value)
|
84
|
+
true
|
85
|
+
else
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,808 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
module CastOff
|
4
|
+
module Compiler
|
5
|
+
module SimpleIR
|
6
|
+
# 3 address code
|
7
|
+
|
8
|
+
include Instruction
|
9
|
+
|
10
|
+
class Stack
|
11
|
+
include CastOff::Util
|
12
|
+
|
13
|
+
attr_reader :depth
|
14
|
+
|
15
|
+
def initialize(depth)
|
16
|
+
@depth = depth
|
17
|
+
end
|
18
|
+
|
19
|
+
def pop()
|
20
|
+
@depth -= 1
|
21
|
+
bug() if @depth < 0
|
22
|
+
@depth
|
23
|
+
end
|
24
|
+
|
25
|
+
def push()
|
26
|
+
ret = @depth
|
27
|
+
@depth += 1
|
28
|
+
ret
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def block_argument_is_unsupported(translator, insn)
|
33
|
+
raise UnsupportedError.new(<<-EOS)
|
34
|
+
|
35
|
+
Currently, CastOff doesn't support method and block invocation with a block argument.
|
36
|
+
------------------------------------------------------------------------------
|
37
|
+
Target file is (#{translator.target_name()}).
|
38
|
+
Call site is (#{insn}).
|
39
|
+
EOS
|
40
|
+
end
|
41
|
+
|
42
|
+
def generate_ir(cfg, insns, depth)
|
43
|
+
irs = []
|
44
|
+
translator = cfg.translator
|
45
|
+
stack = Stack.new(depth)
|
46
|
+
insns.each do |insn|
|
47
|
+
bug() unless stack.depth == insn.depth
|
48
|
+
op = insn.op
|
49
|
+
argv = insn.argv
|
50
|
+
case op
|
51
|
+
when :send,
|
52
|
+
:opt_plus, :opt_minus, :opt_mult, :opt_div, :opt_mod, :opt_lt, :opt_le, :opt_gt, :opt_ge, :opt_neq, :opt_eq, :opt_ltlt, :opt_aref,
|
53
|
+
:opt_length, :opt_size, :opt_not, :opt_succ
|
54
|
+
fcall = false
|
55
|
+
flags = 0
|
56
|
+
case op
|
57
|
+
when :send
|
58
|
+
id = argv[0]
|
59
|
+
argc = argv[1]
|
60
|
+
blockiseq = argv[2]
|
61
|
+
bug() if blockiseq # should be convert to cast_off_prep, ...
|
62
|
+
flags = argv[3]
|
63
|
+
fcall = (flags & VM_CALL_FCALL_BIT) != 0
|
64
|
+
bug() if flags & VM_CALL_OPT_SEND_BIT != 0 # VM_CALL_OPT_SEND_BIT is set at the vm_call_method
|
65
|
+
bug() if flags & VM_CALL_SUPER_BIT != 0 # VM_CALL_SUPER_BIT is set at the invokesuper
|
66
|
+
#VM_CALL_VCALL_BIT: variable or call, 要検討
|
67
|
+
when :opt_plus
|
68
|
+
id = "+".intern
|
69
|
+
argc = 1
|
70
|
+
when :opt_minus
|
71
|
+
id = "-".intern
|
72
|
+
argc = 1
|
73
|
+
when :opt_mult
|
74
|
+
id = "*".intern
|
75
|
+
argc = 1
|
76
|
+
when :opt_div
|
77
|
+
id = "/".intern
|
78
|
+
argc = 1
|
79
|
+
when :opt_mod
|
80
|
+
id = "%".intern
|
81
|
+
argc = 1
|
82
|
+
when :opt_lt
|
83
|
+
id = "<".intern
|
84
|
+
argc = 1
|
85
|
+
when :opt_le
|
86
|
+
id = "<=".intern
|
87
|
+
argc = 1
|
88
|
+
when :opt_gt
|
89
|
+
id = ">".intern
|
90
|
+
argc = 1
|
91
|
+
when :opt_ge
|
92
|
+
id = ">=".intern
|
93
|
+
argc = 1
|
94
|
+
when :opt_neq
|
95
|
+
id = "!=".intern
|
96
|
+
argc = 1
|
97
|
+
when :opt_eq
|
98
|
+
id = "==".intern
|
99
|
+
argc = 1
|
100
|
+
when :opt_ltlt
|
101
|
+
id = "<<".intern
|
102
|
+
argc = 1
|
103
|
+
when :opt_aref
|
104
|
+
id = "[]".intern
|
105
|
+
argc = 1
|
106
|
+
when :opt_length
|
107
|
+
id = :length
|
108
|
+
argc = 0
|
109
|
+
when :opt_size
|
110
|
+
id = :size
|
111
|
+
argc = 0
|
112
|
+
when :opt_not
|
113
|
+
id = "!".intern
|
114
|
+
argc = 0
|
115
|
+
when :opt_succ
|
116
|
+
id = :succ
|
117
|
+
argc = 0
|
118
|
+
else
|
119
|
+
bug()
|
120
|
+
end
|
121
|
+
|
122
|
+
if (flags & VM_CALL_ARGS_BLOCKARG_BIT) != 0
|
123
|
+
blockarg = TmpVariable.new(stack.pop())
|
124
|
+
else
|
125
|
+
blockarg = nil
|
126
|
+
end
|
127
|
+
|
128
|
+
args = []
|
129
|
+
argc.times { args << TmpVariable.new(stack.pop()) }
|
130
|
+
|
131
|
+
if fcall
|
132
|
+
stack.pop();
|
133
|
+
irs << SubIR.new(Self.new(translator), TmpVariable.new(stack.push()), InsnInfo.new([:putself], insn.iseq, -1, -1, true), cfg)
|
134
|
+
end
|
135
|
+
recv = TmpVariable.new(stack.pop())
|
136
|
+
recv.is_also(insn.ic_class) if insn.ic_class
|
137
|
+
param = []
|
138
|
+
param << ParamIR.new(recv, insn, cfg)
|
139
|
+
param += args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
140
|
+
if blockarg
|
141
|
+
param << ParamIR.new(blockarg, insn, cfg)
|
142
|
+
argc += 1
|
143
|
+
end
|
144
|
+
|
145
|
+
irs += param
|
146
|
+
irs << InvokeIR.new(id, flags, param, argc + 1, TmpVariable.new(stack.push()), insn, cfg)
|
147
|
+
when :invokeblock
|
148
|
+
num = argv[0]
|
149
|
+
flags = argv[1]
|
150
|
+
|
151
|
+
block_argument_is_unsupported(translator, insn) if flags & VM_CALL_ARGS_BLOCKARG_BIT != 0
|
152
|
+
|
153
|
+
args = []
|
154
|
+
num.times { args << TmpVariable.new(stack.pop()) }
|
155
|
+
param = []
|
156
|
+
param += args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
157
|
+
|
158
|
+
irs += param
|
159
|
+
irs << YieldIR.new(flags, param, num, TmpVariable.new(stack.push()), insn, cfg)
|
160
|
+
when :putnil
|
161
|
+
irs << SubIR.new(Literal.new(nil, translator), TmpVariable.new(stack.push()), insn, cfg)
|
162
|
+
when :putself
|
163
|
+
irs << SubIR.new(Self.new(translator), TmpVariable.new(stack.push()), insn, cfg)
|
164
|
+
when :putstring
|
165
|
+
obj = argv[0]
|
166
|
+
param = []
|
167
|
+
param << ParamIR.new(Literal.new(obj, translator), insn, cfg)
|
168
|
+
irs += param
|
169
|
+
irs << Putstring.new(param, 1, TmpVariable.new(stack.push()), insn, cfg)
|
170
|
+
when :putobject
|
171
|
+
obj = argv[0]
|
172
|
+
irs << SubIR.new(Literal.new(obj, translator), TmpVariable.new(stack.push()), insn, cfg)
|
173
|
+
when :newarray
|
174
|
+
argc = argv[0]
|
175
|
+
args = []
|
176
|
+
argc.times { args << TmpVariable.new(stack.pop()) }
|
177
|
+
param = args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
178
|
+
irs += param
|
179
|
+
irs << Newarray.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
180
|
+
when :newhash
|
181
|
+
argc = argv[0]
|
182
|
+
args = []
|
183
|
+
argc.times { args << TmpVariable.new(stack.pop()) }
|
184
|
+
param = args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
185
|
+
irs += param
|
186
|
+
irs << Newhash.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
187
|
+
when :duparray
|
188
|
+
obj = argv[0]
|
189
|
+
param = []
|
190
|
+
param << ParamIR.new(Literal.new(obj, translator), insn, cfg)
|
191
|
+
irs += param
|
192
|
+
irs << Duparray.new(param, 1, TmpVariable.new(stack.push()), insn, cfg)
|
193
|
+
when :tostring
|
194
|
+
param = []
|
195
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
196
|
+
irs += param
|
197
|
+
irs << Tostring.new(param, 1, TmpVariable.new(stack.push()), insn, cfg)
|
198
|
+
when :toregexp
|
199
|
+
cnt = argv[1]
|
200
|
+
args = []
|
201
|
+
cnt.times { args << TmpVariable.new(stack.pop()) }
|
202
|
+
param = args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
203
|
+
irs += param
|
204
|
+
irs << Toregexp.new(param, cnt, TmpVariable.new(stack.push()), insn, cfg)
|
205
|
+
when :concatstrings
|
206
|
+
argc = argv[0]
|
207
|
+
args = []
|
208
|
+
argc.times { args << TmpVariable.new(stack.pop()) }
|
209
|
+
param = args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
210
|
+
irs += param
|
211
|
+
irs << Concatstrings.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
212
|
+
when :concatarray
|
213
|
+
argc = 2
|
214
|
+
args = []
|
215
|
+
argc.times { args << TmpVariable.new(stack.pop()) }
|
216
|
+
param = args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
217
|
+
irs += param
|
218
|
+
irs << Concatarray.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
219
|
+
when :newrange
|
220
|
+
flag = argv[0]
|
221
|
+
argc = 2
|
222
|
+
args = []
|
223
|
+
argc.times { args << TmpVariable.new(stack.pop()) }
|
224
|
+
param = args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
225
|
+
irs += param
|
226
|
+
irs << Newrange.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
227
|
+
when :opt_regexpmatch1
|
228
|
+
r = argv[0]
|
229
|
+
argc = 2
|
230
|
+
param = []
|
231
|
+
param << ParamIR.new(Literal.new(r, translator), insn, cfg)
|
232
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
233
|
+
irs += param
|
234
|
+
irs << OptRegexpmatch1.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
235
|
+
when :opt_regexpmatch2
|
236
|
+
argc = 2
|
237
|
+
param = []
|
238
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
239
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
240
|
+
irs += param
|
241
|
+
irs << OptRegexpmatch2.new(param, argc, TmpVariable.new(stack.push()), insn, cfg)
|
242
|
+
when :expandarray
|
243
|
+
num, flag = *argv
|
244
|
+
is_splat = (flag & 0x01) != 0
|
245
|
+
|
246
|
+
op = :expandarray_pre
|
247
|
+
# param が Array かどうかという情報は使用しないので、ガードは不要
|
248
|
+
expandarray_pre_insn = InsnInfo.new([op], insn.iseq, -1, -1, true)
|
249
|
+
param = []
|
250
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), expandarray_pre_insn, cfg)
|
251
|
+
irs += param
|
252
|
+
irs << ExpandarrayPre.new(param, 1, TmpVariable.new(stack.push()), expandarray_pre_insn, cfg)
|
253
|
+
|
254
|
+
depth = stack.pop()
|
255
|
+
if is_splat
|
256
|
+
ary_depth = depth + num + 1
|
257
|
+
else
|
258
|
+
ary_depth = depth + num
|
259
|
+
end
|
260
|
+
irs << SubIR.new(TmpVariable.new(depth), TmpVariable.new(ary_depth), expandarray_pre_insn, cfg)
|
261
|
+
|
262
|
+
if flag & 0x02 != 0
|
263
|
+
# post: ..., nil ,ary[-1], ..., ary[0..-num] # top
|
264
|
+
op = :expandarray_post_loop
|
265
|
+
num.times do |i|
|
266
|
+
# param は Array だと分かっているので、ガードは不要
|
267
|
+
expandarray_post_loop_insn = InsnInfo.new([op, num, i], insn.iseq, -1, -1, true)
|
268
|
+
param = []
|
269
|
+
param << ParamIR.new(TmpVariable.new(ary_depth), expandarray_post_loop_insn, cfg)
|
270
|
+
irs += param
|
271
|
+
irs << ExpandarrayPostLoop.new(param, 1, TmpVariable.new(stack.push()), expandarray_post_loop_insn, cfg)
|
272
|
+
end
|
273
|
+
op = :expandarray_post_splat
|
274
|
+
if is_splat
|
275
|
+
# param は Array だと分かっているので、ガードは不要
|
276
|
+
expandarray_post_splat_insn = InsnInfo.new([op, num], insn.iseq, -1, -1, true)
|
277
|
+
param = []
|
278
|
+
param << ParamIR.new(TmpVariable.new(ary_depth), expandarray_post_splat_insn, cfg)
|
279
|
+
irs += param
|
280
|
+
irs << ExpandarrayPostSplat.new(param, 1, TmpVariable.new(stack.push()), expandarray_post_splat_insn, cfg)
|
281
|
+
end
|
282
|
+
else
|
283
|
+
# normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top
|
284
|
+
op = :expandarray_splat
|
285
|
+
if is_splat
|
286
|
+
# param は Array だと分かっているので、ガードは不要
|
287
|
+
expandarray_splat_insn = InsnInfo.new([op, num], insn.iseq, -1, -1, true)
|
288
|
+
param = []
|
289
|
+
param << ParamIR.new(TmpVariable.new(ary_depth), expandarray_splat_insn, cfg)
|
290
|
+
irs += param
|
291
|
+
irs << ExpandarraySplat.new(param, 1, TmpVariable.new(stack.push()), expandarray_splat_insn, cfg)
|
292
|
+
end
|
293
|
+
op = :expandarray_loop
|
294
|
+
num.times do |i|
|
295
|
+
# param は Array だと分かっているので、ガードは不要
|
296
|
+
expandarray_loop_insn = InsnInfo.new([op, num - i - 1], insn.iseq, -1, -1, true)
|
297
|
+
param = []
|
298
|
+
param << ParamIR.new(TmpVariable.new(ary_depth), expandarray_loop_insn, cfg)
|
299
|
+
irs += param
|
300
|
+
irs << ExpandarrayLoop.new(param, 1, TmpVariable.new(stack.push()), expandarray_loop_insn, cfg)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
when :splatarray
|
304
|
+
param = []
|
305
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
306
|
+
irs += param
|
307
|
+
irs << Splatarray.new(param, 1, TmpVariable.new(stack.push()), insn, cfg)
|
308
|
+
when :checkincludearray
|
309
|
+
flag = argv[0]
|
310
|
+
op = :checkincludearray_pre
|
311
|
+
# param が Array かどうかという情報は使用しないので、ガードは不要
|
312
|
+
checkincludearray_pre_insn = InsnInfo.new([op], insn.iseq, -1, -1, true)
|
313
|
+
param = []
|
314
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), checkincludearray_pre_insn, cfg) # ary
|
315
|
+
irs += param
|
316
|
+
irs << CheckincludearrayPre.new(param, 1, TmpVariable.new(stack.push()), checkincludearray_pre_insn, cfg)
|
317
|
+
|
318
|
+
if flag == true
|
319
|
+
op = :checkincludearray_case
|
320
|
+
# ary は Array だと分かっているので、ガードは不要
|
321
|
+
# obj の型情報は使用しないので、ガードは不要
|
322
|
+
checkincludearray_case_insn = InsnInfo.new([op], insn.iseq, -1, -1, true)
|
323
|
+
param = []
|
324
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), checkincludearray_case_insn, cfg) # ary
|
325
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), checkincludearray_case_insn, cfg) # obj
|
326
|
+
stack.push() # obj
|
327
|
+
irs += param
|
328
|
+
irs << CheckincludearrayCase.new(param, 2, TmpVariable.new(stack.push()), checkincludearray_case_insn, cfg) #result
|
329
|
+
elsif flag == false
|
330
|
+
op = :checkincludearray_when
|
331
|
+
# ary は Array だと分かっているので、ガードは不要
|
332
|
+
checkincludearray_when_insn = InsnInfo.new([op], insn.iseq, -1, -1, true)
|
333
|
+
param = []
|
334
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), checkincludearray_when_insn, cfg) # ary
|
335
|
+
stack.pop() # obj
|
336
|
+
result_depth = stack.push() # result
|
337
|
+
irs += param
|
338
|
+
irs << CheckincludearrayWhen.new(param, 1, TmpVariable.new(result_depth), checkincludearray_when_insn, cfg)
|
339
|
+
irs << SubIR.new(TmpVariable.new(result_depth), TmpVariable.new(stack.push()), checkincludearray_when_insn, cfg)
|
340
|
+
else
|
341
|
+
bug()
|
342
|
+
end
|
343
|
+
when :cast_off_decl_arg
|
344
|
+
if translator.inline_block?
|
345
|
+
irs << SubIR.new(Argument.new(*argv), LocalVariable.new(*argv), insn, cfg)
|
346
|
+
else
|
347
|
+
irs << SubIR.new(Argument.new(*argv), DynamicVariable.new(*argv), insn, cfg)
|
348
|
+
end
|
349
|
+
when :cast_off_decl_var
|
350
|
+
if translator.inline_block?
|
351
|
+
irs << SubIR.new(Literal.new(nil, translator), LocalVariable.new(*argv), insn, cfg)
|
352
|
+
else
|
353
|
+
ir = SubIR.new(Literal.new(nil, translator), DynamicVariable.new(*argv), insn, cfg)
|
354
|
+
ir.vanish()
|
355
|
+
irs << ir
|
356
|
+
end
|
357
|
+
when :cast_off_getconst
|
358
|
+
irs << SubIR.new(ConstWrapper.new(*argv, translator), TmpVariable.new(stack.push()), insn, cfg)
|
359
|
+
when :cast_off_getgvar
|
360
|
+
irs << SubIR.new(GlobalVariable.new(*argv, translator), TmpVariable.new(stack.push()), insn, cfg)
|
361
|
+
when :cast_off_getcvar
|
362
|
+
irs << SubIR.new(ClassVariable.new(*argv), TmpVariable.new(stack.push()), insn, cfg)
|
363
|
+
when :cast_off_getivar
|
364
|
+
irs << SubIR.new(InstanceVariable.new(*argv), TmpVariable.new(stack.push()), insn, cfg)
|
365
|
+
when :cast_off_getlvar
|
366
|
+
irs << SubIR.new(LocalVariable.new(*argv), TmpVariable.new(stack.push()), insn, cfg)
|
367
|
+
when :cast_off_getdvar
|
368
|
+
irs << SubIR.new(DynamicVariable.new(*argv), TmpVariable.new(stack.push()), insn, cfg)
|
369
|
+
when :getdynamic, :setdynamic
|
370
|
+
bug()
|
371
|
+
when :cast_off_setgvar
|
372
|
+
irs << SubIR.new(TmpVariable.new(stack.pop()), GlobalVariable.new(*argv, translator), insn, cfg)
|
373
|
+
when :cast_off_setcvar
|
374
|
+
irs << SubIR.new(TmpVariable.new(stack.pop()), ClassVariable.new(*argv), insn, cfg)
|
375
|
+
when :cast_off_setivar
|
376
|
+
irs << SubIR.new(TmpVariable.new(stack.pop()), InstanceVariable.new(*argv), insn, cfg)
|
377
|
+
when :cast_off_setlvar
|
378
|
+
irs << SubIR.new(TmpVariable.new(stack.pop()), LocalVariable.new(*argv), insn, cfg)
|
379
|
+
when :cast_off_setdvar
|
380
|
+
irs << SubIR.new(TmpVariable.new(stack.pop()), DynamicVariable.new(*argv), insn, cfg)
|
381
|
+
when :getspecial
|
382
|
+
param = []
|
383
|
+
irs << Getspecial.new(param, 0, TmpVariable.new(stack.push()), insn, cfg)
|
384
|
+
when :jump, :cast_off_enter_block, :cast_off_leave_block
|
385
|
+
bug("op = #{op}, depth = #{stack.depth}") if op == :cast_off_leave_block && (stack.depth - 1) != insn.iseq.depth
|
386
|
+
irs << JumpIR.new(nil, insn, cfg)
|
387
|
+
when :cast_off_break_block
|
388
|
+
bug("op = #{op}, depth = #{stack.depth}") if (stack.depth - 1) != insn.iseq.depth
|
389
|
+
d = stack.pop()
|
390
|
+
stack.push()
|
391
|
+
irs << SubIR.new(TmpVariable.new(d), TmpVariable.new(stack.push()), insn, cfg)
|
392
|
+
irs << JumpIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
393
|
+
when :branchunless, :branchif, :cast_off_continue_loop
|
394
|
+
target = argv[0]
|
395
|
+
irs << JumpIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
396
|
+
when :pop
|
397
|
+
stack.pop()
|
398
|
+
when :adjuststack
|
399
|
+
# same as popn instruction
|
400
|
+
num = argv[0]
|
401
|
+
num.times { stack.pop() }
|
402
|
+
when :setn
|
403
|
+
# deep <-----------------------
|
404
|
+
# e.g. num = 3, [:a, :b, :c, :d] => [:d, :b, :c, :d]
|
405
|
+
num = argv[0]
|
406
|
+
dst = stack.pop() - num
|
407
|
+
src = stack.push()
|
408
|
+
irs << SubIR.new(TmpVariable.new(src), TmpVariable.new(dst), insn, cfg)
|
409
|
+
when :dupn
|
410
|
+
# deep <-----------------------
|
411
|
+
# e.g. [:a, :b, :c] => [:a, :b, :c, :a, :b, :c]
|
412
|
+
num = argv[0]
|
413
|
+
num.times do
|
414
|
+
depth = stack.push()
|
415
|
+
irs << SubIR.new(TmpVariable.new(depth - num), TmpVariable.new(depth), insn, cfg)
|
416
|
+
end
|
417
|
+
when :dup
|
418
|
+
depth = stack.push()
|
419
|
+
irs << SubIR.new(TmpVariable.new(depth - 1), TmpVariable.new(depth), insn, cfg)
|
420
|
+
when :swap
|
421
|
+
tmp = stack.push()
|
422
|
+
stack.pop()
|
423
|
+
v0 = tmp - 1
|
424
|
+
v1 = tmp - 2
|
425
|
+
irs << SubIR.new(TmpVariable.new(v0), TmpVariable.new(tmp), insn, cfg)
|
426
|
+
irs << SubIR.new(TmpVariable.new(v1), TmpVariable.new(v0), insn, cfg)
|
427
|
+
irs << SubIR.new(TmpVariable.new(tmp), TmpVariable.new(v1), insn, cfg)
|
428
|
+
when :topn
|
429
|
+
n = argv[0]
|
430
|
+
dst = stack.push()
|
431
|
+
irs << SubIR.new(TmpVariable.new(dst - n - 1), TmpVariable.new(dst), insn, cfg)
|
432
|
+
when :throw
|
433
|
+
type, state, flag, level = insn.get_throw_info()
|
434
|
+
if flag != 0
|
435
|
+
bug()
|
436
|
+
else
|
437
|
+
case type
|
438
|
+
when :return
|
439
|
+
irs << ReturnIR.new(TmpVariable.new(stack.pop()), ReturnIR::ThrowObj.new(type, argv[0], state, flag, level), insn, cfg)
|
440
|
+
else
|
441
|
+
bug()
|
442
|
+
end
|
443
|
+
end
|
444
|
+
when :cast_off_prep
|
445
|
+
# stack には argc + 1 積まれている
|
446
|
+
depth = argv[0]
|
447
|
+
loop_args = argv[1]
|
448
|
+
send_insn = argv[2]
|
449
|
+
send_argv = send_insn.argv
|
450
|
+
send_id = send_argv[0]
|
451
|
+
send_argc = send_argv[1]
|
452
|
+
send_flags = send_argv[3]
|
453
|
+
fcall = (send_flags & VM_CALL_FCALL_BIT) != 0
|
454
|
+
bug() if send_flags & VM_CALL_OPT_SEND_BIT != 0 # VM_CALL_OPT_SEND_BIT is set at the vm_call_method
|
455
|
+
bug() if send_flags & VM_CALL_SUPER_BIT != 0 # VM_CALL_SUPER_BIT is set at the invokesuper
|
456
|
+
block_argument_is_unsupported(translator, insn) if send_flags & VM_CALL_ARGS_BLOCKARG_BIT != 0
|
457
|
+
#VM_CALL_VCALL_BIT: variable or call, 要検討
|
458
|
+
raise UnsupportedError.new(<<-EOS) if send_flags & VM_CALL_ARGS_SPLAT_BIT != 0
|
459
|
+
|
460
|
+
Currently, CastOff doesn't support a method invocation which takes a splat argument (like *arg) and which takes a block.
|
461
|
+
------------------------------------------------------------------------------------------------------------------------
|
462
|
+
Target file is (#{translator.target_name()}).
|
463
|
+
Call site is (#{insn}).
|
464
|
+
EOS
|
465
|
+
|
466
|
+
send_args = []
|
467
|
+
send_argc.times { send_args << TmpVariable.new(stack.pop()) }
|
468
|
+
|
469
|
+
if fcall
|
470
|
+
stack.pop();
|
471
|
+
irs << SubIR.new(Self.new(translator), TmpVariable.new(stack.push()), InsnInfo.new([:putself], insn.iseq, -1, -1, true), cfg)
|
472
|
+
end
|
473
|
+
recv = TmpVariable.new(stack.pop())
|
474
|
+
param = []
|
475
|
+
param << ParamIR.new(recv, insn, cfg)
|
476
|
+
param += send_args.reverse.map{|arg| ParamIR.new(arg, insn, cfg)}
|
477
|
+
|
478
|
+
# loop のための key object を返す, reciever オブジェクト + context (map の場合は返り値の配列 + 帰納変数)
|
479
|
+
# rb_ary_each_context_t みたいなのを作る
|
480
|
+
# block = true だった場合、recv と id から関数名を特定して、それ用の関数を呼ぶ。返り値は loopkey
|
481
|
+
# loopkey は cast_off_ary_each_context_t みたいな構造体
|
482
|
+
loopkey = LoopKey.new(send_id, depth, loop_args, insn, cfg.translator)
|
483
|
+
translator.loopkey[depth] = loopkey
|
484
|
+
irs += param
|
485
|
+
irs << LoopIR.new(loopkey, op, param, send_argc + 1, TmpVariable.new(stack.push()), insn, cfg)
|
486
|
+
when :cast_off_loop
|
487
|
+
depth = argv[0]
|
488
|
+
send_insn = argv[2]
|
489
|
+
send_argv = send_insn.argv
|
490
|
+
send_id = send_argv[0]
|
491
|
+
|
492
|
+
# loopkey を引数で渡す。返り値は true(ループ継続) or false(ループ終了)
|
493
|
+
loopkey = translator.loopkey[depth]
|
494
|
+
bug() unless loopkey
|
495
|
+
param = []
|
496
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
497
|
+
irs += param
|
498
|
+
irs << LoopIR.new(loopkey, op, param, 1, TmpVariable.new(stack.push()), insn, cfg)
|
499
|
+
when :cast_off_cont
|
500
|
+
depth = argv[0]
|
501
|
+
args = argv[1]
|
502
|
+
if translator.inline_block?
|
503
|
+
args.each_with_index{|arg, i| irs << SubIR.new(TmpBuffer.new(i), LocalVariable.new(*arg), insn, cfg)}
|
504
|
+
else
|
505
|
+
args.each_with_index{|arg, i| irs << SubIR.new(TmpBuffer.new(i), DynamicVariable.new(*arg), insn, cfg)}
|
506
|
+
end
|
507
|
+
loopkey = translator.loopkey[depth]
|
508
|
+
loopkey.block_iseq = insn.iseq
|
509
|
+
insn.iseq.set_loopkey(loopkey)
|
510
|
+
insn.iseq.use_temporary_c_ary(args.size())
|
511
|
+
when :cast_off_finl
|
512
|
+
depth = argv[0]
|
513
|
+
send_insn = argv[2]
|
514
|
+
send_argv = send_insn.argv
|
515
|
+
send_id = send_argv[0]
|
516
|
+
loopkey = translator.loopkey[depth]
|
517
|
+
bug() unless loopkey
|
518
|
+
param = []
|
519
|
+
irs << LoopIR.new(loopkey, op, param, 0, TmpVariable.new(stack.push()), insn, cfg)
|
520
|
+
when :cast_off_fetch_args
|
521
|
+
param = []
|
522
|
+
if argv[0]
|
523
|
+
args = argv[0].last
|
524
|
+
if translator.inline_block?
|
525
|
+
args.map!{|arg| LocalVariable.new(*arg).to_name() }
|
526
|
+
else
|
527
|
+
args.map!{|arg| DynamicVariable.new(*arg).to_name() }
|
528
|
+
end
|
529
|
+
end
|
530
|
+
irs << CastOffFetchArgs.new(param, 0, TmpVariable.new(stack.push()), insn, cfg)
|
531
|
+
when :cast_off_handle_optional_args
|
532
|
+
irs << JumpIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
533
|
+
when :leave
|
534
|
+
depth = stack.pop()
|
535
|
+
unless depth == 0
|
536
|
+
if translator.inline_block?
|
537
|
+
# throw => leave
|
538
|
+
else
|
539
|
+
bug()
|
540
|
+
end
|
541
|
+
end
|
542
|
+
irs << ReturnIR.new(TmpVariable.new(depth), nil, insn, cfg)
|
543
|
+
when :defined
|
544
|
+
t = argv[0]
|
545
|
+
case t
|
546
|
+
when DEFINED_IVAR, DEFINED_GVAR, DEFINED_FUNC
|
547
|
+
# ok
|
548
|
+
when DEFINED_IVAR2
|
549
|
+
bug("unexpected defined instruction")
|
550
|
+
when DEFINED_CVAR
|
551
|
+
raise(UnsupportedError.new("Currently, CastOff cannot handle defined instruction for class variable"))
|
552
|
+
when DEFINED_CONST
|
553
|
+
raise(UnsupportedError.new("Currently, CastOff cannot handle defined instruction for constant"))
|
554
|
+
when DEFINED_METHOD
|
555
|
+
raise(UnsupportedError.new("Currently, CastOff cannot handle defined instruction for methods"))
|
556
|
+
when DEFINED_YIELD
|
557
|
+
raise(UnsupportedError.new("Currently, CastOff cannot handle defined instruction for yield"))
|
558
|
+
when DEFINED_REF
|
559
|
+
raise(UnsupportedError.new("Currently, CastOff cannot handle defined instruction for global-variable"))
|
560
|
+
when DEFINED_ZSUPER
|
561
|
+
raise(UnsupportedError.new("Currently, CastOff cannot handle defined instruction for super"))
|
562
|
+
else
|
563
|
+
bug()
|
564
|
+
end
|
565
|
+
|
566
|
+
param = []
|
567
|
+
param << ParamIR.new(TmpVariable.new(stack.pop()), insn, cfg)
|
568
|
+
irs += param
|
569
|
+
irs << Defined.new(param, 1, TmpVariable.new(stack.push()), insn, cfg)
|
570
|
+
else
|
571
|
+
raise(UnsupportedError, "unsupported RubyVM instruction #{insn} ")
|
572
|
+
end
|
573
|
+
unless stack.depth == insn.depth + insn.stack_usage()
|
574
|
+
bug("stack.depth = #{stack.depth}, insn.depth = #{insn.depth + insn.stack_usage()}, insn = #{insn}\n#{irs.join("\n")}\n")
|
575
|
+
end
|
576
|
+
end
|
577
|
+
irs
|
578
|
+
end
|
579
|
+
|
580
|
+
class IR
|
581
|
+
include CastOff::Util
|
582
|
+
|
583
|
+
attr_reader :insn, :alias
|
584
|
+
|
585
|
+
def initialize(insn, cfg)
|
586
|
+
@insn = insn
|
587
|
+
@cfg = cfg
|
588
|
+
@translator = cfg.translator
|
589
|
+
@configuration = @translator.configuration
|
590
|
+
@dependency = @translator.dependency
|
591
|
+
@information = nil
|
592
|
+
@alias = nil
|
593
|
+
@alive = false
|
594
|
+
@valish_p = false
|
595
|
+
@sampling_variable = []
|
596
|
+
end
|
597
|
+
|
598
|
+
def vanish()
|
599
|
+
@vanish_p = true
|
600
|
+
end
|
601
|
+
|
602
|
+
def vanish?
|
603
|
+
@vanish_p
|
604
|
+
end
|
605
|
+
|
606
|
+
### unboxing begin ###
|
607
|
+
def unboxing_prelude()
|
608
|
+
bug()
|
609
|
+
end
|
610
|
+
|
611
|
+
def propergate_value_which_can_not_unbox(defs)
|
612
|
+
bug()
|
613
|
+
end
|
614
|
+
|
615
|
+
def propergate_unbox_value(defs)
|
616
|
+
bug()
|
617
|
+
end
|
618
|
+
### unboxing end ###
|
619
|
+
|
620
|
+
def sampling_variable()
|
621
|
+
s = []
|
622
|
+
if @configuration.development?
|
623
|
+
@sampling_variable.each do |var|
|
624
|
+
next if var.is_a?(Literal)
|
625
|
+
s << " sampling_variable(#{var}, ID2SYM(rb_intern(#{var.source.inspect})));"
|
626
|
+
end
|
627
|
+
end
|
628
|
+
s.empty? ? nil : s.join("\n")
|
629
|
+
end
|
630
|
+
|
631
|
+
def add_sampling_variable(var)
|
632
|
+
@sampling_variable |= [var]
|
633
|
+
end
|
634
|
+
|
635
|
+
def alive()
|
636
|
+
@alive ? false : (@alive = true)
|
637
|
+
end
|
638
|
+
|
639
|
+
def alive?
|
640
|
+
@alive
|
641
|
+
end
|
642
|
+
|
643
|
+
def reset()
|
644
|
+
@alive = false
|
645
|
+
@variables.each{|v| v.reset()}
|
646
|
+
end
|
647
|
+
|
648
|
+
def standard_guard_target()
|
649
|
+
nil
|
650
|
+
end
|
651
|
+
|
652
|
+
def propergate_guard_usage()
|
653
|
+
# nothing to do
|
654
|
+
end
|
655
|
+
|
656
|
+
def generate_guard(vars)
|
657
|
+
target = standard_guard_target()
|
658
|
+
if target.is_a?(Variable) && !target.dynamic? && @insn.need_guard?
|
659
|
+
# FIXME target <= should be dup
|
660
|
+
StandardGuard.new(target, vars, @insn, @cfg)
|
661
|
+
else
|
662
|
+
nil
|
663
|
+
end
|
664
|
+
end
|
665
|
+
|
666
|
+
def get_usage()
|
667
|
+
blocks = []
|
668
|
+
usage = {}
|
669
|
+
irs = [self]
|
670
|
+
change = true
|
671
|
+
while change
|
672
|
+
change = false
|
673
|
+
@cfg.blocks.each do |b|
|
674
|
+
foo = b.irs & irs
|
675
|
+
bar = b.information.variable_definition & irs
|
676
|
+
if foo.size > 0 || bar.size > 0
|
677
|
+
vars = []
|
678
|
+
bar.each do |ir|
|
679
|
+
result_variable = ir.result_variable
|
680
|
+
next unless result_variable
|
681
|
+
vars << result_variable
|
682
|
+
end
|
683
|
+
b.irs.each do |ir|
|
684
|
+
case ir
|
685
|
+
when SubIR
|
686
|
+
src = ir.src
|
687
|
+
dst = ir.dst
|
688
|
+
if src != dst
|
689
|
+
if vars.include?(dst)
|
690
|
+
vars.reject! {|v| v == dst}
|
691
|
+
#vars -= [dst]
|
692
|
+
end
|
693
|
+
if vars.include?(src)
|
694
|
+
if dst.is_a?(Pointer)
|
695
|
+
usage[:escape] = ir
|
696
|
+
return usage
|
697
|
+
end
|
698
|
+
vars |= [dst]
|
699
|
+
if !irs.include?(ir)
|
700
|
+
irs << ir
|
701
|
+
change = true
|
702
|
+
end
|
703
|
+
end
|
704
|
+
end
|
705
|
+
when JumpIR
|
706
|
+
# nothing to do
|
707
|
+
when ParamIR
|
708
|
+
if vars.include?(ir.param_value) && !irs.include?(ir)
|
709
|
+
irs << ir
|
710
|
+
change = true
|
711
|
+
end
|
712
|
+
when CallIR
|
713
|
+
argc = ir.argc
|
714
|
+
return_value = ir.return_value
|
715
|
+
param = ir.param_variables()
|
716
|
+
param.each do |p|
|
717
|
+
if vars.include?(p)
|
718
|
+
usage[[param[0], ir]] = vars.index(param[0])
|
719
|
+
break
|
720
|
+
end
|
721
|
+
end
|
722
|
+
if vars.include?(return_value)
|
723
|
+
vars.reject! {|v| v == return_value}
|
724
|
+
#vars -= [return_value]
|
725
|
+
end
|
726
|
+
when ReturnIR
|
727
|
+
if vars.include?(ir.return_value)
|
728
|
+
usage[:escape] = ir
|
729
|
+
return usage
|
730
|
+
end
|
731
|
+
end
|
732
|
+
result_variable = ir.result_variable
|
733
|
+
vars |= [result_variable] if foo.include?(ir) && result_variable
|
734
|
+
end
|
735
|
+
end
|
736
|
+
end
|
737
|
+
end
|
738
|
+
usage
|
739
|
+
end
|
740
|
+
|
741
|
+
def set_info(d)
|
742
|
+
@information = d
|
743
|
+
end
|
744
|
+
|
745
|
+
def get_definition(target)
|
746
|
+
case target
|
747
|
+
when Self, Literal
|
748
|
+
return [target]
|
749
|
+
when Variable
|
750
|
+
ds = @information.variable_definition_of(target)
|
751
|
+
bug() if ds.empty?
|
752
|
+
ary = []
|
753
|
+
ds.each do |d|
|
754
|
+
case d
|
755
|
+
when SubIR
|
756
|
+
src = d.src
|
757
|
+
if src.is_a?(TmpVariable)
|
758
|
+
ary += d.get_definition(src)
|
759
|
+
else
|
760
|
+
ary << d
|
761
|
+
end
|
762
|
+
when CallIR
|
763
|
+
ary << d
|
764
|
+
else
|
765
|
+
bug()
|
766
|
+
end
|
767
|
+
end
|
768
|
+
return ary
|
769
|
+
else
|
770
|
+
raise(UnsupportedError.new("Currently, CastOff cannot compile this method or block"))
|
771
|
+
end
|
772
|
+
bug()
|
773
|
+
end
|
774
|
+
|
775
|
+
def get_definition_str(target)
|
776
|
+
ary = get_definition(target)
|
777
|
+
ary.map {|d|
|
778
|
+
case d
|
779
|
+
when Self, Literal
|
780
|
+
d.source
|
781
|
+
when SubIR
|
782
|
+
d.src.source
|
783
|
+
when LoopIR, VMInsnIR
|
784
|
+
"vm internal value"
|
785
|
+
when InvokeIR
|
786
|
+
"result of #{d.to_verbose_string}"
|
787
|
+
when YieldIR
|
788
|
+
"result of yield"
|
789
|
+
else
|
790
|
+
bug()
|
791
|
+
end
|
792
|
+
}.join("\n")
|
793
|
+
end
|
794
|
+
|
795
|
+
def dispatch_method?
|
796
|
+
# FIXME 型情報を活用(Fixnum#+ とかはインスタンス変数を触らないよね)
|
797
|
+
return true if !@translator.inline_block? && self.is_a?(LoopIR)
|
798
|
+
self.is_a?(InvokeIR) || self.is_a?(YieldIR)
|
799
|
+
end
|
800
|
+
|
801
|
+
def inlining_target?
|
802
|
+
false
|
803
|
+
end
|
804
|
+
end
|
805
|
+
end
|
806
|
+
end
|
807
|
+
end
|
808
|
+
|