pub fn fixed_point_forward_options<'f, Analysis, State>(
    analysis: Analysis,
    function: &'f il::Function,
    force: bool,
) -> Result<HashMap<il::ProgramLocation, State>>
where
    Analysis: FixedPointAnalysis<'f, State>,
    State: 'f + Clone + Debug + PartialOrd,
{
    let mut states: HashMap<il::ProgramLocation, State> = HashMap::new();

    let mut queue: VecDeque<il::ProgramLocation> = VecDeque::new();

    // Find the entry block to the function.
    let entry_index = function
        .control_flow_graph()
        .entry()
        .ok_or("Function's control flow graph must have entry")?;
    let entry_block = function.control_flow_graph().block(entry_index)?;

    match entry_block.instructions().first() {
        Some(instruction) => {
            let location = il::RefFunctionLocation::Instruction(entry_block, instruction);
            let location = il::RefProgramLocation::new(function, location);
            queue.push_back(location.into());
        }
        None => {
            let location = il::RefFunctionLocation::EmptyBlock(entry_block);
            let location = il::RefProgramLocation::new(function, location);
            queue.push_back(location.into());
        }
    }

    while !queue.is_empty() {
        let location = queue.pop_front().unwrap();

        // TODO this should not be an unwrap
        let location = location.function_location().apply(function).unwrap();

        let location = il::RefProgramLocation::new(function, location);

        let location_predecessors = location.backward()?;

        let state =
            location_predecessors
                .into_iter()
                .fold(None, |s, p| match states.get(&p.into()) {
                    Some(in_state) => match s {
                        Some(s) => Some(analysis.join(s, in_state).unwrap()),
                        None => Some(in_state.clone()),
                    },
                    None => s,
                });

        let mut state = analysis.trans(location.clone(), state)?;

        if let Some(in_state) = states.get(&location.clone().into()) {
            let ordering = match state.partial_cmp(in_state) {
                Some(ordering) => match ordering {
                    ::std::cmp::Ordering::Less => Some("less"),
                    ::std::cmp::Ordering::Equal => {
                        continue;
                    }
                    ::std::cmp::Ordering::Greater => None,
                },
                None => Some("no relation"),
            };
            if force {
                state = analysis.join(state, in_state)?;
            } else if let Some(ordering) = ordering {
                bail!(
                    "Found a state which was not >= previous state (it was {}) @ {}",
                    ordering,
                    location
                );
            }
        }

        states.insert(location.clone().into(), state);

        for successor in location.forward()? {
            if !queue.contains(&successor.clone().into()) {
                queue.push_back(successor.into());
            }
        }
    }

    Ok(states)
}
/// A forward, work-list data-flow analysis algorithm.
///
/// When force is true, the partial order over inputs is forced by joining
/// states which do not inherently enforce the partial order.
A forward, work-list data-flow analysis algorithm.
When force is true, the partial order over inputs is forced by joining
states which do not inherently enforce the partial order.
A forward work - list data - flow analysis algorithm . When force is true the partial order over inputs is forced by joining states which do not inherently enforce the partial order .
pub fn fixed_point_forward_options<'f, Analysis, State>(
    analysis: Analysis,
    function: &'f il::Function,
    force: bool,
) -> Result<HashMap<il::ProgramLocation, State>>
where
    Analysis: FixedPointAnalysis<'f, State>,
    State: 'f + Clone + Debug + PartialOrd,
{
    let mut states: HashMap<il::ProgramLocation, State> = HashMap::new();
    let mut queue: VecDeque<il::ProgramLocation> = VecDeque::new();
    // Find the entry block to the function.
    let entry_index = function
        .control_flow_graph()
        .entry()
        .ok_or("Function's control flow graph must have entry")?;
    let entry_block = function.control_flow_graph().block(entry_index)?;
    match entry_block.instructions().first() {
        Some(instruction) => {
            let location = il::RefFunctionLocation::Instruction(entry_block, instruction);
            let location = il::RefProgramLocation::new(function, location);
            queue.push_back(location.into());
        }
        None => {
            let location = il::RefFunctionLocation::EmptyBlock(entry_block);
            let location = il::RefProgramLocation::new(function, location);
            queue.push_back(location.into());
        }
    }
    while !queue.is_empty() {
        let location = queue.pop_front().unwrap();
        // TODO this should not be an unwrap
        let location = location.function_location().apply(function).unwrap();
        let location = il::RefProgramLocation::new(function, location);
        let location_predecessors = location.backward()?;
        let state =
            location_predecessors
                .into_iter()
                .fold(None, |s, p| match states.get(&p.into()) {
                    Some(in_state) => match s {
                        Some(s) => Some(analysis.join(s, in_state).unwrap()),
                        None => Some(in_state.clone()),
                    },
                    None => s,
                });
        let mut state = analysis.trans(location.clone(), state)?;
        if let Some(in_state) = states.get(&location.clone().into()) {
            let ordering = match state.partial_cmp(in_state) {
                Some(ordering) => match ordering {
                    ::std::cmp::Ordering::Less => Some("less"),
                    ::std::cmp::Ordering::Equal => {
                        continue;
                    }
                    ::std::cmp::Ordering::Greater => None,
                },
                None => Some("no relation"),
            };
            if force {
                state = analysis.join(state, in_state)?;
            } else if let Some(ordering) = ordering {
                bail!(
                    "Found a state which was not >= previous state (it was {}) @ {}",
                    ordering,
                    location
                );
            }
        }
        states.insert(location.clone().into(), state);
        for successor in location.forward()? {
            if !queue.contains(&successor.clone().into()) {
                queue.push_back(successor.into());
            }
        }
    }
    Ok(states)
}
pub fn fixed_point_forward_options < ' f , Analysis , State > ( analysis : Analysis , function : & ' f il :: Function , force : bool , ) -> Result < HashMap < il :: ProgramLocation , State > > where Analysis : FixedPointAnalysis < ' f , State > , State : ' f + Clone + Debug + PartialOrd , { let mut states : HashMap < il :: ProgramLocation , State > = HashMap :: new ( ) ; let mut queue : VecDeque < il :: ProgramLocation > = VecDeque :: new ( ) ; // Find the entry block to the function. let entry_index = function . control_flow_graph ( ) . entry ( ) . ok_or ( " " ) ? ; let entry_block = function . control_flow_graph ( ) . block ( entry_index ) ? ; match entry_block . instructions ( ) . first ( ) { Some ( instruction ) => { let location = il :: RefFunctionLocation :: Instruction ( entry_block , instruction ) ; let location = il :: RefProgramLocation :: new ( function , location ) ; queue . push_back ( location . into ( ) ) ; } None => { let location = il :: RefFunctionLocation :: EmptyBlock ( entry_block ) ; let location = il :: RefProgramLocation :: new ( function , location ) ; queue . push_back ( location . into ( ) ) ; } } while ! queue . is_empty ( ) { let location = queue . pop_front ( ) . unwrap ( ) ; // TODO this should not be an unwrap let location = location . function_location ( ) . apply ( function ) . unwrap ( ) ; let location = il :: RefProgramLocation :: new ( function , location ) ; let location_predecessors = location . backward ( ) ? ; let state = location_predecessors . into_iter ( ) . fold ( None , | s , p | match states . get ( & p . into ( ) ) { Some ( in_state ) => match s { Some ( s ) => Some ( analysis . join ( s , in_state ) . unwrap ( ) ) , None => Some ( in_state . clone ( ) ) , } , None => s , } ) ; let mut state = analysis . trans ( location . clone ( ) , state ) ? ; if let Some ( in_state ) = states . get ( & location . clone ( ) . into ( ) ) { let ordering = match state . partial_cmp ( in_state ) { Some ( ordering ) => match ordering { :: std :: cmp :: Ordering :: Less => Some ( " " ) , :: std :: cmp :: Ordering :: Equal => { continue ; } :: std :: cmp :: Ordering :: Greater => None , } , None => Some ( " " ) , } ; if force { state = analysis . join ( state , in_state ) ? ; } else if let Some ( ordering ) = ordering { bail ! ( " " ordering location ) ; } } states . insert ( location . clone ( ) . into ( ) , state ) ; for successor in location . forward ( ) ? { if ! queue . contains ( & successor . clone ( ) . into ( ) ) { queue . push_back ( successor . into ( ) ) ; } } } Ok ( states ) }
A forward, work-list data-flow analysis algorithm.
A forward work - list data - flow analysis algorithm .
analysis
Analysis
function
&'f il::Function
force
bool
analysis
Analysis
function
&'f il::Function
force
bool