cast_off 0.2.3 → 0.3.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 +22 -47
- data/README.en +14 -36
- data/bin/{CastOff → cast_off} +53 -22
- data/cast_off.gemspec +2 -2
- data/lib/cast_off/compile/basicblock.rb +12 -0
- data/lib/cast_off/compile/cfg.rb +1 -1
- data/lib/cast_off/compile/code_manager.rb +3 -2
- data/lib/cast_off/compile/configuration.rb +43 -29
- data/lib/cast_off/compile/information.rb +363 -229
- data/lib/cast_off/compile/ir/guard_ir.rb +29 -9
- data/lib/cast_off/compile/ir/simple_ir.rb +2 -2
- data/lib/cast_off/compile/translator.rb +48 -10
- data/lib/cast_off/compile.rb +42 -17
- metadata +4 -4
@@ -6,40 +6,55 @@ module CastOff::Compiler
|
|
6
6
|
include CastOff::Util
|
7
7
|
include SimpleIR
|
8
8
|
|
9
|
-
attr_reader :
|
10
|
-
attr_reader :variable_condition
|
9
|
+
attr_reader :definition, :undefs, :block, :alias
|
11
10
|
|
12
|
-
def initialize(block, vars, a, defs, undefs, ptr_defs, ptrs)
|
11
|
+
def initialize(block, vars, a, c, defs, undefs, ptr_defs, ptrs)
|
13
12
|
@block = block
|
14
13
|
@alias = a.instance_of?(Alias) ? a : Alias.new(@block, a, vars, ptrs)
|
15
|
-
@
|
14
|
+
@condition = c
|
15
|
+
@definition = defs
|
16
16
|
@ptr_defs = ptr_defs
|
17
17
|
@undefs = undefs
|
18
18
|
@ptrs = ptrs
|
19
19
|
@vars = vars
|
20
|
-
@variable_condition = VariableCondition.new(@block, @ptrs, @alias)
|
21
20
|
check_initialize()
|
22
21
|
end
|
23
22
|
|
23
|
+
def initialize_condition()
|
24
|
+
@condition = Condition.new(@block, @ptrs, @alias)
|
25
|
+
end
|
26
|
+
|
27
|
+
def condition()
|
28
|
+
@condition
|
29
|
+
end
|
30
|
+
|
31
|
+
def condition=(cond)
|
32
|
+
bug() unless @condition
|
33
|
+
bug() unless cond.instance_of?(Condition)
|
34
|
+
@condition = cond
|
35
|
+
end
|
36
|
+
|
24
37
|
def freeze()
|
25
38
|
super()
|
26
39
|
check_initialize()
|
27
40
|
@alias.freeze()
|
28
|
-
@
|
41
|
+
@definition.freeze()
|
29
42
|
@ptr_defs.freeze()
|
30
43
|
@undefs.freeze()
|
31
44
|
@ptrs.freeze()
|
32
45
|
@vars.freeze()
|
33
|
-
@
|
46
|
+
@condition.freeze()
|
47
|
+
self
|
34
48
|
end
|
35
49
|
|
36
50
|
def final_state()
|
37
51
|
# variable_condition までは final_state にならないので注意
|
38
52
|
check_initialize()
|
39
53
|
final_alias = @alias.final_state()
|
40
|
-
|
54
|
+
final_cond = @condition ? @condition.final_state() : nil
|
55
|
+
final_defs = (@definition - @block.ekill) | @block.egen
|
41
56
|
final_undefs = @undefs + @block.ekill.map{|ir| ir.result_variable} - @block.egen.map{|ir| ir.result_variable}
|
42
|
-
Information.new(@block, @vars, final_alias, final_defs, final_undefs, @ptr_defs, @ptrs)
|
57
|
+
Information.new(@block, @vars, final_alias, final_cond, final_defs, final_undefs, @ptr_defs, @ptrs)
|
43
58
|
end
|
44
59
|
|
45
60
|
def find_same_variables(var)
|
@@ -51,7 +66,7 @@ module CastOff::Compiler
|
|
51
66
|
check_initialize()
|
52
67
|
@alias.validate()
|
53
68
|
bug() unless @alias.final_state() == @block.information.alias.final_state()
|
54
|
-
defs = @
|
69
|
+
defs = @definition.map{|d| d.result_variable}.compact()
|
55
70
|
bug() unless (defs & @undefs).empty?
|
56
71
|
bug() unless (@vars - (defs | @undefs)).empty?
|
57
72
|
end
|
@@ -60,15 +75,19 @@ module CastOff::Compiler
|
|
60
75
|
check_initialize()
|
61
76
|
@alias.validate()
|
62
77
|
bug() unless @alias == @block.information.alias.final_state()
|
63
|
-
defs = @
|
78
|
+
defs = @definition.map{|d| d.result_variable}.compact()
|
64
79
|
bug() unless (defs & @undefs).empty?
|
65
80
|
bug() unless (@vars - (defs | @undefs)).empty?
|
81
|
+
bug() unless @condition.instance_of?(Condition)
|
82
|
+
bug() unless @block.information.condition.instance_of?(Condition)
|
83
|
+
bug() unless @condition == @block.information.condition.final_state()
|
66
84
|
end
|
67
85
|
|
68
86
|
def step(ir)
|
69
87
|
check_initialize()
|
70
88
|
@alias.step(ir)
|
71
|
-
@
|
89
|
+
bug() unless @condition.instance_of?(Condition)
|
90
|
+
@condition.step(ir)
|
72
91
|
delete(ir)
|
73
92
|
add(ir)
|
74
93
|
end
|
@@ -76,13 +95,14 @@ module CastOff::Compiler
|
|
76
95
|
def |(other)
|
77
96
|
check_initialize()
|
78
97
|
bug() unless other.instance_of?(Information)
|
79
|
-
|
98
|
+
bug() if @condition
|
99
|
+
Information.new(@block, @vars, @alias.union(other.alias), nil, @definition | other.definition, @undefs | other.undefs, @ptr_defs, @ptrs)
|
80
100
|
end
|
81
101
|
|
82
102
|
def kill_definition(other)
|
83
|
-
@
|
103
|
+
@definition.delete_if do |d0|
|
84
104
|
next unless d0.result_variable
|
85
|
-
not other.
|
105
|
+
not other.definition.find{|d1| d0.result_variable == d1.result_variable}
|
86
106
|
end
|
87
107
|
end
|
88
108
|
|
@@ -90,8 +110,9 @@ module CastOff::Compiler
|
|
90
110
|
check_initialize()
|
91
111
|
bug() unless other.instance_of?(Information)
|
92
112
|
bug() unless @block == other.block
|
93
|
-
return false unless (@
|
113
|
+
return false unless (@definition - other.definition).empty? && (other.definition - @definition).empty?
|
94
114
|
return false unless (@undefs - other.undefs).empty? && (other.undefs - @undefs).empty?
|
115
|
+
return false unless @condition == other.condition
|
95
116
|
@alias == other.alias
|
96
117
|
end
|
97
118
|
|
@@ -102,23 +123,23 @@ module CastOff::Compiler
|
|
102
123
|
|
103
124
|
def size()
|
104
125
|
check_initialize()
|
105
|
-
@
|
126
|
+
@definition.size()
|
106
127
|
end
|
107
128
|
|
108
129
|
def replace_entry(ir)
|
109
130
|
check_initialize()
|
110
|
-
i = @
|
111
|
-
@
|
131
|
+
i = @definition.index(ir)
|
132
|
+
@definition[i] = ir if i
|
112
133
|
end
|
113
134
|
|
114
135
|
def reject!(&b)
|
115
136
|
check_initialize()
|
116
|
-
@
|
137
|
+
@definition.reject!{|ir| yield ir}
|
117
138
|
end
|
118
139
|
|
119
140
|
def flatten!
|
120
141
|
check_initialize()
|
121
|
-
@
|
142
|
+
@definition.flatten!
|
122
143
|
end
|
123
144
|
|
124
145
|
def hash()
|
@@ -127,16 +148,16 @@ module CastOff::Compiler
|
|
127
148
|
|
128
149
|
def dup()
|
129
150
|
check_initialize()
|
130
|
-
Information.new(@block, @vars, @alias.dup(), @
|
151
|
+
Information.new(@block, @vars, @alias.dup(), @condition ? @condition.dup() : nil, @definition.dup(), @undefs.dup(), @ptr_defs, @ptrs)
|
131
152
|
end
|
132
153
|
|
133
154
|
def to_s()
|
134
|
-
@
|
155
|
+
@definition.join("\n")
|
135
156
|
end
|
136
157
|
|
137
|
-
def
|
158
|
+
def definition_of(var)
|
138
159
|
check_initialize()
|
139
|
-
@
|
160
|
+
@definition.select{|d| d.result_variable == var}
|
140
161
|
end
|
141
162
|
|
142
163
|
def undefined_variables()
|
@@ -146,7 +167,7 @@ module CastOff::Compiler
|
|
146
167
|
|
147
168
|
def mark(var)
|
148
169
|
check_initialize()
|
149
|
-
ds = @
|
170
|
+
ds = @definition.select {|d| var == d.result_variable }
|
150
171
|
ds.inject(false){|change, d| d.alive() || change}
|
151
172
|
end
|
152
173
|
|
@@ -156,9 +177,9 @@ module CastOff::Compiler
|
|
156
177
|
return false unless var.is_a?(Variable)
|
157
178
|
ret = false
|
158
179
|
|
159
|
-
bug() unless @
|
160
|
-
ret |= @
|
161
|
-
ds = @
|
180
|
+
bug() unless @condition
|
181
|
+
ret |= @condition.use(var)
|
182
|
+
ds = @definition.select {|d| var == d.result_variable }
|
162
183
|
if @undefs.include?(var) || ds.empty?
|
163
184
|
case var
|
164
185
|
when TmpBuffer
|
@@ -180,7 +201,7 @@ module CastOff::Compiler
|
|
180
201
|
check_initialize()
|
181
202
|
return false if !var.is_a?(Variable) || var.class_exact?
|
182
203
|
|
183
|
-
ds = @
|
204
|
+
ds = @definition.select{|d| var == d.result_variable }
|
184
205
|
if @undefs.include?(var) || ds.empty?
|
185
206
|
case var
|
186
207
|
when TmpBuffer, Pointer, Argument, Self
|
@@ -203,7 +224,7 @@ module CastOff::Compiler
|
|
203
224
|
def can_not_unbox_variable_resolve_forward(var)
|
204
225
|
check_initialize()
|
205
226
|
return false if var.can_not_unbox?
|
206
|
-
ds = @
|
227
|
+
ds = @definition.select {|d| var == d.result_variable }
|
207
228
|
if ds.empty?
|
208
229
|
case var
|
209
230
|
when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
|
@@ -224,7 +245,7 @@ module CastOff::Compiler
|
|
224
245
|
def can_not_unbox_variable_resolve_backward(var)
|
225
246
|
check_initialize()
|
226
247
|
bug() unless var.can_not_unbox?
|
227
|
-
ds = @
|
248
|
+
ds = @definition.select {|d| var == d.result_variable }
|
228
249
|
if ds.empty?
|
229
250
|
case var
|
230
251
|
when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
|
@@ -240,7 +261,7 @@ module CastOff::Compiler
|
|
240
261
|
check_initialize()
|
241
262
|
bug() if !var.unboxed? && !var.boxed?
|
242
263
|
return false if var.boxed?
|
243
|
-
ds = @
|
264
|
+
ds = @definition.select {|d| var == d.result_variable }
|
244
265
|
if ds.empty?
|
245
266
|
case var
|
246
267
|
when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
|
@@ -262,7 +283,7 @@ module CastOff::Compiler
|
|
262
283
|
def box_value_resolve_backward(var)
|
263
284
|
check_initialize()
|
264
285
|
bug() unless var.boxed?
|
265
|
-
ds = @
|
286
|
+
ds = @definition.select {|d| var == d.result_variable }
|
266
287
|
if ds.empty?
|
267
288
|
case var
|
268
289
|
when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
|
@@ -278,7 +299,7 @@ module CastOff::Compiler
|
|
278
299
|
check_initialize()
|
279
300
|
bug() if var.can_not_unbox?
|
280
301
|
return false if var.unboxed?
|
281
|
-
ds = @
|
302
|
+
ds = @definition.select {|d| var == d.result_variable }
|
282
303
|
if ds.empty?
|
283
304
|
case var
|
284
305
|
when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
|
@@ -308,239 +329,331 @@ module CastOff::Compiler
|
|
308
329
|
|
309
330
|
def check_initialize()
|
310
331
|
bug() unless @block.instance_of?(BasicBlock)
|
311
|
-
bug() unless @
|
332
|
+
bug() unless @definition.instance_of?(Array)
|
312
333
|
bug() unless @ptr_defs.instance_of?(Array)
|
313
334
|
bug() unless @undefs.instance_of?(Array)
|
314
335
|
bug() unless @ptrs.instance_of?(Array)
|
315
336
|
bug() unless @vars.instance_of?(Array)
|
316
337
|
bug() unless @alias.instance_of?(Alias)
|
317
|
-
bug() unless @
|
338
|
+
bug() unless @condition.nil? || @condition.instance_of?(Condition)
|
318
339
|
end
|
319
340
|
|
320
341
|
def delete(ir)
|
321
342
|
check_initialize()
|
322
|
-
@
|
343
|
+
@definition.reject!{|d| d.result_variable == ir.result_variable}
|
323
344
|
if ir.dispatch_method?
|
324
|
-
@
|
345
|
+
@definition -= @ptr_defs
|
325
346
|
@undefs |= @ptrs
|
326
347
|
end
|
327
348
|
end
|
328
349
|
|
329
350
|
def add(ir)
|
330
351
|
check_initialize()
|
331
|
-
@
|
352
|
+
@definition << ir
|
332
353
|
result_variable = ir.result_variable
|
333
354
|
@undefs -= [result_variable] if result_variable
|
334
355
|
end
|
356
|
+
end # Information
|
335
357
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
attr_reader :set
|
340
|
-
|
341
|
-
def initialize(b, a, all, ptrs)
|
342
|
-
bug() unless b.instance_of?(BasicBlock)
|
343
|
-
@block = b
|
344
|
-
@all = all
|
345
|
-
@ptrs = ptrs
|
346
|
-
case a
|
347
|
-
when NilClass
|
348
|
-
a = all.dup()
|
349
|
-
bug() if a.find{|v| not v.is_a?(Variable)}
|
350
|
-
@set = [a]
|
351
|
-
when Array
|
352
|
-
bug() if a.find{|v| not v.is_a?(Variable)}
|
353
|
-
@set = a.map{|v| [v]}
|
354
|
-
when Alias
|
355
|
-
@set = a.set.map{|s| s.dup()}
|
356
|
-
else
|
357
|
-
bug()
|
358
|
-
end
|
359
|
-
validate()
|
360
|
-
end
|
361
|
-
|
362
|
-
def freeze()
|
363
|
-
super()
|
364
|
-
@all.freeze()
|
365
|
-
@set.freeze()
|
366
|
-
@ptrs.freeze()
|
367
|
-
end
|
358
|
+
class Condition
|
359
|
+
include CastOff::Util
|
360
|
+
include SimpleIR
|
368
361
|
|
369
|
-
|
370
|
-
a = dup()
|
371
|
-
@block.irs.each{|ir| a.step(ir)}
|
372
|
-
a
|
373
|
-
end
|
362
|
+
attr_reader :block, :condition, :temporary_condition
|
374
363
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
364
|
+
def initialize(b, ptrs, a_or_c, tmp = nil)
|
365
|
+
# 管理が煩雑になるので、alias を内部で保持しないこと。
|
366
|
+
# step 時に alias まで進めないと、final_state で古い alias を持つことになる。
|
367
|
+
@block = b
|
368
|
+
@ptrs = ptrs
|
369
|
+
@temporary_condition = tmp
|
370
|
+
case a_or_c
|
371
|
+
when Alias
|
372
|
+
@condition = initialize_condition_from_block(a_or_c)
|
373
|
+
when Hash
|
374
|
+
# @condition は呼び出し元で dup している
|
375
|
+
@condition = a_or_c
|
376
|
+
bug() if @condition.keys.find{|v| !v.is_a?(Variable)}
|
377
|
+
bug() if @condition.values.find{|p| !p.is_a?(Proc)}
|
378
|
+
else
|
379
|
+
bug()
|
387
380
|
end
|
381
|
+
end
|
388
382
|
|
389
|
-
|
390
|
-
|
391
|
-
|
383
|
+
def use(v)
|
384
|
+
promote_temporary_condition()
|
385
|
+
bug() if @temporary_condition
|
386
|
+
p = @condition[v]
|
387
|
+
p ? p.call(v) : false
|
388
|
+
end
|
392
389
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
390
|
+
def step(ir)
|
391
|
+
promote_temporary_condition()
|
392
|
+
bug() if @temporary_condition
|
393
|
+
unless ir.result_variable
|
394
|
+
bug() if ir.dispatch_method?
|
395
|
+
return
|
397
396
|
end
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
397
|
+
case ir
|
398
|
+
when SubIR
|
399
|
+
src = ir.src
|
400
|
+
dst = ir.dst
|
401
|
+
if @condition[src]
|
402
|
+
@condition[dst] = @condition[src]
|
403
|
+
else
|
404
|
+
@condition.delete(dst)
|
403
405
|
end
|
404
|
-
|
405
|
-
|
406
|
+
when CallIR
|
407
|
+
return_value = ir.return_value
|
408
|
+
bug() unless return_value.is_a?(Variable)
|
409
|
+
@condition.delete(return_value)
|
410
|
+
@ptrs.each{|p| @condition.delete(p)} if ir.dispatch_method?
|
406
411
|
end
|
412
|
+
end
|
407
413
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
end
|
414
|
+
def dup()
|
415
|
+
# condition は呼び出し元で dup する
|
416
|
+
tmp = @temporary_condition ? @temporary_condition.dup() : nil
|
417
|
+
Condition.new(@block, @ptrs, @condition.dup, tmp)
|
418
|
+
end
|
414
419
|
|
415
|
-
|
416
|
-
|
417
|
-
|
420
|
+
def final_state
|
421
|
+
v = dup()
|
422
|
+
@block.irs.each{|ir| v.step(ir)}
|
423
|
+
v
|
424
|
+
end
|
418
425
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
s = s0 & s1
|
427
|
-
new_set << s
|
428
|
-
a -= s
|
426
|
+
def union(other)
|
427
|
+
bug() unless @block.pre.include?(other.block)
|
428
|
+
bug() unless other.instance_of?(Condition)
|
429
|
+
if @temporary_condition
|
430
|
+
tmp = @temporary_condition.dup
|
431
|
+
other.condition.each do |(v, p)|
|
432
|
+
tmp.delete(v) if !tmp[v] || (tmp[v] && tmp[v] != p)
|
429
433
|
end
|
430
|
-
|
431
|
-
|
432
|
-
dup()
|
434
|
+
else
|
435
|
+
tmp = other.condition.dup
|
433
436
|
end
|
437
|
+
# condition は呼び出し元で dup する
|
438
|
+
Condition.new(@block, @ptrs, @condition.dup, tmp)
|
439
|
+
end
|
434
440
|
|
435
|
-
|
441
|
+
def eql?(other)
|
442
|
+
return false unless @block == other.block
|
443
|
+
return false unless @temporary_condition == other.temporary_condition
|
444
|
+
@condition == other.condition
|
445
|
+
end
|
436
446
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
s = find_set(arg0)
|
441
|
-
bug() if s.include?(result)
|
442
|
-
s << result
|
443
|
-
end
|
447
|
+
def ==(other)
|
448
|
+
eql?(other)
|
449
|
+
end
|
444
450
|
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
end
|
451
|
+
def hash
|
452
|
+
bug()
|
453
|
+
end
|
449
454
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
end
|
455
|
+
def freeze()
|
456
|
+
super()
|
457
|
+
@ptrs.freeze()
|
458
|
+
@condition.freeze()
|
459
|
+
self
|
460
|
+
end
|
456
461
|
|
457
|
-
|
458
|
-
|
459
|
-
|
462
|
+
def to_s
|
463
|
+
@condition.inject(''){|str, (v, p)|
|
464
|
+
str.concat("#{v} => #{p}\n")
|
465
|
+
}.chomp
|
466
|
+
end
|
460
467
|
|
461
|
-
|
468
|
+
private
|
462
469
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
470
|
+
NilWrapper = ClassWrapper.new(NilClass, true)
|
471
|
+
FalseWrapper = ClassWrapper.new(FalseClass, true)
|
472
|
+
CondNotNilNotFalse = proc{|v| v.is_not([NilWrapper, FalseWrapper])}
|
473
|
+
CondNilOrFalse = proc{|v| v.is_negative_cond_value; v.is_static([NilWrapper, FalseWrapper])}
|
474
|
+
CondNotNilNotFalse.instance_eval do
|
475
|
+
def to_s
|
476
|
+
"neither nil nor false"
|
467
477
|
end
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
478
|
+
end
|
479
|
+
CondNilOrFalse.instance_eval do
|
480
|
+
def to_s
|
481
|
+
"nil or false"
|
472
482
|
end
|
483
|
+
end
|
484
|
+
def initialize_condition_from_block(a)
|
485
|
+
cond = {}
|
486
|
+
bug() unless a.instance_of?(Alias)
|
487
|
+
return cond unless @block.pre.size == 1
|
488
|
+
b = @block.pre[0]
|
489
|
+
ir = b.irs.last
|
490
|
+
return cond unless ir.is_a?(JumpIR)
|
491
|
+
fallthrough = (ir.jump_targets & @block.labels).empty?
|
492
|
+
p = nil
|
493
|
+
case ir.jump_type
|
494
|
+
when :branchif
|
495
|
+
p = fallthrough ? CondNilOrFalse : CondNotNilNotFalse
|
496
|
+
when :branchunless
|
497
|
+
p = fallthrough ? CondNotNilNotFalse : CondNilOrFalse
|
498
|
+
end
|
499
|
+
if p
|
500
|
+
set = a.find_set(ir.cond_value)
|
501
|
+
bug() if set.empty?
|
502
|
+
set.each{|s| cond[s] = p}
|
503
|
+
end
|
504
|
+
cond
|
505
|
+
end
|
473
506
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
@condition
|
480
|
-
@
|
507
|
+
def promote_temporary_condition()
|
508
|
+
return unless @temporary_condition
|
509
|
+
bug() unless @temporary_condition.instance_of?(Hash)
|
510
|
+
@temporary_condition.each do |(v, p)|
|
511
|
+
bug() unless v.is_a?(Variable)
|
512
|
+
bug() if @condition[v] && @condition[v] != p
|
513
|
+
@condition[v] = p
|
481
514
|
end
|
515
|
+
@temporary_condition = nil
|
516
|
+
end
|
517
|
+
end #Condition
|
482
518
|
|
483
|
-
|
484
|
-
|
519
|
+
def calc_egen_ekill
|
520
|
+
all = all_ir()
|
521
|
+
@blocks.each { |b| b.calc_egen() }
|
522
|
+
@blocks.each { |b| b.calc_ekill(all) }
|
523
|
+
end
|
524
|
+
|
525
|
+
class Alias
|
526
|
+
include CastOff::Compiler::SimpleIR
|
527
|
+
include CastOff::Util
|
528
|
+
attr_reader :set
|
529
|
+
|
530
|
+
def initialize(b, a, all, ptrs)
|
531
|
+
bug() unless b.instance_of?(BasicBlock)
|
532
|
+
@block = b
|
533
|
+
@all = all
|
534
|
+
@ptrs = ptrs
|
535
|
+
case a
|
536
|
+
when NilClass
|
537
|
+
a = all.dup()
|
538
|
+
bug() if a.find{|v| not v.is_a?(Variable)}
|
539
|
+
@set = [a]
|
540
|
+
when Array
|
541
|
+
bug() if a.find{|v| not v.is_a?(Variable)}
|
542
|
+
@set = a.map{|v| [v]}
|
543
|
+
when Alias
|
544
|
+
@set = a.set.map{|s| s.dup()}
|
545
|
+
else
|
485
546
|
bug()
|
486
547
|
end
|
548
|
+
validate()
|
549
|
+
end
|
550
|
+
|
551
|
+
def freeze()
|
552
|
+
super()
|
553
|
+
@all.freeze()
|
554
|
+
@set.freeze()
|
555
|
+
@ptrs.freeze()
|
556
|
+
self
|
557
|
+
end
|
487
558
|
|
488
|
-
|
489
|
-
|
559
|
+
def final_state()
|
560
|
+
a = dup()
|
561
|
+
@block.irs.each{|ir| a.step(ir)}
|
562
|
+
a
|
563
|
+
end
|
564
|
+
|
565
|
+
def step(ir)
|
566
|
+
case ir
|
567
|
+
when SubIR
|
568
|
+
src = ir.src
|
569
|
+
dst = ir.dst
|
570
|
+
src.is_a?(Variable) ? sub(src, dst) : isolate(dst)
|
571
|
+
when CallIR
|
572
|
+
return_value = ir.return_value
|
573
|
+
bug() unless return_value.is_a?(Variable)
|
574
|
+
isolate(return_value)
|
575
|
+
@ptrs.each{|p| isolate(p)} if ir.dispatch_method?
|
490
576
|
end
|
577
|
+
end
|
491
578
|
|
492
|
-
|
493
|
-
|
579
|
+
def dup()
|
580
|
+
Alias.new(@block, self, @all, @ptrs)
|
581
|
+
end
|
582
|
+
|
583
|
+
def find_set(var)
|
584
|
+
bug() unless var.is_a?(Variable)
|
585
|
+
set.each{|s| return s if s.include?(var)}
|
586
|
+
bug("set = #{set}, var = #{var}, #{var.class}")
|
587
|
+
end
|
588
|
+
|
589
|
+
def validate()
|
590
|
+
a = @set.inject([]) do |ary, s|
|
591
|
+
bug() unless (ary & s).empty?
|
592
|
+
ary + s
|
494
593
|
end
|
594
|
+
size = @all.size()
|
595
|
+
bug() unless a.size() == size && (a & @all).size() == size
|
596
|
+
end
|
495
597
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
if fallthrough
|
518
|
-
p = proc{|v| v.is_negative_cond_value; v.is_static([NilWrapper, FalseWrapper])}
|
519
|
-
else
|
520
|
-
p = proc{|v| v.is_not([NilWrapper, FalseWrapper])}
|
521
|
-
end
|
522
|
-
when :branchunless
|
523
|
-
if fallthrough
|
524
|
-
p = proc{|v| v.is_not([NilWrapper, FalseWrapper])}
|
525
|
-
else
|
526
|
-
p = proc{|v| v.is_negative_cond_value; v.is_static([NilWrapper, FalseWrapper])}
|
527
|
-
end
|
528
|
-
end
|
529
|
-
if p
|
530
|
-
set = a.find_set(ir.cond_value)
|
531
|
-
bug() if set.empty?
|
532
|
-
set.each{|s| cond[s] = p}
|
533
|
-
end
|
534
|
-
cond
|
598
|
+
def eql?(other)
|
599
|
+
other_set = other.set.dup()
|
600
|
+
@set.each{|s| other_set.delete(s){return false}}
|
601
|
+
bug() unless other_set.empty?
|
602
|
+
return true
|
603
|
+
end
|
604
|
+
|
605
|
+
def ==(other)
|
606
|
+
eql?(other)
|
607
|
+
end
|
608
|
+
|
609
|
+
def __union(other)
|
610
|
+
a = @all.dup()
|
611
|
+
new_set = []
|
612
|
+
until a.empty?
|
613
|
+
var = a.pop()
|
614
|
+
s0 = find_set(var)
|
615
|
+
s1 = other.find_set(var)
|
616
|
+
s = s0 & s1
|
617
|
+
new_set << s
|
618
|
+
a -= s
|
535
619
|
end
|
536
|
-
|
537
|
-
|
620
|
+
@set = new_set
|
621
|
+
validate()
|
622
|
+
end
|
538
623
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
624
|
+
def union(other)
|
625
|
+
a = dup()
|
626
|
+
a.__union(other)
|
627
|
+
a
|
628
|
+
end
|
629
|
+
|
630
|
+
def to_s
|
631
|
+
@set.inject(''){|str, s|
|
632
|
+
str.concat(s.map{|v| v.to_debug_string}.join(", ")).concat("\n")
|
633
|
+
}.chomp
|
634
|
+
end
|
635
|
+
|
636
|
+
private
|
637
|
+
|
638
|
+
def sub(arg0, result)
|
639
|
+
return if arg0 == result
|
640
|
+
reject(result)
|
641
|
+
s = find_set(arg0)
|
642
|
+
bug() if s.include?(result)
|
643
|
+
s << result
|
644
|
+
end
|
645
|
+
|
646
|
+
def isolate(var)
|
647
|
+
reject(var)
|
648
|
+
@set << [var]
|
649
|
+
end
|
650
|
+
|
651
|
+
def reject(var)
|
652
|
+
s = find_set(var)
|
653
|
+
s.delete(var){bug()}
|
654
|
+
@set.delete(s){bug()} if s.empty?
|
655
|
+
end
|
656
|
+
end # Alias
|
544
657
|
|
545
658
|
class BasicBlock
|
546
659
|
attr_reader :egen, :ekill
|
@@ -612,6 +725,25 @@ module CastOff::Compiler
|
|
612
725
|
end
|
613
726
|
end
|
614
727
|
|
728
|
+
def set_condition
|
729
|
+
@blocks.each{|b| b.information.initialize_condition()}
|
730
|
+
change = true
|
731
|
+
entry = @blocks.first
|
732
|
+
while change
|
733
|
+
change = false
|
734
|
+
@blocks.each do |b0|
|
735
|
+
next if b0 == entry
|
736
|
+
info = b0.information
|
737
|
+
cond = b0.pre.inject(info.condition.dup) do |c, b1|
|
738
|
+
next c if b0 == b1
|
739
|
+
c.union(b1.information.condition.final_state)
|
740
|
+
end
|
741
|
+
change = true if info.condition != cond
|
742
|
+
info.condition = cond
|
743
|
+
end
|
744
|
+
end
|
745
|
+
end
|
746
|
+
|
615
747
|
def set_information
|
616
748
|
ptr_defs = all_pointer_definition()
|
617
749
|
ptrs = all_pointer()
|
@@ -622,14 +754,14 @@ module CastOff::Compiler
|
|
622
754
|
bug() if @blocks.find{|b| (not b.in_undefined) || (not b.out_undefined)}
|
623
755
|
bug() if @blocks.find{|b| b != entry && b.pre.empty? }
|
624
756
|
bug() unless entry.pre.empty?
|
625
|
-
@blocks.each{|b| b.information = Information.new(b, vars, vars, [], [], ptr_defs, ptrs)}
|
626
|
-
entry.information = Information.new(entry, vars, vars, [], vars, ptr_defs, ptrs)
|
757
|
+
@blocks.each{|b| b.information = Information.new(b, vars, vars, nil, [], [], ptr_defs, ptrs)}
|
758
|
+
entry.information = Information.new(entry, vars, vars, nil, [], vars, ptr_defs, ptrs)
|
627
759
|
change = true
|
628
760
|
while change
|
629
761
|
change = false
|
630
762
|
@blocks.each do |b0|
|
631
763
|
next if b0 == entry
|
632
|
-
info = b0.pre.inject(Information.new(b0, vars, nil, [], [], ptr_defs, ptrs)) {|info, b1| info | b1.information.final_state()}
|
764
|
+
info = b0.pre.inject(Information.new(b0, vars, nil, nil, [], [], ptr_defs, ptrs)) {|info, b1| info | b1.information.final_state()}
|
633
765
|
change = true if b0.information != info
|
634
766
|
b0.information = info
|
635
767
|
end
|
@@ -645,18 +777,19 @@ module CastOff::Compiler
|
|
645
777
|
b0.information = info
|
646
778
|
end
|
647
779
|
end
|
780
|
+
set_condition()
|
648
781
|
@blocks.each{|b| b.information.freeze()}
|
649
782
|
# validation
|
650
783
|
@blocks.each do |b|
|
651
|
-
|
652
|
-
|
784
|
+
definition = b.information.dup()
|
785
|
+
definition.validate()
|
653
786
|
b.irs.each do |ir|
|
654
787
|
ir.variables_without_result.each do |var|
|
655
|
-
var.has_undefined_path() if
|
788
|
+
var.has_undefined_path() if definition.undefined_variables.include?(var)
|
656
789
|
end
|
657
|
-
|
790
|
+
definition.step(ir)
|
658
791
|
end
|
659
|
-
|
792
|
+
definition.validate_final()
|
660
793
|
end
|
661
794
|
@blocks.each do |b|
|
662
795
|
u0 = b.in_undefined
|
@@ -676,18 +809,18 @@ module CastOff::Compiler
|
|
676
809
|
|
677
810
|
def initialize(b, d, g, ptrs)
|
678
811
|
@block = b
|
679
|
-
@
|
812
|
+
@definition = d
|
680
813
|
@guards = g
|
681
814
|
@ptrs = ptrs
|
682
815
|
end
|
683
816
|
|
684
817
|
def dup()
|
685
|
-
Guards.new(@block, @
|
818
|
+
Guards.new(@block, @definition.dup(), @guards.dup(), @ptrs)
|
686
819
|
end
|
687
820
|
|
688
821
|
def &(other)
|
689
822
|
bug() unless other.instance_of?(Guards)
|
690
|
-
Guards.new(@block, @
|
823
|
+
Guards.new(@block, @definition.dup(), @guards & other.guards, @ptrs)
|
691
824
|
end
|
692
825
|
|
693
826
|
def eql?(other)
|
@@ -707,7 +840,7 @@ module CastOff::Compiler
|
|
707
840
|
end
|
708
841
|
|
709
842
|
def validate_final()
|
710
|
-
@
|
843
|
+
@definition.validate_final()
|
711
844
|
end
|
712
845
|
|
713
846
|
def redundant?(ir)
|
@@ -720,7 +853,7 @@ module CastOff::Compiler
|
|
720
853
|
guard_value = ir.guard_value
|
721
854
|
bug() unless guard_value.is_a?(Variable)
|
722
855
|
@guards | [guard_value]
|
723
|
-
@guards |= @
|
856
|
+
@guards |= @definition.find_same_variables(guard_value)
|
724
857
|
when SubIR
|
725
858
|
src = ir.src
|
726
859
|
dst = ir.dst
|
@@ -733,13 +866,14 @@ module CastOff::Compiler
|
|
733
866
|
@guards -= [ir.return_value]
|
734
867
|
@guards -= @ptrs if ir.dispatch_method?
|
735
868
|
end
|
736
|
-
@
|
869
|
+
@definition.step(ir)
|
737
870
|
end
|
738
871
|
|
739
872
|
def freeze()
|
740
873
|
super()
|
741
874
|
@guards.freeze()
|
742
|
-
@
|
875
|
+
@definition.freeze()
|
876
|
+
self
|
743
877
|
end
|
744
878
|
|
745
879
|
def to_s()
|