Walk blocks in CFG order
This commit is contained in:
+21
-6
@@ -109,10 +109,18 @@ impl RegFn {
|
||||
let pcs = flat_fn.code.iter().map(|i| i.pc).collect::<Vec<usize>>();
|
||||
let (starts, mut blocks) = find_basic_blocks(&flat_fn.code, &pcs);
|
||||
|
||||
let mut output = Vec::with_capacity(flat_fn.code.len());
|
||||
let mut next_val = flat_fn.var_count; // Reserve values for locals
|
||||
|
||||
for b in 0..blocks.len() {
|
||||
// Emit per block, so blocks can be WALKED in the order control reaches
|
||||
// them and still be READ in listing order. Listing order alone is not
|
||||
// enough: a for-of puts its body before the test, and the body is
|
||||
// reached only by the back edge, so walking it first finds no stack.
|
||||
let mut emitted = vec![Vec::new(); blocks.len()];
|
||||
let mut seen = vec![false; blocks.len()];
|
||||
let mut todo = vec![0];
|
||||
seen[0] = true;
|
||||
|
||||
while let Some(b) = todo.pop() {
|
||||
// A block starts with the stack it is ENTERED with, not with
|
||||
// whatever the block above it in the listing left behind. This one
|
||||
// line is what stops the walk running off a `return` into a
|
||||
@@ -212,18 +220,25 @@ impl RegFn {
|
||||
}
|
||||
|
||||
reg_instr.block_start = std::mem::take(&mut first);
|
||||
output.push(reg_instr);
|
||||
emitted[b].push(reg_instr);
|
||||
}
|
||||
|
||||
// Every edge out of here arrives at its target with this stack.
|
||||
// One pass in listing order reaches every block, because a block is
|
||||
// always entered from earlier in the listing before any back edge
|
||||
// returns to it.
|
||||
// Walking a block only after something has arrived at it is what
|
||||
// makes the entry stack right, and it is why the order is the CFG's
|
||||
// and not the listing's.
|
||||
for i in 0..blocks[b].succ.len() {
|
||||
let to = blocks[b].succ[i];
|
||||
blocks[to].arrive(&stack);
|
||||
|
||||
if !seen[to] {
|
||||
seen[to] = true;
|
||||
todo.push(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let output = emitted.into_iter().flatten().collect::<Vec<RegInstr>>();
|
||||
|
||||
Self {
|
||||
name: flat_fn.name,
|
||||
|
||||
Reference in New Issue
Block a user