///|
/// Reverse postorder over every CFG root, starting with the entry block.
///
/// The verifier seeds block 0 and every predecessor-free block separately,
/// so unreachable rooted components remain verifiable. The explicit stack
/// keeps input-controlled CFG depth off the native call stack.
fn reverse_postorder_from_roots(
successors : Array[Array[Int]],
has_predecessor : Array[Bool],
) -> Array[Int] {
let postorder : Array[Int] = []
let visited = Array::make(successors.length(), false)
for root in 0.. 0 {
let (block, next_successor) = stack[stack.length() - 1]
let block_successors = successors[block]
if next_successor < block_successors.length() {
stack[stack.length() - 1] = (block, next_successor + 1)
let target = block_successors[next_successor]
if target >= 0 && target < successors.length() && !visited[target] {
visited[target] = true
stack.push((target, 0))
}
} else {
postorder.push(block)
stack.pop() |> ignore
}
}
}
postorder.rev_in_place()
postorder
}