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

Commit f600b06

Browse files
committed
Properly use the disassembler for the cfg
1 parent 439ffb6 commit f600b06

File tree

4 files changed

+82
-79
lines changed

4 files changed

+82
-79
lines changed

lib/syntax_tree/yarv/control_flow_graph.rb

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,28 @@ def initialize(iseq, insns, blocks)
3333
end
3434

3535
def disasm
36-
fmt = Disassembler.new
37-
output = StringIO.new
38-
output.puts "== cfg #{iseq.name}"
36+
fmt = Disassembler.new(iseq)
37+
fmt.output.puts "== cfg #{iseq.name}"
3938

4039
blocks.each do |block|
41-
output.print(block.id)
40+
fmt.output.print(block.id)
4241

4342
unless block.incoming_blocks.empty?
44-
output.print(" # from: #{block.incoming_blocks.map(&:id).join(", ")}")
43+
fmt.output.print(" # from: #{block.incoming_blocks.map(&:id).join(", ")}")
4544
end
4645

47-
output.puts
46+
fmt.output.puts
4847

49-
block.insns.each do |insn|
50-
output.print(" ")
51-
output.puts(insn.disasm(fmt))
52-
end
48+
fmt.with_prefix(" ") { fmt.format_insns!(block.insns) }
5349

5450
dests = block.outgoing_blocks.map(&:id)
5551
dests << "leaves" if block.insns.last.leaves?
56-
output.print(" # to: #{dests.join(", ")}") unless dests.empty?
52+
fmt.output.print(" # to: #{dests.join(", ")}") unless dests.empty?
5753

58-
output.puts
54+
fmt.output.puts
5955
end
6056

61-
output.string
57+
fmt.string
6258
end
6359

6460
# This method is used to verify that the control flow graph is well

lib/syntax_tree/yarv/disassembler.rb

Lines changed: 59 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ module SyntaxTree
44
module YARV
55
class Disassembler
66
attr_reader :output, :queue
7+
78
attr_reader :current_prefix
89
attr_accessor :current_iseq
910

10-
def initialize
11+
def initialize(current_iseq = nil)
1112
@output = StringIO.new
1213
@queue = []
1314

1415
@current_prefix = ""
15-
@current_iseq = nil
16+
@current_iseq = current_iseq
1617
end
1718

1819
########################################################################
@@ -97,16 +98,69 @@ def object(value)
9798
end
9899

99100
########################################################################
100-
# Main entrypoint
101+
# Entrypoints
101102
########################################################################
102103

104+
def string
105+
output.string
106+
end
107+
103108
def format!
104109
while (@current_iseq = queue.shift)
105110
output << "\n" if output.pos > 0
106111
format_iseq(@current_iseq)
107112
end
113+
end
108114

109-
output.string
115+
def format_insns!(insns, length = 0)
116+
events = []
117+
lines = []
118+
119+
insns.each do |insn|
120+
case insn
121+
when Integer
122+
lines << insn
123+
when Symbol
124+
events << event(insn)
125+
when InstructionSequence::Label
126+
# skip
127+
else
128+
output << "#{current_prefix}%04d " % length
129+
130+
disasm = insn.disasm(self)
131+
output << disasm
132+
133+
if lines.any?
134+
output << " " * (65 - disasm.length) if disasm.length < 65
135+
elsif events.any?
136+
output << " " * (39 - disasm.length) if disasm.length < 39
137+
end
138+
139+
if lines.any?
140+
output << "(%4d)" % lines.last
141+
lines.clear
142+
end
143+
144+
if events.any?
145+
output << "[#{events.join}]"
146+
events.clear
147+
end
148+
149+
output << "\n"
150+
length += insn.length
151+
end
152+
end
153+
end
154+
155+
def with_prefix(value)
156+
previous = @current_prefix
157+
158+
begin
159+
@current_prefix = value
160+
yield
161+
ensure
162+
@current_prefix = previous
163+
end
110164
end
111165

112166
private
@@ -157,55 +211,7 @@ def format_iseq(iseq)
157211
output << "#{current_prefix}#{locals.join(" ")}\n"
158212
end
159213

160-
length = 0
161-
events = []
162-
lines = []
163-
164-
iseq.insns.each do |insn|
165-
case insn
166-
when Integer
167-
lines << insn
168-
when Symbol
169-
events << event(insn)
170-
when InstructionSequence::Label
171-
# skip
172-
else
173-
output << "#{current_prefix}%04d " % length
174-
175-
disasm = insn.disasm(self)
176-
output << disasm
177-
178-
if lines.any?
179-
output << " " * (65 - disasm.length) if disasm.length < 65
180-
elsif events.any?
181-
output << " " * (39 - disasm.length) if disasm.length < 39
182-
end
183-
184-
if lines.any?
185-
output << "(%4d)" % lines.last
186-
lines.clear
187-
end
188-
189-
if events.any?
190-
output << "[#{events.join}]"
191-
events.clear
192-
end
193-
194-
output << "\n"
195-
length += insn.length
196-
end
197-
end
198-
end
199-
200-
def with_prefix(value)
201-
previous = @current_prefix
202-
203-
begin
204-
@current_prefix = value
205-
yield
206-
ensure
207-
@current_prefix = previous
208-
end
214+
format_insns!(iseq.insns)
209215
end
210216
end
211217
end

lib/syntax_tree/yarv/instruction_sequence.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,10 @@ def to_a
270270
end
271271

272272
def disasm
273-
disassembler = Disassembler.new
274-
disassembler.enqueue(self)
275-
disassembler.format!
273+
fmt = Disassembler.new
274+
fmt.enqueue(self)
275+
fmt.format!
276+
fmt.string
276277
end
277278

278279
# This method converts our linked list of instructions into a final array

test/yarv_test.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -305,22 +305,22 @@ def test_cfg
305305
assert_equal(<<~CFG, cfg.disasm)
306306
== cfg <compiled>
307307
block_0
308-
putobject 100
309-
putobject 14
310-
putobject_INT2FIX_0_
311-
opt_lt <calldata!mid:<, argc:1, ARGS_SIMPLE>
312-
branchunless 13
308+
0000 putobject 100
309+
0002 putobject 14
310+
0004 putobject_INT2FIX_0_
311+
0005 opt_lt <calldata!mid:<, argc:1, ARGS_SIMPLE>
312+
0007 branchunless 13
313313
# to: block_7, block_5
314314
block_5 # from: block_0
315-
putobject -1
316-
jump 14
315+
0000 putobject -1
316+
0002 jump 14
317317
# to: block_8
318318
block_7 # from: block_0
319-
putobject_INT2FIX_1_
319+
0000 putobject_INT2FIX_1_
320320
# to: block_8
321321
block_8 # from: block_5, block_7
322-
opt_plus <calldata!mid:+, argc:1, ARGS_SIMPLE>
323-
leave
322+
0000 opt_plus <calldata!mid:+, argc:1, ARGS_SIMPLE>
323+
0002 leave
324324
# to: leaves
325325
CFG
326326
end

0 commit comments

Comments
 (0)