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,144 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
module CastOff::Compiler
|
4
|
+
class Translator::CFG
|
5
|
+
class BasicBlock
|
6
|
+
include CastOff::Util
|
7
|
+
include CastOff::Compiler::Instruction
|
8
|
+
include CastOff::Compiler::SimpleIR
|
9
|
+
|
10
|
+
attr_reader :insns, :pre, :next, :labels, :number, :irs, :iseq
|
11
|
+
|
12
|
+
def initialize(cfg, insns, number)
|
13
|
+
@cfg = cfg
|
14
|
+
@insns = insns
|
15
|
+
bug() if @insns.find{|i| not i.instance_of?(InsnInfo)}
|
16
|
+
@number = number
|
17
|
+
@pre = nil
|
18
|
+
@next = nil
|
19
|
+
@labels = []
|
20
|
+
@irs = nil
|
21
|
+
@entry_point = number == 0
|
22
|
+
@iseq = @insns[0].iseq
|
23
|
+
bug() if @insns.find{|i| i.iseq != @iseq}
|
24
|
+
end
|
25
|
+
|
26
|
+
def entry_point?
|
27
|
+
@entry_point
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_prev_block(blocks)
|
31
|
+
@pre = []
|
32
|
+
index = blocks.index(self)
|
33
|
+
if index != 0
|
34
|
+
pre = blocks[index - 1]
|
35
|
+
case pre
|
36
|
+
when Symbol
|
37
|
+
# this block is branch or jump target
|
38
|
+
@labels << pre
|
39
|
+
i = index - 2
|
40
|
+
while i >= 0
|
41
|
+
break unless blocks[i].is_a?(Symbol)
|
42
|
+
@labels << blocks[i]
|
43
|
+
i -= 1
|
44
|
+
end
|
45
|
+
matchlabels = []
|
46
|
+
blocks.each do |basicblock|
|
47
|
+
case basicblock when BasicBlock
|
48
|
+
last_insn = basicblock.insns.last
|
49
|
+
op = last_insn.op
|
50
|
+
argv = last_insn.argv
|
51
|
+
if BranchInstruction.include?(op)
|
52
|
+
case op
|
53
|
+
when :jump, :branchunless, :branchif, \
|
54
|
+
:cast_off_enter_block, :cast_off_leave_block, :cast_off_continue_loop, \
|
55
|
+
:cast_off_break_block
|
56
|
+
targets = [argv[0]]
|
57
|
+
when :cast_off_handle_optional_args
|
58
|
+
targets = argv[0]
|
59
|
+
else
|
60
|
+
bug("unexpected instruction #{op}")
|
61
|
+
end
|
62
|
+
targets.each do |t|
|
63
|
+
if @labels.include?(t)
|
64
|
+
matchlabels << t
|
65
|
+
@pre << basicblock unless @pre.include?(basicblock)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
if @pre.empty?
|
72
|
+
# join point with exception handler
|
73
|
+
# nothing to do
|
74
|
+
@labels = []
|
75
|
+
else
|
76
|
+
@labels = @labels & matchlabels
|
77
|
+
bug() if @labels.empty?
|
78
|
+
end
|
79
|
+
# consider fall-throuth from previous block
|
80
|
+
i = index - 2
|
81
|
+
while i >= 0
|
82
|
+
pre = blocks[i]
|
83
|
+
break if pre.is_a?(BasicBlock)
|
84
|
+
i -= 1
|
85
|
+
end
|
86
|
+
if pre.is_a?(BasicBlock)
|
87
|
+
last_insn = pre.insns.last
|
88
|
+
@pre << pre if !JumpOrReturnInstruction.include?(last_insn.op)
|
89
|
+
end
|
90
|
+
when BasicBlock
|
91
|
+
# fall-throuth from previous block
|
92
|
+
last_insn = pre.insns.last
|
93
|
+
if JumpOrReturnInstruction.include?(last_insn.op)
|
94
|
+
# dead block
|
95
|
+
else
|
96
|
+
@pre << pre
|
97
|
+
end
|
98
|
+
else
|
99
|
+
bug()
|
100
|
+
end
|
101
|
+
else
|
102
|
+
# entry point
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_next_block(blocks)
|
107
|
+
@next = []
|
108
|
+
bug() if blocks.find{|b| b.instance_of?(BasicBlock) && !b.pre }
|
109
|
+
blocks.each{|b| @next << b if b.instance_of?(BasicBlock) && b.pre.include?(self)}
|
110
|
+
end
|
111
|
+
|
112
|
+
def gen_ir()
|
113
|
+
@irs = generate_ir(@cfg, @insns, in_depth())
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_c()
|
117
|
+
params = []
|
118
|
+
codes = []
|
119
|
+
@labels.each{|label| codes << "#{label}:" }
|
120
|
+
@irs.each do |ir|
|
121
|
+
bug() unless ir.insn.iseq == @iseq
|
122
|
+
ir.variables.each{|v| @iseq.declare_local_variable("#{v.declare()} #{v}") if v.declare?}
|
123
|
+
case ir
|
124
|
+
when SubIR, JumpIR, ReturnIR, GuardIR
|
125
|
+
codes << ir.to_c()
|
126
|
+
when ParamIR
|
127
|
+
params << ir.param_value
|
128
|
+
when CallIR
|
129
|
+
codes << ir.to_c(params)
|
130
|
+
else
|
131
|
+
bug("invalid ir #{ir}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
bug() unless params.empty?
|
135
|
+
codes.join("\n")
|
136
|
+
end
|
137
|
+
|
138
|
+
def to_s()
|
139
|
+
"(#{@labels.join(", ")})BB#{@number}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
@@ -0,0 +1,391 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
|
3
|
+
module CastOff::Compiler
|
4
|
+
class Translator
|
5
|
+
class CFG
|
6
|
+
include CastOff::Util
|
7
|
+
include CastOff::Compiler::Instruction
|
8
|
+
include CastOff::Compiler::SimpleIR
|
9
|
+
|
10
|
+
attr_reader :blocks
|
11
|
+
|
12
|
+
def to_c()
|
13
|
+
@blocks.each{|b| b.iseq.append_c_function_body(b.to_c())}
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s()
|
17
|
+
@blocks.join("\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
def translator
|
21
|
+
bug() unless @translator
|
22
|
+
@translator
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(body)
|
26
|
+
@translator = nil
|
27
|
+
blocks = []
|
28
|
+
basicblock = []
|
29
|
+
body.each do |v|
|
30
|
+
case v
|
31
|
+
when InsnInfo
|
32
|
+
basicblock << v
|
33
|
+
if BlockSeparator.include?(v.op)
|
34
|
+
blocks << basicblock
|
35
|
+
basicblock = []
|
36
|
+
end
|
37
|
+
when Symbol
|
38
|
+
if !basicblock.empty?
|
39
|
+
blocks << basicblock
|
40
|
+
basicblock = []
|
41
|
+
end
|
42
|
+
blocks << v
|
43
|
+
else
|
44
|
+
bug("v = #{v}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
blocks << basicblock unless basicblock.empty?
|
48
|
+
|
49
|
+
bbnum = -1
|
50
|
+
blocks.map!{|b| b.instance_of?(Array) ? BasicBlock.new(self, b, bbnum += 1) : b}
|
51
|
+
blocks.each{|b| b.set_prev_block(blocks) if b.instance_of?(BasicBlock)}
|
52
|
+
blocks.each{|b| b.set_next_block(blocks) if b.instance_of?(BasicBlock)}
|
53
|
+
@blocks = blocks.select{|b| b.instance_of?(BasicBlock)}
|
54
|
+
@blocks.each{|b| bug() unless b.next && b.pre}
|
55
|
+
|
56
|
+
eliminate_unreachable_blocks()
|
57
|
+
validate_stack() # stack.rb
|
58
|
+
end
|
59
|
+
|
60
|
+
def gen_ir(t)
|
61
|
+
@translator = t
|
62
|
+
@blocks.each{|b| b.gen_ir()}
|
63
|
+
change = true
|
64
|
+
while change
|
65
|
+
change = false
|
66
|
+
set_information() # information.rb
|
67
|
+
type_propergation()
|
68
|
+
propergate_exact_class()
|
69
|
+
propergate_guard_usage()
|
70
|
+
inject_guards()
|
71
|
+
reject_redundant_guards()
|
72
|
+
if transform_branch_instruction()
|
73
|
+
eliminate_unreachable_blocks() # this method generates jump_guards
|
74
|
+
change = true
|
75
|
+
end
|
76
|
+
reject_unused_ir() # should be call after guard generation
|
77
|
+
change |= method_inlining()
|
78
|
+
if change
|
79
|
+
validate_stack() # stack.rb
|
80
|
+
reject_guards()
|
81
|
+
reset_ir()
|
82
|
+
end
|
83
|
+
end
|
84
|
+
unboxing()
|
85
|
+
attach_var_info()
|
86
|
+
set_sampling()
|
87
|
+
end
|
88
|
+
|
89
|
+
def find_variable(v0)
|
90
|
+
all_variable.find{|v1| v0 == v1}
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def all_ir()
|
96
|
+
@blocks.inject([]){|a, b| a.concat(b.irs)}.freeze()
|
97
|
+
end
|
98
|
+
|
99
|
+
def all_pointer_definition()
|
100
|
+
all_ir().select{|ir| ir.result_variable.is_a?(Pointer)}.freeze()
|
101
|
+
end
|
102
|
+
|
103
|
+
def all_pointer()
|
104
|
+
ptrs = all_pointer_definition().map{|ir| ir.result_variable}.uniq()
|
105
|
+
bug() if ptrs.find{|p| not p.is_a?(Pointer)}
|
106
|
+
ptrs.freeze()
|
107
|
+
end
|
108
|
+
|
109
|
+
def all_variable()
|
110
|
+
all_ir().inject([]){|a, ir| a.concat(ir.variables)}.uniq()
|
111
|
+
end
|
112
|
+
|
113
|
+
def reset_ir()
|
114
|
+
all_ir().each{|ir| ir.reset()}
|
115
|
+
end
|
116
|
+
|
117
|
+
def eliminate_unreachable_blocks()
|
118
|
+
# Breadth first search
|
119
|
+
achieved = []
|
120
|
+
vertex = nil
|
121
|
+
depth = 0
|
122
|
+
queue = [@blocks[0]]
|
123
|
+
while !queue.empty?
|
124
|
+
vertex = queue.shift()
|
125
|
+
bug() unless vertex
|
126
|
+
achieved << vertex
|
127
|
+
queue += vertex.next.select{|b| !queue.include?(b) && !achieved.include?(b)}
|
128
|
+
end
|
129
|
+
deadblocks = @blocks - achieved
|
130
|
+
achieved.each do |aliveblock|
|
131
|
+
aliveblock.pre.reject!{|b| deadblocks.include?(b)}
|
132
|
+
bug() if aliveblock.next.find{|b| deadblocks.include?(b)}
|
133
|
+
end
|
134
|
+
@blocks = achieved
|
135
|
+
@blocks.sort! {|a, b| a.number <=> b.number}
|
136
|
+
bug() if @blocks.find{|b| b.pre.empty? && !b.entry_point?}
|
137
|
+
end
|
138
|
+
|
139
|
+
def reject_unused_ir()
|
140
|
+
change = true
|
141
|
+
while change
|
142
|
+
change = false
|
143
|
+
@blocks.each do |b|
|
144
|
+
defs = b.information.dup
|
145
|
+
b.irs.each do |ir|
|
146
|
+
change |= ir.mark(defs)
|
147
|
+
defs.step(ir)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
@blocks.each do |b|
|
152
|
+
information = b.information.dup
|
153
|
+
information.reject!{|ir| not ir.alive?}
|
154
|
+
b.information = information
|
155
|
+
b.irs.reject!{|ir| not ir.alive?}
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def transform_branch_instruction()
|
160
|
+
change = false
|
161
|
+
@blocks.each do |b|
|
162
|
+
if b.next.size > 1
|
163
|
+
ir = b.irs.last
|
164
|
+
bug() unless ir.is_a?(JumpIR)
|
165
|
+
unused = ir.unused_target()
|
166
|
+
if unused
|
167
|
+
change = true
|
168
|
+
bug() unless b.next.size == 2
|
169
|
+
targets = ir.jump_targets
|
170
|
+
bug() unless targets.size() == 1
|
171
|
+
target = targets[0]
|
172
|
+
fallthrough = unused != :fallthrough
|
173
|
+
if fallthrough
|
174
|
+
dead_index = b.next[0].labels.include?(target) ? 0 : 1
|
175
|
+
else
|
176
|
+
dead_index = b.next[0].labels.include?(target) ? 1 : 0
|
177
|
+
end
|
178
|
+
dead = b.next[dead_index]
|
179
|
+
jir = b.irs.pop()
|
180
|
+
b.irs.push(JumpGuard.new(jir.cond_value, all_variable, jir.insn, self))
|
181
|
+
if !fallthrough
|
182
|
+
insn = InsnInfo.new([:jump, target], ir.insn.iseq, -1, -1)
|
183
|
+
b.irs.push(JumpIR.new(nil, insn, self))
|
184
|
+
end
|
185
|
+
b.next.delete(dead)
|
186
|
+
dead.pre.delete(b)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
change
|
191
|
+
end
|
192
|
+
|
193
|
+
def method_inlining()
|
194
|
+
@blocks.each do |b|
|
195
|
+
b.irs.each do |ir|
|
196
|
+
if ir.inlining_target?
|
197
|
+
todo()
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
false
|
202
|
+
end
|
203
|
+
|
204
|
+
def type_propergation()
|
205
|
+
change = true
|
206
|
+
while change
|
207
|
+
change = false
|
208
|
+
@blocks.each do |b|
|
209
|
+
defs = b.information.dup
|
210
|
+
b.irs.each do |ir|
|
211
|
+
change |= ir.type_propergation(defs)
|
212
|
+
bug() unless change == true || change == false
|
213
|
+
defs.step(ir)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
all_ir().each{|ir| ir.variables.each{|v| v.not_initialized() if v.undefined?}}
|
218
|
+
bug() if all_ir().find{|ir| ir.variables.find{|v| v.undefined?}}
|
219
|
+
end
|
220
|
+
|
221
|
+
def propergate_exact_class()
|
222
|
+
change = true
|
223
|
+
while change
|
224
|
+
change = false
|
225
|
+
@blocks.each do |b|
|
226
|
+
defs = b.information.dup
|
227
|
+
b.irs.each do |ir|
|
228
|
+
change |= ir.propergate_exact_class(defs)
|
229
|
+
defs.step(ir)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def propergate_guard_usage()
|
236
|
+
irs = all_ir()
|
237
|
+
irs.each{|ir| ir.propergate_guard_usage()}
|
238
|
+
end
|
239
|
+
|
240
|
+
### unboxing begin ###
|
241
|
+
def unboxing()
|
242
|
+
# 1: mark value which can not unbox
|
243
|
+
# 1: mark value which can unbox
|
244
|
+
irs = all_ir()
|
245
|
+
irs.each{|ir| ir.unboxing_prelude()}
|
246
|
+
bug() if irs.map{|ir| ir.values }.flatten.find{|v| v.box_unbox_undefined? }
|
247
|
+
|
248
|
+
# 2: propergate value which can not unbox
|
249
|
+
change = true
|
250
|
+
while change
|
251
|
+
change = false
|
252
|
+
@blocks.each do |b|
|
253
|
+
defs = b.information.dup
|
254
|
+
b.irs.each do |ir|
|
255
|
+
change |= ir.propergate_value_which_can_not_unbox(defs)
|
256
|
+
defs.step(ir)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
bug() if irs.find{|ir| ir.instance_of?(SubIR) && ir.dst.can_not_unbox? != ir.src.can_not_unbox?}
|
261
|
+
|
262
|
+
# 3: propergate value which can unbox
|
263
|
+
change = true
|
264
|
+
while change
|
265
|
+
change = false
|
266
|
+
@blocks.each do |b|
|
267
|
+
defs = b.information.dup
|
268
|
+
b.irs.each do |ir|
|
269
|
+
change |= ir.propergate_unbox_value(defs)
|
270
|
+
defs.step(ir)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
bug() if irs.map{|ir| ir.values }.flatten.find{|v| v.unboxed? && (v.dynamic? || v.types.size != 1)}
|
276
|
+
irs.each do |ir|
|
277
|
+
ir.values.each do |v|
|
278
|
+
next unless v.unboxed?
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
irs.map{|ir| ir.values}.flatten.each{|v| v.box() unless v.unboxed?}
|
283
|
+
irs.map{|ir| ir.values}.flatten.each{|v| bug() if !v.boxed? && !v.unboxed?}
|
284
|
+
change = true
|
285
|
+
while change
|
286
|
+
change = false
|
287
|
+
@blocks.each do |b|
|
288
|
+
defs = b.information.dup
|
289
|
+
b.irs.each do |ir|
|
290
|
+
change |= ir.propergate_box_value(defs)
|
291
|
+
defs.step(ir)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
@blocks.each do |b|
|
297
|
+
defs = b.information.dup
|
298
|
+
b.irs.each do |ir|
|
299
|
+
case ir
|
300
|
+
when SubIR
|
301
|
+
bug() unless ir.src.boxed? == ir.dst.boxed?
|
302
|
+
bug() unless ir.src.unboxed? == ir.dst.unboxed?
|
303
|
+
end
|
304
|
+
ir.variables_without_result.each do |v|
|
305
|
+
ds = defs.variable_definition.select {|d| v == d.result_variable }
|
306
|
+
if v.unboxed?
|
307
|
+
bug() if ds.find{|d| not d.result_variable.unboxed? }
|
308
|
+
elsif v.boxed?
|
309
|
+
bug() if ds.find{|d| d.result_variable.unboxed? }
|
310
|
+
else
|
311
|
+
bug(ir)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
defs.step(ir)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
### unboxing end ###
|
319
|
+
|
320
|
+
def reject_redundant_guards()
|
321
|
+
redundant = []
|
322
|
+
ptrs = all_pointer()
|
323
|
+
@blocks.each do |b|
|
324
|
+
safe = b.in_guards.dup()
|
325
|
+
b.irs.each do |ir|
|
326
|
+
redundant << ir if safe.redundant?(ir)
|
327
|
+
safe.step(ir)
|
328
|
+
end
|
329
|
+
safe.validate_final()
|
330
|
+
b.irs.reject!{|ir| redundant.include?(ir)}
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def reject_guards()
|
335
|
+
@blocks.each{|b| b.irs.reject!{|ir| ir.is_a?(StandardGuard)}}
|
336
|
+
end
|
337
|
+
|
338
|
+
def set_sampling()
|
339
|
+
all_ir().each do |ir|
|
340
|
+
targets = nil
|
341
|
+
case ir
|
342
|
+
when CallIR
|
343
|
+
case ir
|
344
|
+
when InvokeIR
|
345
|
+
ir.sampling_return_value()
|
346
|
+
else
|
347
|
+
# TODO
|
348
|
+
end
|
349
|
+
targets = ir.param_variables()
|
350
|
+
when JumpIR
|
351
|
+
targets = [ir.cond_value] if ir.cond_value
|
352
|
+
end
|
353
|
+
next unless targets
|
354
|
+
targets.each do |p|
|
355
|
+
next unless p.dynamic?
|
356
|
+
ir.get_definition(p).each do |d|
|
357
|
+
case d
|
358
|
+
when Literal
|
359
|
+
bug()
|
360
|
+
when Self
|
361
|
+
ir.add_sampling_variable(d)
|
362
|
+
when SubIR
|
363
|
+
d.add_sampling_variable(d.src)
|
364
|
+
#ir.add_sampling_variable(d.src)
|
365
|
+
when CallIR
|
366
|
+
# Nothing to do.
|
367
|
+
# Always sampling CallIR's return value.
|
368
|
+
else
|
369
|
+
bug()
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def attach_var_info()
|
377
|
+
set_information() # information.rb
|
378
|
+
|
379
|
+
@blocks.each do |b|
|
380
|
+
defs = b.information.dup()
|
381
|
+
b.irs.each do |ir|
|
382
|
+
ir.set_info(defs.dup())
|
383
|
+
defs.step(ir)
|
384
|
+
end
|
385
|
+
defs.validate_final()
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|