@@ -40,8 +40,8 @@ def disasm
40
40
blocks . each do |block |
41
41
output . print ( block . id )
42
42
43
- unless block . predecessors . empty?
44
- output . print ( " # from: #{ block . predecessors . map ( &:id ) . join ( ", " ) } " )
43
+ unless block . incoming_blocks . empty?
44
+ output . print ( " # from: #{ block . incoming_blocks . map ( &:id ) . join ( ", " ) } " )
45
45
end
46
46
47
47
output . puts
@@ -51,9 +51,9 @@ def disasm
51
51
output . puts ( insn . disasm ( fmt ) )
52
52
end
53
53
54
- successors = block . successors . map ( &:id )
55
- successors << "leaves" if block . insns . last . leaves?
56
- output . print ( " # to: #{ successors . join ( ", " ) } " ) unless successors . empty?
54
+ dests = block . outgoing_blocks . map ( &:id )
55
+ dests << "leaves" if block . insns . last . leaves?
56
+ output . print ( " # to: #{ dests . join ( ", " ) } " ) unless dests . empty?
57
57
58
58
output . puts
59
59
end
@@ -72,49 +72,6 @@ def self.compile(iseq)
72
72
Compiler . new ( iseq ) . compile
73
73
end
74
74
75
- # This object represents a single basic block, wherein all contained
76
- # instructions do not branch except for the last one.
77
- class BasicBlock
78
- # This is the unique identifier for this basic block.
79
- attr_reader :id
80
-
81
- # This is the index into the list of instructions where this block
82
- # starts.
83
- attr_reader :block_start
84
-
85
- # This is the set of instructions that this block contains.
86
- attr_reader :insns
87
-
88
- # This is an array of basic blocks that are predecessors to this block.
89
- attr_reader :predecessors
90
-
91
- # This is an array of basic blocks that are successors to this block.
92
- attr_reader :successors
93
-
94
- def initialize ( block_start , insns )
95
- @id = "block_#{ block_start } "
96
-
97
- @block_start = block_start
98
- @insns = insns
99
-
100
- @predecessors = [ ]
101
- @successors = [ ]
102
- end
103
-
104
- # Yield each instruction in this basic block along with its index from
105
- # the original instruction sequence.
106
- def each_with_index ( &block )
107
- insns . each . with_index ( block_start , &block )
108
- end
109
-
110
- # This method is used to verify that the basic block is well formed. It
111
- # checks that the only instruction in this basic block that branches is
112
- # the last instruction.
113
- def verify
114
- insns [ 0 ...-1 ] . each { |insn | raise unless insn . branch_targets . empty? }
115
- end
116
- end
117
-
118
75
# This class is responsible for creating a control flow graph from the
119
76
# given instruction sequence.
120
77
class Compiler
@@ -186,22 +143,22 @@ def build_basic_blocks
186
143
end
187
144
end
188
145
189
- # Connect the blocks by letting them know which blocks precede them and
190
- # which blocks succeed them .
146
+ # Connect the blocks by letting them know which blocks are incoming and
147
+ # outgoing from each block .
191
148
def connect_basic_blocks ( blocks )
192
149
blocks . each do |block_start , block |
193
150
insn = block . insns . last
194
151
195
152
insn . branch_targets . each do |branch_target |
196
- block . successors << blocks . fetch ( labels [ branch_target ] )
153
+ block . outgoing_blocks << blocks . fetch ( labels [ branch_target ] )
197
154
end
198
155
199
156
if ( insn . branch_targets . empty? && !insn . leaves? ) || insn . falls_through?
200
- block . successors << blocks . fetch ( block_start + block . insns . length )
157
+ block . outgoing_blocks << blocks . fetch ( block_start + block . insns . length )
201
158
end
202
159
203
- block . successors . each do |successor |
204
- successor . predecessors << block
160
+ block . outgoing_blocks . each do |outgoing_block |
161
+ outgoing_block . incoming_blocks << block
205
162
end
206
163
end
207
164
end
0 commit comments