pub struct ControlFlowGraph {
pub blocks: HashMap<String, BasicBlock>,
pub edges: HashMap<String, Vec<String>>,
pub entry_block: String,
pub exit_blocks: Vec<String>,
}Expand description
Control Flow Graph extracted from MIR basic blocks
Fields§
§blocks: HashMap<String, BasicBlock>Map from block ID to BasicBlock
edges: HashMap<String, Vec<String>>Map from block ID to successor block IDs
entry_block: StringEntry block (usually “bb0”)
exit_blocks: Vec<String>Exit blocks (blocks with Return terminator)
Implementations§
Source§impl ControlFlowGraph
impl ControlFlowGraph
Sourcepub fn from_mir_function(function: &MirFunction) -> Self
pub fn from_mir_function(function: &MirFunction) -> Self
Extract CFG from a MIR function’s body
Sourcepub fn block_count(&self) -> usize
pub fn block_count(&self) -> usize
Get the number of basic blocks in the CFG
Sourcepub fn branch_count(&self) -> usize
pub fn branch_count(&self) -> usize
Count branch points in the CFG (blocks with multiple successors)
Sourcepub fn is_too_complex_for_path_enumeration(&self) -> bool
pub fn is_too_complex_for_path_enumeration(&self) -> bool
Check if this CFG is too complex for full path enumeration. Returns true if enumeration should be skipped to prevent memory explosion.
The heuristic is based on empirical observation:
- influxdb3_id: 78 blocks, 20 branches → works fine (~100 MB)
- influxdb3 serve: 2442 blocks, 381 branches → 58 GB explosion
A CFG with B branches can have up to 2^B paths. With MAX_DEPTH=50, we limit path length, but the DFS exploration tree still grows exponentially.
Safe thresholds (empirically derived):
- MAX_BLOCKS: 500 (well above typical functions, catches mega-closures)
- MAX_BRANCHES: 100 (limits exponential exploration)
Sourcepub fn get_all_paths(&self) -> (Vec<Vec<String>>, bool)
pub fn get_all_paths(&self) -> (Vec<Vec<String>>, bool)
Enumerate all paths from entry to exit blocks Returns paths as sequences of block IDs
For extremely complex CFGs (large async closures, state machines), returns an empty vec to prevent memory explosion.
Returns (paths, was_skipped_due_to_complexity)
Sourcepub fn get_block(&self, block_id: &str) -> Option<&BasicBlock>
pub fn get_block(&self, block_id: &str) -> Option<&BasicBlock>
Get the basic block for a given ID
Sourcepub fn has_branching(&self) -> bool
pub fn has_branching(&self) -> bool
Check if the CFG has any branching (multiple paths)
Trait Implementations§
Source§impl Clone for ControlFlowGraph
impl Clone for ControlFlowGraph
Source§fn clone(&self) -> ControlFlowGraph
fn clone(&self) -> ControlFlowGraph
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for ControlFlowGraph
impl RefUnwindSafe for ControlFlowGraph
impl Send for ControlFlowGraph
impl Sync for ControlFlowGraph
impl Unpin for ControlFlowGraph
impl UnsafeUnpin for ControlFlowGraph
impl UnwindSafe for ControlFlowGraph
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more