[][src]Function walrus::ir::dfs_in_order

pub fn dfs_in_order<'instr>(
    visitor: &mut impl Visitor<'instr>,
    func: &'instr LocalFunction,
    start: InstrSeqId
)

Perform an intra-procedural, depth-first, in-order traversal of the IR.

  • Intra-procedural: Only traverses IR within a function. Does not cross function boundaries (although it will report edges to other functions via visit_function_id calls on the visitor, so you can use this as a building block for making global, inter-procedural analyses).

  • Depth-first, in-order: Visits instructions and instruction sequences in the order they are defined and nested. See Wikipedia for details.

Calls visitor methods for every instruction, instruction sequence, and resource that the traversal visits.

The traversals begins at the start instruction sequence and goes from there. To traverse everything in a function, pass func.entry_block() as start.

This implementation is iterative — not recursive — and so it will not blow the call stack on deeply nested Wasm (although it may still OOM).

Example

This example counts the number of instruction sequences in a function.

use walrus::LocalFunction;
use walrus::ir::*;

#[derive(Default)]
struct CountInstructionSequences {
    count: usize,
}

impl<'instr> Visitor<'instr> for CountInstructionSequences {
    fn start_instr_seq(&mut self, _: &'instr InstrSeq) {
        self.count += 1;
    }
}

// Get a function from somewhere.
let my_func: &LocalFunction = get_my_function();

// Create our visitor.
let mut visitor = CountInstructionSequences::default();

// Traverse everything in the function with our visitor.
dfs_in_order(&mut visitor, my_func, my_func.entry_block());

// Use the aggregate results that `visitor` built up.
println!("The number of instruction sequences in `my_func` is {}", visitor.count);