Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Provide BasicBlock.each_with_index
  • Loading branch information
kddnewton committed Feb 2, 2023
commit 92cbfcae048c6867d0d5a6db5265591ed0b53076
7 changes: 6 additions & 1 deletion lib/syntax_tree/yarv/control_flow_graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ def initialize(block_start, insns)
@successors = []
end

# Yield each instruction in this basic block along with its index from
# the original instruction sequence.
def each_with_index(&block)
insns.each.with_index(block_start, &block)
end

# This method is used to verify that the basic block is well formed. It
# checks that the only instruction in this basic block that branches is
# the last instruction.
Expand Down Expand Up @@ -171,7 +177,6 @@ def find_basic_block_starts
# block. They are keyed by the index of their first instruction.
def build_basic_blocks
block_starts = find_basic_block_starts
blocks = {}

block_starts.each_with_index.to_h do |block_start, block_index|
block_end = (block_starts[(block_index + 1)..] + [insns.length]).min
Expand Down
20 changes: 10 additions & 10 deletions lib/syntax_tree/yarv/data_flow_graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ def self.compile(cfg)
# blocks.
block_flows = {}
cfg.blocks.each do |block|
block_flows[block.block_start] = DataFlow.new
block_flows[block.id] = DataFlow.new
end

# Now, discover the data flow within each basic block. Using an abstract
# stack, connect from consumers of data to the producers of that data.
cfg.blocks.each do |block|
block_flow = block_flows.fetch(block.block_start)
block_flow = block_flows.fetch(block.id)

stack = []
stack_initial_depth = 0

# Go through each instruction in the block...
block.insns.each.with_index(block.block_start) do |insn, index|
block.each_with_index do |insn, index|
insn_flow = insn_flows[index]

# How many values will be missing from the local stack to run this
Expand Down Expand Up @@ -107,9 +107,9 @@ def self.compile(cfg)
stack = [*cfg.blocks]
until stack.empty?
succ = stack.pop
succ_flow = block_flows.fetch(succ.block_start)
succ_flow = block_flows.fetch(succ.id)
succ.predecessors.each do |pred|
pred_flow = block_flows.fetch(pred.block_start)
pred_flow = block_flows.fetch(pred.id)

# Does a predecessor block have fewer outputs than the successor
# has inputs?
Expand All @@ -132,20 +132,20 @@ def self.compile(cfg)

# Verify that we constructed the data flow graph correctly. Check that
# the first block has no arguments.
raise unless block_flows.fetch(cfg.blocks.first.block_start).in.empty?
raise unless block_flows.fetch(cfg.blocks.first.id).in.empty?

# Check all control flow edges between blocks pass the right number of
# arguments.
cfg.blocks.each do |pred|
pred_flow = block_flows.fetch(pred.block_start)
pred_flow = block_flows.fetch(pred.id)

if pred.successors.empty?
# With no successors, there should be no output arguments.
raise unless pred_flow.out.empty?
else
# Check with successor...
pred.successors.each do |succ|
succ_flow = block_flows.fetch(succ.block_start)
succ_flow = block_flows.fetch(succ.id)

# The predecessor should have as many output arguments as the
# success has input arguments.
Expand All @@ -170,12 +170,12 @@ def disasm
end
output.puts

block_flow = block_flows.fetch(block.block_start)
block_flow = block_flows.fetch(block.id)
unless block_flow.in.empty?
output.puts " # in: #{block_flow.in.join(", ")}"
end

block.insns.each.with_index(block.block_start) do |insn, index|
block.each_with_index do |insn, index|
output.print(" ")
output.print(insn.disasm(fmt))

Expand Down