fn analysis_exit_load(
        &self,
        ssa: &SSAStorage,
        exit_offset: HashMap<LValueRef, i64>,
    ) -> HashMap<String, i64> {
        let mut exit_load: HashMap<String, i64> = HashMap::new();
        let mut worklist: VecDeque<LValueRef> = VecDeque::new();
        let mut visited: HashSet<LValueRef> = HashSet::new();

        let reg_state = registers_in_err!(ssa, exit_node_err!(ssa));
        worklist.push_back(reg_state);

        while let Some(node) = worklist.pop_front() {
            if !visited.contains(&node) {
                visited.insert(node);
            } else {
                continue;
            }
            radeco_trace!("CallFixer|Pop {:?} with {:?}", node, ssa.node_data(node));
            radeco_trace!("CallFixer|Register is {:?}", ssa.registers(node));
            let args = ssa.operands_of(node);
            for arg in args {
                if ssa.registers(arg).is_empty() {
                    continue;
                }

                if ssa.is_phi(arg) {
                    worklist.push_back(arg);
                    continue;
                }
                match ssa.opcode(arg) {
                    // OpNarrow and OpWiden are transfromed data
                    Some(MOpcode::OpNarrow(_)) | Some(MOpcode::OpZeroExt(_)) => {
                        worklist.push_back(arg);
                    }
                    Some(MOpcode::OpLoad) => {
                        let operands = ssa.operands_of(arg);
                        if !exit_offset.contains_key(&operands[1]) {
                            continue;
                        }

                        let base = exit_offset
                            .get(&operands[1])
                            .unwrap_or_else(|| {
                                radeco_err!("Invalid operands: {:?}", operands[1]);
                                &0
                            })
                            .clone();
                        let names = ssa.registers(arg);
                        for name in names {
                            radeco_trace!("CallFixer|Found {:?} with {:?}", name, base);
                            if exit_load.contains_key(&name) {
                                continue;
                            }
                            exit_load.insert(name, base);
                        }
                    }
                    _ => {}
                }
            }
        }

        radeco_trace!("CallFixer|Exit_load: {:?}", exit_load);
        exit_load
    }
// Analyze exit block's load for preserved registers
Analyze exit block's load for preserved registers
Analyze exit block ' s load for preserved registers
fn analysis_exit_load(
        &self,
        ssa: &SSAStorage,
        exit_offset: HashMap<LValueRef, i64>,
    ) -> HashMap<String, i64> {
        let mut exit_load: HashMap<String, i64> = HashMap::new();
        let mut worklist: VecDeque<LValueRef> = VecDeque::new();
        let mut visited: HashSet<LValueRef> = HashSet::new();
        let reg_state = registers_in_err!(ssa, exit_node_err!(ssa));
        worklist.push_back(reg_state);
        while let Some(node) = worklist.pop_front() {
            if !visited.contains(&node) {
                visited.insert(node);
            } else {
                continue;
            }
            radeco_trace!("CallFixer|Pop {:?} with {:?}", node, ssa.node_data(node));
            radeco_trace!("CallFixer|Register is {:?}", ssa.registers(node));
            let args = ssa.operands_of(node);
            for arg in args {
                if ssa.registers(arg).is_empty() {
                    continue;
                }
                if ssa.is_phi(arg) {
                    worklist.push_back(arg);
                    continue;
                }
                match ssa.opcode(arg) {
                    // OpNarrow and OpWiden are transfromed data
                    Some(MOpcode::OpNarrow(_)) | Some(MOpcode::OpZeroExt(_)) => {
                        worklist.push_back(arg);
                    }
                    Some(MOpcode::OpLoad) => {
                        let operands = ssa.operands_of(arg);
                        if !exit_offset.contains_key(&operands[1]) {
                            continue;
                        }
                        let base = exit_offset
                            .get(&operands[1])
                            .unwrap_or_else(|| {
                                radeco_err!("Invalid operands: {:?}", operands[1]);
                                &0
                            })
                            .clone();
                        let names = ssa.registers(arg);
                        for name in names {
                            radeco_trace!("CallFixer|Found {:?} with {:?}", name, base);
                            if exit_load.contains_key(&name) {
                                continue;
                            }
                            exit_load.insert(name, base);
                        }
                    }
                    _ => {}
                }
            }
        }
        radeco_trace!("CallFixer|Exit_load: {:?}", exit_load);
        exit_load
    }
fn analysis_exit_load ( & self , ssa : & SSAStorage , exit_offset : HashMap < LValueRef , i64 > , ) -> HashMap < String , i64 > { let mut exit_load : HashMap < String , i64 > = HashMap :: new ( ) ; let mut worklist : VecDeque < LValueRef > = VecDeque :: new ( ) ; let mut visited : HashSet < LValueRef > = HashSet :: new ( ) ; let reg_state = registers_in_err ! ( ssa exit_node_err ( ssa ) ) ; worklist . push_back ( reg_state ) ; while let Some ( node ) = worklist . pop_front ( ) { if ! visited . contains ( & node ) { visited . insert ( node ) ; } else { continue ; } radeco_trace ! ( " " node ssa node_data ( node ) ) ; radeco_trace ! ( " " ssa registers ( node ) ) ; let args = ssa . operands_of ( node ) ; for arg in args { if ssa . registers ( arg ) . is_empty ( ) { continue ; } if ssa . is_phi ( arg ) { worklist . push_back ( arg ) ; continue ; } match ssa . opcode ( arg ) { // OpNarrow and OpWiden are transfromed data Some ( MOpcode :: OpNarrow ( _ ) ) | Some ( MOpcode :: OpZeroExt ( _ ) ) => { worklist . push_back ( arg ) ; } Some ( MOpcode :: OpLoad ) => { let operands = ssa . operands_of ( arg ) ; if ! exit_offset . contains_key ( & operands [ 1 ] ) { continue ; } let base = exit_offset . get ( & operands [ 1 ] ) . unwrap_or_else ( | | { radeco_err ! ( " " operands [ 1 ] ) ; & 0 } ) . clone ( ) ; let names = ssa . registers ( arg ) ; for name in names { radeco_trace ! ( " " name base ) ; if exit_load . contains_key ( & name ) { continue ; } exit_load . insert ( name , base ) ; } } _ => { } } } } radeco_trace ! ( " " exit_load ) ; exit_load }
Analyze exit block's load for preserved registers
Analyze exit block ' s load for preserved registers
&self
ssa
&SSAStorage
exit_offset
HashMap<LValueRef, i64>
&self
ssa
&SSAStorage
exit_offset
HashMap<LValueRef, i64>