fn analyze_function(
        &mut self,
        initial_state: Self::State,
        function_view: &FunctionDefinitionView<CompiledModule>,
        cfg: &VMControlFlowGraph,
    ) -> InvariantMap<Self::State> {
        let mut inv_map: InvariantMap<Self::State> = InvariantMap::new();
        let entry_block_id = cfg.entry_block_id();
        // seed worklist/precondition map with initial block/state
        let mut work_list = vec![entry_block_id];
        inv_map.insert(
            entry_block_id,
            BlockInvariant {
                pre: initial_state,
                post: BlockPostcondition::Success,
            },
        );

        while let Some(block_id) = work_list.pop() {
            let mut block_invariant = match inv_map.get_mut(&block_id) {
                Some(BlockInvariant {
                    post: BlockPostcondition::Error,
                    ..
                }) =>
                // Analyzing this block previously resulted in an error. Avoid double-reporting.
                {
                    continue
                }
                Some(invariant) => invariant.clone(),
                None => unreachable!("Missing invariant for block {}", block_id),
            };

            let mut state = block_invariant.pre.clone();
            let block_ends_in_error = self
                .execute_block(block_id, &mut state, &function_view, &cfg)
                .is_err();
            if block_ends_in_error {
                block_invariant.post = BlockPostcondition::Error;
                continue;
            } else {
                block_invariant.post = BlockPostcondition::Success;
            };

            let block = cfg
                .block_of_id(block_id)
                .expect("block_id is not the start offset of a block");
            // propagate postcondition of this block to successor blocks
            for next_block_id in &block.successors {
                match inv_map.get_mut(next_block_id) {
                    Some(next_block_invariant) => {
                        let join_result = next_block_invariant.pre.join(&state);
                        match join_result {
                            JoinResult::Unchanged => {
                                // Pre is the same after join. Reanalyzing this block would produce
                                // the same post. Don't schedule it.
                                continue;
                            }
                            JoinResult::Changed => {
                                // The pre changed. Schedule the next block.
                                work_list.push(*next_block_id);
                            }
                            JoinResult::Error => {
                                // This join produced an error. Don't schedule the block.
                                next_block_invariant.post = BlockPostcondition::Error;
                                continue;
                            }
                        }
                    }
                    None => {
                        // Haven't visited the next block yet. Use the post of the current block as
                        // its pre and schedule it.
                        inv_map.insert(
                            *next_block_id,
                            BlockInvariant {
                                pre: state.clone(),
                                post: BlockPostcondition::Success,
                            },
                        );
                        work_list.push(*next_block_id);
                    }
                }
            }
        }

        inv_map
    }
/// Analyze procedure local@function_view starting from pre-state local@initial_state.
Analyze procedure local@function_view starting from pre-state local@initial_state.
Analyze procedure local@function_view starting from pre - state local@initial_state .
fn analyze_function(
        &mut self,
        initial_state: Self::State,
        function_view: &FunctionDefinitionView<CompiledModule>,
        cfg: &VMControlFlowGraph,
    ) -> InvariantMap<Self::State> {
        let mut inv_map: InvariantMap<Self::State> = InvariantMap::new();
        let entry_block_id = cfg.entry_block_id();
        // seed worklist/precondition map with initial block/state
        let mut work_list = vec![entry_block_id];
        inv_map.insert(
            entry_block_id,
            BlockInvariant {
                pre: initial_state,
                post: BlockPostcondition::Success,
            },
        );
        while let Some(block_id) = work_list.pop() {
            let mut block_invariant = match inv_map.get_mut(&block_id) {
                Some(BlockInvariant {
                    post: BlockPostcondition::Error,
                    ..
                }) =>
                // Analyzing this block previously resulted in an error. Avoid double-reporting.
                {
                    continue
                }
                Some(invariant) => invariant.clone(),
                None => unreachable!("Missing invariant for block {}", block_id),
            };
            let mut state = block_invariant.pre.clone();
            let block_ends_in_error = self
                .execute_block(block_id, &mut state, &function_view, &cfg)
                .is_err();
            if block_ends_in_error {
                block_invariant.post = BlockPostcondition::Error;
                continue;
            } else {
                block_invariant.post = BlockPostcondition::Success;
            };
            let block = cfg
                .block_of_id(block_id)
                .expect("block_id is not the start offset of a block");
            // propagate postcondition of this block to successor blocks
            for next_block_id in &block.successors {
                match inv_map.get_mut(next_block_id) {
                    Some(next_block_invariant) => {
                        let join_result = next_block_invariant.pre.join(&state);
                        match join_result {
                            JoinResult::Unchanged => {
                                // Pre is the same after join. Reanalyzing this block would produce
                                // the same post. Don't schedule it.
                                continue;
                            }
                            JoinResult::Changed => {
                                // The pre changed. Schedule the next block.
                                work_list.push(*next_block_id);
                            }
                            JoinResult::Error => {
                                // This join produced an error. Don't schedule the block.
                                next_block_invariant.post = BlockPostcondition::Error;
                                continue;
                            }
                        }
                    }
                    None => {
                        // Haven't visited the next block yet. Use the post of the current block as
                        // its pre and schedule it.
                        inv_map.insert(
                            *next_block_id,
                            BlockInvariant {
                                pre: state.clone(),
                                post: BlockPostcondition::Success,
                            },
                        );
                        work_list.push(*next_block_id);
                    }
                }
            }
        }
        inv_map
    }
fn analyze_function ( & mut self , initial_state : Self :: State , function_view : & FunctionDefinitionView < CompiledModule > , cfg : & VMControlFlowGraph , ) -> InvariantMap < Self :: State > { let mut inv_map : InvariantMap < Self :: State > = InvariantMap :: new ( ) ; let entry_block_id = cfg . entry_block_id ( ) ; // seed worklist/precondition map with initial block/state let mut work_list = vec ! [ entry_block_id ] ; inv_map . insert ( entry_block_id , BlockInvariant { pre : initial_state , post : BlockPostcondition :: Success , } , ) ; while let Some ( block_id ) = work_list . pop ( ) { let mut block_invariant = match inv_map . get_mut ( & block_id ) { Some ( BlockInvariant { post : BlockPostcondition :: Error , .. } ) => // Analyzing this block previously resulted in an error. Avoid double-reporting. { continue } Some ( invariant ) => invariant . clone ( ) , None => unreachable ! ( " " block_id ) , } ; let mut state = block_invariant . pre . clone ( ) ; let block_ends_in_error = self . execute_block ( block_id , & mut state , & function_view , & cfg ) . is_err ( ) ; if block_ends_in_error { block_invariant . post = BlockPostcondition :: Error ; continue ; } else { block_invariant . post = BlockPostcondition :: Success ; } ; let block = cfg . block_of_id ( block_id ) . expect ( " " ) ; // propagate postcondition of this block to successor blocks for next_block_id in & block . successors { match inv_map . get_mut ( next_block_id ) { Some ( next_block_invariant ) => { let join_result = next_block_invariant . pre . join ( & state ) ; match join_result { JoinResult :: Unchanged => { // Pre is the same after join. Reanalyzing this block would produce // the same post. Don't schedule it. continue ; } JoinResult :: Changed => { // The pre changed. Schedule the next block. work_list . push ( * next_block_id ) ; } JoinResult :: Error => { // This join produced an error. Don't schedule the block. next_block_invariant . post = BlockPostcondition :: Error ; continue ; } } } None => { // Haven't visited the next block yet. Use the post of the current block as // its pre and schedule it. inv_map . insert ( * next_block_id , BlockInvariant { pre : state . clone ( ) , post : BlockPostcondition :: Success , } , ) ; work_list . push ( * next_block_id ) ; } } } } inv_map }
Analyze procedure local@function_view starting from pre-state local@initial_state.
Analyze procedure local@function_view starting from pre - state local@initial_state .
&mut self
initial_state
Self::State
function_view
&FunctionDefinitionView<CompiledModule>
cfg
&VMControlFlowGraph