Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7578736

Browse files
committed
More moving around and documentation
1 parent 907cf23 commit 7578736

File tree

2 files changed

+78
-76
lines changed

2 files changed

+78
-76
lines changed

lib/syntax_tree/yarv/control_flow_graph.rb

Lines changed: 69 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,64 @@ module YARV
1414
# cfg = SyntaxTree::YARV::ControlFlowGraph.compile(iseq)
1515
#
1616
class ControlFlowGraph
17+
# This is the instruction sequence that this control flow graph
18+
# corresponds to.
19+
attr_reader :iseq
20+
21+
# This is the list of instructions that this control flow graph contains.
22+
# It is effectively the same as the list of instructions in the
23+
# instruction sequence but with line numbers and events filtered out.
24+
attr_reader :insns
25+
26+
# This is the set of basic blocks that this control-flow graph contains.
27+
attr_reader :blocks
28+
29+
def initialize(iseq, insns, blocks)
30+
@iseq = iseq
31+
@insns = insns
32+
@blocks = blocks
33+
end
34+
35+
def disasm
36+
fmt = Disassembler.new
37+
output = StringIO.new
38+
output.puts "== cfg #{iseq.name}"
39+
40+
blocks.each do |block|
41+
output.print(block.id)
42+
43+
unless block.predecessors.empty?
44+
output.print(" # from: #{block.predecessors.map(&:id).join(", ")}")
45+
end
46+
47+
output.puts
48+
49+
block.insns.each do |insn|
50+
output.print(" ")
51+
output.puts(insn.disasm(fmt))
52+
end
53+
54+
successors = block.successors.map(&:id)
55+
successors << "leaves" if block.last.leaves?
56+
output.print(" # to: #{successors.join(", ")}") unless successors.empty?
57+
58+
output.puts
59+
end
60+
61+
output.string
62+
end
63+
64+
# This method is used to verify that the control flow graph is well
65+
# formed. It does this by checking that each basic block is itself well
66+
# formed.
67+
def verify
68+
blocks.each(&:verify)
69+
end
70+
71+
def self.compile(iseq)
72+
Compiler.new(iseq).compile
73+
end
74+
1775
# This object represents a single basic block, wherein all contained
1876
# instructions do not branch except for the last one.
1977
class BasicBlock
@@ -28,19 +86,19 @@ class BasicBlock
2886
attr_reader :insns
2987

3088
# This is an array of basic blocks that are predecessors to this block.
31-
attr_reader :preds
89+
attr_reader :predecessors
3290

3391
# This is an array of basic blocks that are successors to this block.
34-
attr_reader :succs
92+
attr_reader :successors
3593

3694
def initialize(block_start, insns)
3795
@id = "block_#{block_start}"
3896

3997
@block_start = block_start
4098
@insns = insns
4199

42-
@preds = []
43-
@succs = []
100+
@predecessors = []
101+
@successors = []
44102
end
45103

46104
# This method is used to verify that the basic block is well formed. It
@@ -122,81 +180,25 @@ def build_basic_blocks
122180
end
123181
end
124182

125-
# Now we need to connect the blocks by letting them know which blocks
126-
# precede them and which blocks follow them.
183+
# Connect the blocks by letting them know which blocks precede them and
184+
# which blocks succeed them.
127185
def connect_basic_blocks(blocks)
128186
blocks.each do |block_start, block|
129187
insn = block.last
130188

131189
if insn.branches? && insn.respond_to?(:label)
132-
block.succs << blocks.fetch(labels[insn.label])
190+
block.successors << blocks.fetch(labels[insn.label])
133191
end
134192

135193
if (!insn.branches? && !insn.leaves?) || insn.falls_through?
136-
block.succs << blocks.fetch(block_start + block.insns.length)
194+
block.successors << blocks.fetch(block_start + block.insns.length)
137195
end
138196

139-
block.succs.each { |succ| succ.preds << block }
140-
end
141-
end
142-
end
143-
144-
# This is the instruction sequence that this control flow graph
145-
# corresponds to.
146-
attr_reader :iseq
147-
148-
# This is the list of instructions that this control flow graph contains.
149-
# It is effectively the same as the list of instructions in the
150-
# instruction sequence but with line numbers and events filtered out.
151-
attr_reader :insns
152-
153-
# This is the set of basic blocks that this control-flow graph contains.
154-
attr_reader :blocks
155-
156-
def initialize(iseq, insns, blocks)
157-
@iseq = iseq
158-
@insns = insns
159-
@blocks = blocks
160-
end
161-
162-
def disasm
163-
fmt = Disassembler.new
164-
output = StringIO.new
165-
output.puts "== cfg #{iseq.name}"
166-
167-
blocks.each do |block|
168-
output.print(block.id)
169-
170-
unless block.preds.empty?
171-
output.print(" # from: #{block.preds.map(&:id).join(", ")}")
172-
end
173-
174-
output.puts
175-
176-
block.insns.each do |insn|
177-
output.print(" ")
178-
output.puts(insn.disasm(fmt))
197+
block.successors.each do |successor|
198+
successor.predecessors << block
199+
end
179200
end
180-
181-
succs = block.succs.map(&:id)
182-
succs << "leaves" if block.last.leaves?
183-
output.print(" # to: #{succs.join(", ")}") unless succs.empty?
184-
185-
output.puts
186201
end
187-
188-
output.string
189-
end
190-
191-
# This method is used to verify that the control flow graph is well
192-
# formed. It does this by checking that each basic block is itself well
193-
# formed.
194-
def verify
195-
blocks.each(&:verify)
196-
end
197-
198-
def self.compile(iseq)
199-
Compiler.new(iseq).compile
200202
end
201203
end
202204
end

lib/syntax_tree/yarv/data_flow_graph.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def self.compile(cfg)
108108
until stack.empty?
109109
succ = stack.pop
110110
succ_flow = block_flows.fetch(succ.block_start)
111-
succ.preds.each do |pred|
111+
succ.predecessors.each do |pred|
112112
pred_flow = block_flows.fetch(pred.block_start)
113113

114114
# Does a predecessor block have fewer outputs than the successor
@@ -139,12 +139,12 @@ def self.compile(cfg)
139139
cfg.blocks.each do |pred|
140140
pred_flow = block_flows.fetch(pred.block_start)
141141

142-
if pred.succs.empty?
142+
if pred.successors.empty?
143143
# With no successors, there should be no output arguments.
144144
raise unless pred_flow.out.empty?
145145
else
146146
# Check with successor...
147-
pred.succs.each do |succ|
147+
pred.successors.each do |succ|
148148
succ_flow = block_flows.fetch(succ.block_start)
149149

150150
# The predecessor should have as many output arguments as the
@@ -165,8 +165,8 @@ def disasm
165165

166166
cfg.blocks.each do |block|
167167
output.print(block.id)
168-
unless block.preds.empty?
169-
output.print(" # from: #{block.preds.map(&:id).join(", ")}")
168+
unless block.predecessors.empty?
169+
output.print(" # from: #{block.predecessors.map(&:id).join(", ")}")
170170
end
171171
output.puts
172172

@@ -198,9 +198,9 @@ def disasm
198198
output.puts
199199
end
200200

201-
succs = block.succs.map(&:id)
202-
succs << "leaves" if block.last.leaves?
203-
output.puts(" # to: #{succs.join(", ")}") unless succs.empty?
201+
successors = block.successors.map(&:id)
202+
successors << "leaves" if block.last.leaves?
203+
output.puts(" # to: #{successors.join(", ")}") unless successors.empty?
204204

205205
unless block_flow.out.empty?
206206
output.puts " # out: #{block_flow.out.join(", ")}"
@@ -211,4 +211,4 @@ def disasm
211211
end
212212
end
213213
end
214-
end
214+
end

0 commit comments

Comments
 (0)