furnace-avm2 0.0.9 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +4 -3
- data/LICENSE +20 -0
- data/bin/furnace-avm2 +36 -6
- data/bin/furnace-avm2-decompiler +141 -0
- data/furnace-avm2.gemspec +2 -2
- data/lib/furnace-avm2.rb +1 -0
- data/lib/furnace-avm2/abc.rb +24 -7
- data/lib/furnace-avm2/abc/metadata/{option_detail.rb → default_value.rb} +5 -1
- data/lib/furnace-avm2/abc/metadata/initializer_body.rb +8 -0
- data/lib/furnace-avm2/abc/metadata/instance_info.rb +19 -4
- data/lib/furnace-avm2/abc/metadata/klass_info.rb +1 -4
- data/lib/furnace-avm2/abc/metadata/method_body_info.rb +27 -10
- data/lib/furnace-avm2/abc/metadata/method_info.rb +20 -13
- data/lib/furnace-avm2/abc/metadata/multiname_info.rb +6 -0
- data/lib/furnace-avm2/abc/metadata/multiname_kind_genericname.rb +8 -5
- data/lib/furnace-avm2/abc/metadata/multiname_kind_multiname.rb +4 -0
- data/lib/furnace-avm2/abc/metadata/multiname_kind_qname.rb +5 -1
- data/lib/furnace-avm2/abc/metadata/record_with_value.rb +90 -0
- data/lib/furnace-avm2/abc/metadata/script_info.rb +25 -1
- data/lib/furnace-avm2/abc/metadata/trait_class.rb +7 -3
- data/lib/furnace-avm2/abc/metadata/trait_info.rb +8 -4
- data/lib/furnace-avm2/abc/metadata/trait_method.rb +4 -0
- data/lib/furnace-avm2/abc/metadata/trait_slot.rb +5 -51
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_lshift.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_rshift.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_urshift.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/debug/as3_debug.rb +15 -0
- data/lib/furnace-avm2/abc/opcodes/debug/as3_debugfile.rb +12 -0
- data/lib/furnace-avm2/abc/opcodes/debug/as3_debugline.rb +12 -0
- data/lib/furnace-avm2/abc/opcodes/function_invocation/as3_callproplex.rb +21 -0
- data/lib/furnace-avm2/abc/opcodes/push_literal/as3_pushbyte.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/push_literal/as3_pushshort.rb +1 -1
- data/lib/furnace-avm2/binary/record.rb +21 -1
- data/lib/furnace-avm2/source/declaration_tokens/argument_declaration_token.rb +4 -0
- data/lib/furnace-avm2/source/declaration_tokens/arguments_token.rb +15 -0
- data/lib/furnace-avm2/source/declaration_tokens/callee_token.rb +72 -0
- data/lib/furnace-avm2/source/declaration_tokens/class_implementations_token.rb +21 -0
- data/lib/furnace-avm2/source/declaration_tokens/class_inheritance_token.rb +17 -0
- data/lib/furnace-avm2/source/declaration_tokens/class_name_token.rb +21 -0
- data/lib/furnace-avm2/source/declaration_tokens/class_specifiers_token.rb +12 -0
- data/lib/furnace-avm2/source/declaration_tokens/class_token.rb +21 -0
- data/lib/furnace-avm2/source/declaration_tokens/comment_token.rb +22 -0
- data/lib/furnace-avm2/source/declaration_tokens/constructor_specifiers_token.rb +12 -0
- data/lib/furnace-avm2/source/declaration_tokens/constructor_token.rb +15 -0
- data/lib/furnace-avm2/source/declaration_tokens/function_name_token.rb +14 -0
- data/lib/furnace-avm2/source/declaration_tokens/import_token.rb +17 -0
- data/lib/furnace-avm2/source/declaration_tokens/initialization_token.rb +7 -0
- data/lib/furnace-avm2/source/declaration_tokens/method_specifiers_token.rb +13 -0
- data/lib/furnace-avm2/source/declaration_tokens/method_token.rb +15 -0
- data/lib/furnace-avm2/source/declaration_tokens/multiname_token.rb +41 -0
- data/lib/furnace-avm2/source/declaration_tokens/namespace_name_token.rb +16 -0
- data/lib/furnace-avm2/source/declaration_tokens/package_name_token.rb +17 -0
- data/lib/furnace-avm2/source/declaration_tokens/package_token.rb +29 -0
- data/lib/furnace-avm2/source/declaration_tokens/rest_argument_token.rb +12 -0
- data/lib/furnace-avm2/source/declaration_tokens/scope_token.rb +23 -0
- data/lib/furnace-avm2/source/declaration_tokens/script_token.rb +14 -0
- data/lib/furnace-avm2/source/declaration_tokens/slot_name_token.rb +17 -0
- data/lib/furnace-avm2/source/declaration_tokens/slot_token.rb +23 -0
- data/lib/furnace-avm2/source/declaration_tokens/specifiers_token.rb +32 -0
- data/lib/furnace-avm2/source/declaration_tokens/token_with_traits.rb +51 -0
- data/lib/furnace-avm2/source/declaration_tokens/type_token.rb +7 -0
- data/lib/furnace-avm2/source/decompiler.rb +669 -0
- data/lib/furnace-avm2/source/implementation_tokens/access_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/array_token.rb +17 -0
- data/lib/furnace-avm2/source/implementation_tokens/as_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/assignment_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/binary_operator_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/break_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/call_token.rb +5 -0
- data/lib/furnace-avm2/source/implementation_tokens/continue_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/control_flow_token.rb +26 -0
- data/lib/furnace-avm2/source/implementation_tokens/control_transfer_token.rb +20 -0
- data/lib/furnace-avm2/source/implementation_tokens/delete_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/do_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/else_if_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/else_token.rb +22 -0
- data/lib/furnace-avm2/source/implementation_tokens/for_each_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/for_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/generic_specializers_token.rb +17 -0
- data/lib/furnace-avm2/source/implementation_tokens/generic_type_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/if_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/immediate_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/immediate_typename_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/in_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/index_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/is_complex.rb +7 -0
- data/lib/furnace-avm2/source/implementation_tokens/is_simple.rb +7 -0
- data/lib/furnace-avm2/source/implementation_tokens/is_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/label_declaration_token.rb +12 -0
- data/lib/furnace-avm2/source/implementation_tokens/label_token.rb +12 -0
- data/lib/furnace-avm2/source/implementation_tokens/local_variable_token.rb +7 -0
- data/lib/furnace-avm2/source/implementation_tokens/new_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/object_pair_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/object_token.rb +17 -0
- data/lib/furnace-avm2/source/implementation_tokens/parentheses_token.rb +11 -0
- data/lib/furnace-avm2/source/implementation_tokens/property_name_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/return_token.rb +16 -0
- data/lib/furnace-avm2/source/implementation_tokens/rtname_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/statement_token.rb +8 -0
- data/lib/furnace-avm2/source/implementation_tokens/super_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/switch_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/ternary_operator_token.rb +13 -0
- data/lib/furnace-avm2/source/implementation_tokens/throw_token.rb +12 -0
- data/lib/furnace-avm2/source/implementation_tokens/typeof_token.rb +13 -0
- data/lib/furnace-avm2/source/implementation_tokens/unary_operator_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/unary_post_operator_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/variable_name_token.rb +14 -0
- data/lib/furnace-avm2/source/implementation_tokens/while_token.rb +9 -0
- data/lib/furnace-avm2/transform.rb +5 -1
- data/lib/furnace-avm2/transform/ast_build.rb +22 -7
- data/lib/furnace-avm2/transform/ast_normalize.rb +61 -20
- data/lib/furnace-avm2/transform/cfg_build.rb +86 -0
- data/lib/furnace-avm2/transform/cfg_reduce.rb +249 -0
- data/lib/furnace-avm2/transform/nf_normalize.rb +130 -0
- data/lib/furnace-avm2/version.rb +4 -2
- data/test/basic.as +239 -0
- metadata +110 -38
- data/lib/furnace-avm2/abc/metadata/option_info.rb +0 -5
- data/test/exception.as +0 -29
- data/test/literal.as +0 -5
- data/test/logic.as +0 -23
- data/test/loops.as +0 -30
- data/test/number.as +0 -14
- data/test/switch.as +0 -38
- data/test/ternary.as +0 -22
@@ -0,0 +1,13 @@
|
|
1
|
+
module Furnace::AVM2::Tokens
|
2
|
+
class TernaryOperatorToken < Furnace::Code::NonterminalToken
|
3
|
+
include IsComplex
|
4
|
+
|
5
|
+
def to_text
|
6
|
+
"#{@children[0].to_text} ? #{@children[1].to_text} : #{@children[2].to_text}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_structure
|
10
|
+
structurize "... ? ... : ..."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Furnace::AVM2::Tokens
|
2
|
+
class UnaryOperatorToken < Furnace::Code::SurroundedToken
|
3
|
+
include IsSimple
|
4
|
+
|
5
|
+
def initialize(origin, children, operator, options={})
|
6
|
+
super(origin, children, options)
|
7
|
+
@operator = operator
|
8
|
+
end
|
9
|
+
|
10
|
+
def text_before
|
11
|
+
@operator.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Furnace::AVM2::Tokens
|
2
|
+
class UnaryPostOperatorToken < Furnace::Code::SurroundedToken
|
3
|
+
include IsSimple
|
4
|
+
|
5
|
+
def initialize(origin, children, operator, options={})
|
6
|
+
super(origin, children, options)
|
7
|
+
@operator = operator
|
8
|
+
end
|
9
|
+
|
10
|
+
def text_after
|
11
|
+
@operator.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module Furnace::AVM2::Transform
|
2
2
|
AST = Furnace::AST
|
3
|
+
CFG = Furnace::CFG
|
3
4
|
end
|
4
5
|
|
5
6
|
require_relative "transform/ast_build"
|
6
|
-
require_relative "transform/ast_normalize"
|
7
|
+
require_relative "transform/ast_normalize"
|
8
|
+
require_relative "transform/cfg_build"
|
9
|
+
require_relative "transform/cfg_reduce"
|
10
|
+
require_relative "transform/nf_normalize"
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Furnace::AVM2
|
2
2
|
module Transform
|
3
|
+
# I'm not exactly proud of this code, but it works... for now. I really should
|
4
|
+
# rework it if I want to expect it to work good.
|
3
5
|
class ASTBuild
|
4
6
|
CONDITIONAL_OPERATORS = [ :if_eq, :if_false, :if_true, :if_ge, :if_gt,
|
5
7
|
:if_le, :if_lt, :if_ne, :if_nge, :if_ngt,
|
@@ -63,20 +65,33 @@ module Furnace::AVM2
|
|
63
65
|
produce.(expr)
|
64
66
|
end
|
65
67
|
|
66
|
-
finalize_complex_expr = lambda do |opcode, worklist, valid_types, expected_depth=nil|
|
68
|
+
finalize_complex_expr = lambda do |opcode, worklist, valid_types, expected_depth=nil, wrap_to=nil|
|
67
69
|
while worklist.last == opcode.offset
|
68
70
|
extend_complex_expr.(valid_types, expected_depth)
|
71
|
+
|
72
|
+
if wrap_to
|
73
|
+
node, *prepend = *wrap_to
|
74
|
+
|
75
|
+
expr, = consume.(1)
|
76
|
+
expr = AST::Node.new(node, [*prepend, expr])
|
77
|
+
produce.(expr)
|
78
|
+
end
|
79
|
+
|
69
80
|
worklist.pop
|
70
81
|
end
|
71
82
|
end
|
72
83
|
|
73
84
|
expand_conditionals = lambda do
|
85
|
+
expressions = []
|
86
|
+
|
74
87
|
while stack.any? && CONDITIONAL_OPERATORS.include?(stack.last.type)
|
75
88
|
conditional, = consume.(1)
|
76
89
|
|
77
90
|
jump_node = AST::Node.new(:jump_if, [ true, conditional.metadata[:offset], conditional ])
|
78
|
-
|
91
|
+
expressions.unshift jump_node
|
79
92
|
end
|
93
|
+
|
94
|
+
ast.children.concat expressions
|
80
95
|
end
|
81
96
|
|
82
97
|
code.each do |opcode|
|
@@ -88,7 +103,7 @@ module Furnace::AVM2
|
|
88
103
|
end
|
89
104
|
|
90
105
|
finalize_complex_expr.(opcode, shortjump, [ :and, :or ], 1)
|
91
|
-
finalize_complex_expr.(opcode, ternary, CONDITIONAL_OPERATORS)
|
106
|
+
finalize_complex_expr.(opcode, ternary, CONDITIONAL_OPERATORS, nil, [:ternary_if, false])
|
92
107
|
|
93
108
|
if dup == 1 && (opcode.is_a?(ABC::AS3CoerceB) ||
|
94
109
|
opcode.is_a?(ABC::AS3IfTrue) || opcode.is_a?(ABC::AS3IfFalse))
|
@@ -134,7 +149,7 @@ module Furnace::AVM2
|
|
134
149
|
end
|
135
150
|
elsif opcode.is_a?(ABC::AS3Jump)
|
136
151
|
if opcode.body.jump_offset == 0
|
137
|
-
node = AST::Node.new(:
|
152
|
+
node = AST::Node.new(:nop, [], label: opcode.offset)
|
138
153
|
emit.(node)
|
139
154
|
elsif stack.any? && !CONDITIONAL_OPERATORS.include?(stack.last.type)
|
140
155
|
extend_complex_expr.(CONDITIONAL_OPERATORS)
|
@@ -157,11 +172,11 @@ module Furnace::AVM2
|
|
157
172
|
if dup
|
158
173
|
spurious += 1
|
159
174
|
|
160
|
-
save_node = AST::Node.new(:
|
175
|
+
save_node = AST::Node.new(:set_local, [ -spurious, *consume.(1) ])
|
161
176
|
emit.(save_node)
|
162
177
|
|
163
178
|
(1 + dup).times do
|
164
|
-
load_node = AST::Node.new(:
|
179
|
+
load_node = AST::Node.new(:get_local, [ -spurious ])
|
165
180
|
produce.(load_node)
|
166
181
|
end
|
167
182
|
|
@@ -198,7 +213,7 @@ module Furnace::AVM2
|
|
198
213
|
end
|
199
214
|
end
|
200
215
|
|
201
|
-
|
216
|
+
ast.normalize_hierarchy!
|
202
217
|
end
|
203
218
|
end
|
204
219
|
end
|
@@ -3,10 +3,10 @@ module Furnace::AVM2
|
|
3
3
|
class ASTNormalize
|
4
4
|
include AST::Visitor
|
5
5
|
|
6
|
-
def transform(ast
|
6
|
+
def transform(ast)
|
7
7
|
visit ast
|
8
8
|
|
9
|
-
|
9
|
+
ast
|
10
10
|
end
|
11
11
|
|
12
12
|
# (pop x) -> (jump-target) x
|
@@ -15,7 +15,7 @@ module Furnace::AVM2
|
|
15
15
|
|
16
16
|
node.update(:expand, [
|
17
17
|
child,
|
18
|
-
AST::Node.new(:
|
18
|
+
AST::Node.new(:nop, [], node.metadata)
|
19
19
|
], nil)
|
20
20
|
end
|
21
21
|
|
@@ -31,32 +31,73 @@ module Furnace::AVM2
|
|
31
31
|
|
32
32
|
# (if-* a b) -> (*' a b)
|
33
33
|
IF_MAPPING = {
|
34
|
-
:eq
|
35
|
-
:ne
|
36
|
-
:ge
|
37
|
-
:nge
|
38
|
-
:gt
|
39
|
-
:ngt
|
40
|
-
:le
|
41
|
-
:nle
|
42
|
-
:lt
|
43
|
-
:nlt
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:true
|
47
|
-
:false
|
34
|
+
:eq => [false, :==],
|
35
|
+
:ne => [false, :!=],
|
36
|
+
:ge => [false, :>=],
|
37
|
+
:nge => [true, :>=],
|
38
|
+
:gt => [false, :>],
|
39
|
+
:ngt => [true, :>],
|
40
|
+
:le => [false, :<=],
|
41
|
+
:nle => [true, :<=],
|
42
|
+
:lt => [false, :<],
|
43
|
+
:nlt => [true, :<],
|
44
|
+
:strict_eq => [false, :===],
|
45
|
+
:strict_ne => [false, :"!=="],
|
46
|
+
:true => [false, :expand],
|
47
|
+
:false => [true, :expand]
|
48
48
|
}
|
49
49
|
IF_MAPPING.each do |cond, (reverse, comp)|
|
50
50
|
define_method :"on_if_#{cond}" do |node|
|
51
51
|
node.update(comp)
|
52
52
|
node.parent.children[0] = !node.parent.children[0] if reverse
|
53
|
+
|
54
|
+
if node.parent.type == :ternary_if && comp == :expand
|
55
|
+
node.parent.update(:ternary_if_boolean)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# (ternary-if * (op a b x y)) -> (ternary-if-boolean * (op a b) x y)
|
61
|
+
def on_ternary_if(node)
|
62
|
+
comparsion, op = node.children
|
63
|
+
node.children.concat op.children.slice!(2..-1)
|
64
|
+
|
65
|
+
on_ternary_if_boolean(node)
|
66
|
+
end
|
67
|
+
|
68
|
+
# (ternary-if-boolean true (op a b) x y) -> (ternary (op a b) x y)
|
69
|
+
# (ternary-if-boolean false (op a b) x y) -> (ternary (op a b) y x)
|
70
|
+
def on_ternary_if_boolean(node)
|
71
|
+
comparsion, condition, if_true, if_false = node.children
|
72
|
+
if comparsion
|
73
|
+
node.update(:ternary, [ condition, if_true, if_false ])
|
74
|
+
else
|
75
|
+
node.update(:ternary, [ condition, if_false, if_true ])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# (&& (coerce-b ...) (coerce-b ...)) -> (&& ... ...)
|
80
|
+
def fix_boolean(node)
|
81
|
+
node.children.map! do |child|
|
82
|
+
if child.is_a?(AST::Node) &&
|
83
|
+
child.type == :coerce_b
|
84
|
+
child.children.first
|
85
|
+
else
|
86
|
+
child
|
87
|
+
end
|
53
88
|
end
|
54
89
|
end
|
90
|
+
alias :on_and :fix_boolean
|
91
|
+
alias :on_or :fix_boolean
|
92
|
+
alias :on_jump_if :fix_boolean
|
55
93
|
|
56
|
-
|
57
|
-
|
58
|
-
node.update(:remove)
|
94
|
+
def replace_with_nop(node)
|
95
|
+
node.update(:nop)
|
59
96
|
end
|
97
|
+
alias :on_label :replace_with_nop
|
98
|
+
alias :on_debug :replace_with_nop
|
99
|
+
alias :on_debug_file :replace_with_nop
|
100
|
+
alias :on_debug_line :replace_with_nop
|
60
101
|
end
|
61
102
|
end
|
62
103
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Furnace::AVM2
|
2
|
+
module Transform
|
3
|
+
class CFGBuild
|
4
|
+
include AST::Visitor
|
5
|
+
|
6
|
+
def transform(ast)
|
7
|
+
@ast = ast
|
8
|
+
visit @ast
|
9
|
+
|
10
|
+
@cfg = CFG::Graph.new
|
11
|
+
|
12
|
+
@pending_label = nil
|
13
|
+
@pending_queue = []
|
14
|
+
|
15
|
+
@jumps = []
|
16
|
+
|
17
|
+
@ast.children.each_with_index do |node, index|
|
18
|
+
@pending_label ||= node.metadata[:label]
|
19
|
+
@pending_queue << node if ![:nop, :jump].include? node.type
|
20
|
+
|
21
|
+
next_node = @ast.children[index + 1]
|
22
|
+
next_label = next_node.metadata[:label] if next_node
|
23
|
+
|
24
|
+
case node.type
|
25
|
+
when :return_value, :return_void
|
26
|
+
cutoff(nil, [nil])
|
27
|
+
|
28
|
+
when :jump
|
29
|
+
@jumps << node.children[0]
|
30
|
+
cutoff(nil, [node.children.delete_at(0)])
|
31
|
+
|
32
|
+
when :jump_if
|
33
|
+
@jumps << node.children[1]
|
34
|
+
cutoff(node, [node.children.delete_at(1), next_label])
|
35
|
+
|
36
|
+
else
|
37
|
+
if @jumps.include? next_label
|
38
|
+
cutoff(nil, [next_label])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
exit_node = CFG::Node.new(@cfg)
|
44
|
+
@cfg.nodes.add exit_node
|
45
|
+
@cfg.exit = exit_node
|
46
|
+
|
47
|
+
@cfg.eliminate_unreachable!
|
48
|
+
@cfg.merge_redundant!
|
49
|
+
|
50
|
+
@cfg
|
51
|
+
end
|
52
|
+
|
53
|
+
# propagate labels
|
54
|
+
def on_any(node)
|
55
|
+
return if node == @ast
|
56
|
+
|
57
|
+
label = nil
|
58
|
+
|
59
|
+
node.children.each do |child|
|
60
|
+
if child.is_a?(AST::Node) && child.metadata[:label]
|
61
|
+
if label.nil? || child.metadata[:label] < label
|
62
|
+
label = child.metadata[:label]
|
63
|
+
end
|
64
|
+
|
65
|
+
child.metadata.delete :label
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
node.metadata[:label] = label if label
|
70
|
+
end
|
71
|
+
|
72
|
+
def cutoff(cti, targets)
|
73
|
+
node = CFG::Node.new(@cfg, @pending_label, @pending_queue, cti, targets)
|
74
|
+
|
75
|
+
if @cfg.nodes.empty?
|
76
|
+
@cfg.entry = node
|
77
|
+
end
|
78
|
+
|
79
|
+
@cfg.nodes.add node
|
80
|
+
|
81
|
+
@pending_label = nil
|
82
|
+
@pending_queue = []
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|