fn generic_frontward_analysis(
    ssa: &SSAStorage,
    sp_name: String,
    bp_name: String,
    is_global: bool,
) -> HashMap<LValueRef, i64> {
    let mut stack_offset: HashMap<LValueRef, i64> = HashMap::new();
    {
        let reg_state = registers_in_err!(ssa, entry_node_err!(ssa));

        let nodes = ssa.operands_of(reg_state);
        for node in &nodes {
            if ssa.comment(*node) != Some(sp_name.clone()) {
                continue;
            }
            stack_offset.insert(*node, 0);
            break;
        }
    }

    let nodes = if is_global {
        let mut nodes: Vec<LValueRef> = Vec::new();
        let mut walker = ssa.bfs_walk().nodes;
        while let Some(node) = walker.pop_front() {
            nodes.push(node);
        }
        nodes
    } else {
        let blocks = ssa.succs_of(entry_node_err!(ssa));
        if blocks.len() != 1 {
            radeco_err!("blocks.len() should return 1");
        }
        ssa.exprs_in(blocks[0])
    };

    for node in &nodes {
        if let Some(opc) = ssa.opcode(*node) {
            if opc == MOpcode::OpCall && !is_global {
                break;
            }

            match opc {
                MOpcode::OpZeroExt(_) | MOpcode::OpNarrow(_) => {
                    let args = ssa.operands_of(*node);
                    if stack_offset.contains_key(&args[0]) {
                        let num = stack_offset
                            .get(&args[0])
                            .unwrap_or_else(|| {
                                radeco_err!("Stack offset not found");
                                &0
                            })
                            .clone();
                        stack_offset.insert(*node, num);
                        continue;
                    }
                }
                _ => {}
            }

            // We only consider SP/BP.
            if ssa.registers(*node).is_empty() {
                continue;
            }
            let regnames = ssa.registers(*node);
            if !regnames.contains(&sp_name) && !regnames.contains(&bp_name) {
                continue;
            }

            let args = ssa.operands_of(*node);
            if args.len() != 2 {
                continue;
            }

            let const_arg: i64;
            let opcode_arg: i64;
            match opc {
                MOpcode::OpSub => {
                    const_arg = 1;
                    opcode_arg = 0;
                }
                MOpcode::OpAdd => {
                    const_arg = 0;
                    opcode_arg = 1;
                }
                // Some compiler will initial SP with and 0xfffffff0
                MOpcode::OpAnd => {
                    stack_offset.clear();
                    stack_offset.insert(*node, 0);
                    continue;
                }
                _ => {
                    continue;
                }
            }
            if ssa.opcode(args[opcode_arg as usize]).is_some()
                || ssa.comment(args[opcode_arg as usize]).is_some()
                || (ssa.is_phi(args[opcode_arg as usize]) && is_global)
            {
                if let Some(MOpcode::OpConst(num)) = ssa.opcode(args[const_arg as usize]) {
                    // TODO: Some special cases may by not consided
                    if !stack_offset.contains_key(&args[opcode_arg as usize]) {
                        continue;
                    }
                    let base = stack_offset
                        .get(&args[opcode_arg as usize])
                        .unwrap_or_else(|| {
                            radeco_err!("Stack offset not found");
                            &0
                        })
                        .clone() as i64;
                    stack_offset.insert(*node, base + (opcode_arg - const_arg) * (num as i64));
                    continue;
                }
            }
            radeco_warn!("No SP/BP algorithm Found!");
        }

        // If we are doing a global search, we should consider phi node.
        if ssa.is_phi(*node) && is_global {
            let args = ssa.operands_of(*node);
            let mut nums: Vec<i64> = Vec::new();
            for arg in &args {
                if stack_offset.contains_key(arg) {
                    let num = stack_offset
                        .get(arg)
                        .unwrap_or_else(|| {
                            radeco_err!("Stack offset not found");
                            &0
                        })
                        .clone();
                    if !nums.contains(&num) {
                        nums.push(num);
                    }
                }
            }
            if nums.len() == 1 {
                stack_offset.insert(*node, nums[0]);
            }
        }
    }
    radeco_trace!("CallFixer|Stack_offset: {:?}", stack_offset);
    stack_offset
}
// Analyze stack offset frontward, for the first block or whole SSA.
Analyze stack offset frontward, for the first block or whole SSA.
Analyze stack offset frontward for the first block or whole SSA .
fn generic_frontward_analysis(
    ssa: &SSAStorage,
    sp_name: String,
    bp_name: String,
    is_global: bool,
) -> HashMap<LValueRef, i64> {
    let mut stack_offset: HashMap<LValueRef, i64> = HashMap::new();
    {
        let reg_state = registers_in_err!(ssa, entry_node_err!(ssa));
        let nodes = ssa.operands_of(reg_state);
        for node in &nodes {
            if ssa.comment(*node) != Some(sp_name.clone()) {
                continue;
            }
            stack_offset.insert(*node, 0);
            break;
        }
    }
    let nodes = if is_global {
        let mut nodes: Vec<LValueRef> = Vec::new();
        let mut walker = ssa.bfs_walk().nodes;
        while let Some(node) = walker.pop_front() {
            nodes.push(node);
        }
        nodes
    } else {
        let blocks = ssa.succs_of(entry_node_err!(ssa));
        if blocks.len() != 1 {
            radeco_err!("blocks.len() should return 1");
        }
        ssa.exprs_in(blocks[0])
    };
    for node in &nodes {
        if let Some(opc) = ssa.opcode(*node) {
            if opc == MOpcode::OpCall && !is_global {
                break;
            }
            match opc {
                MOpcode::OpZeroExt(_) | MOpcode::OpNarrow(_) => {
                    let args = ssa.operands_of(*node);
                    if stack_offset.contains_key(&args[0]) {
                        let num = stack_offset
                            .get(&args[0])
                            .unwrap_or_else(|| {
                                radeco_err!("Stack offset not found");
                                &0
                            })
                            .clone();
                        stack_offset.insert(*node, num);
                        continue;
                    }
                }
                _ => {}
            }
            // We only consider SP/BP.
            if ssa.registers(*node).is_empty() {
                continue;
            }
            let regnames = ssa.registers(*node);
            if !regnames.contains(&sp_name) && !regnames.contains(&bp_name) {
                continue;
            }
            let args = ssa.operands_of(*node);
            if args.len() != 2 {
                continue;
            }
            let const_arg: i64;
            let opcode_arg: i64;
            match opc {
                MOpcode::OpSub => {
                    const_arg = 1;
                    opcode_arg = 0;
                }
                MOpcode::OpAdd => {
                    const_arg = 0;
                    opcode_arg = 1;
                }
                // Some compiler will initial SP with and 0xfffffff0
                MOpcode::OpAnd => {
                    stack_offset.clear();
                    stack_offset.insert(*node, 0);
                    continue;
                }
                _ => {
                    continue;
                }
            }
            if ssa.opcode(args[opcode_arg as usize]).is_some()
                || ssa.comment(args[opcode_arg as usize]).is_some()
                || (ssa.is_phi(args[opcode_arg as usize]) && is_global)
            {
                if let Some(MOpcode::OpConst(num)) = ssa.opcode(args[const_arg as usize]) {
                    // TODO: Some special cases may by not consided
                    if !stack_offset.contains_key(&args[opcode_arg as usize]) {
                        continue;
                    }
                    let base = stack_offset
                        .get(&args[opcode_arg as usize])
                        .unwrap_or_else(|| {
                            radeco_err!("Stack offset not found");
                            &0
                        })
                        .clone() as i64;
                    stack_offset.insert(*node, base + (opcode_arg - const_arg) * (num as i64));
                    continue;
                }
            }
            radeco_warn!("No SP/BP algorithm Found!");
        }
        // If we are doing a global search, we should consider phi node.
        if ssa.is_phi(*node) && is_global {
            let args = ssa.operands_of(*node);
            let mut nums: Vec<i64> = Vec::new();
            for arg in &args {
                if stack_offset.contains_key(arg) {
                    let num = stack_offset
                        .get(arg)
                        .unwrap_or_else(|| {
                            radeco_err!("Stack offset not found");
                            &0
                        })
                        .clone();
                    if !nums.contains(&num) {
                        nums.push(num);
                    }
                }
            }
            if nums.len() == 1 {
                stack_offset.insert(*node, nums[0]);
            }
        }
    }
    radeco_trace!("CallFixer|Stack_offset: {:?}", stack_offset);
    stack_offset
}
fn generic_frontward_analysis ( ssa : & SSAStorage , sp_name : String , bp_name : String , is_global : bool , ) -> HashMap < LValueRef , i64 > { let mut stack_offset : HashMap < LValueRef , i64 > = HashMap :: new ( ) ; { let reg_state = registers_in_err ! ( ssa entry_node_err ( ssa ) ) ; let nodes = ssa . operands_of ( reg_state ) ; for node in & nodes { if ssa . comment ( * node ) != Some ( sp_name . clone ( ) ) { continue ; } stack_offset . insert ( * node , 0 ) ; break ; } } let nodes = if is_global { let mut nodes : Vec < LValueRef > = Vec :: new ( ) ; let mut walker = ssa . bfs_walk ( ) . nodes ; while let Some ( node ) = walker . pop_front ( ) { nodes . push ( node ) ; } nodes } else { let blocks = ssa . succs_of ( entry_node_err ! ( ssa ) ) ; if blocks . len ( ) != 1 { radeco_err ! ( " " ) ; } ssa . exprs_in ( blocks [ 0 ] ) } ; for node in & nodes { if let Some ( opc ) = ssa . opcode ( * node ) { if opc == MOpcode :: OpCall && ! is_global { break ; } match opc { MOpcode :: OpZeroExt ( _ ) | MOpcode :: OpNarrow ( _ ) => { let args = ssa . operands_of ( * node ) ; if stack_offset . contains_key ( & args [ 0 ] ) { let num = stack_offset . get ( & args [ 0 ] ) . unwrap_or_else ( | | { radeco_err ! ( " " ) ; & 0 } ) . clone ( ) ; stack_offset . insert ( * node , num ) ; continue ; } } _ => { } } // We only consider SP/BP. if ssa . registers ( * node ) . is_empty ( ) { continue ; } let regnames = ssa . registers ( * node ) ; if ! regnames . contains ( & sp_name ) && ! regnames . contains ( & bp_name ) { continue ; } let args = ssa . operands_of ( * node ) ; if args . len ( ) != 2 { continue ; } let const_arg : i64 ; let opcode_arg : i64 ; match opc { MOpcode :: OpSub => { const_arg = 1 ; opcode_arg = 0 ; } MOpcode :: OpAdd => { const_arg = 0 ; opcode_arg = 1 ; } // Some compiler will initial SP with and 0xfffffff0 MOpcode :: OpAnd => { stack_offset . clear ( ) ; stack_offset . insert ( * node , 0 ) ; continue ; } _ => { continue ; } } if ssa . opcode ( args [ opcode_arg as usize ] ) . is_some ( ) || ssa . comment ( args [ opcode_arg as usize ] ) . is_some ( ) || ( ssa . is_phi ( args [ opcode_arg as usize ] ) && is_global ) { if let Some ( MOpcode :: OpConst ( num ) ) = ssa . opcode ( args [ const_arg as usize ] ) { // TODO: Some special cases may by not consided if ! stack_offset . contains_key ( & args [ opcode_arg as usize ] ) { continue ; } let base = stack_offset . get ( & args [ opcode_arg as usize ] ) . unwrap_or_else ( | | { radeco_err ! ( " " ) ; & 0 } ) . clone ( ) as i64 ; stack_offset . insert ( * node , base + ( opcode_arg - const_arg ) * ( num as i64 ) ) ; continue ; } } radeco_warn ! ( " " ) ; } // If we are doing a global search, we should consider phi node. if ssa . is_phi ( * node ) && is_global { let args = ssa . operands_of ( * node ) ; let mut nums : Vec < i64 > = Vec :: new ( ) ; for arg in & args { if stack_offset . contains_key ( arg ) { let num = stack_offset . get ( arg ) . unwrap_or_else ( | | { radeco_err ! ( " " ) ; & 0 } ) . clone ( ) ; if ! nums . contains ( & num ) { nums . push ( num ) ; } } } if nums . len ( ) == 1 { stack_offset . insert ( * node , nums [ 0 ] ) ; } } } radeco_trace ! ( " " stack_offset ) ; stack_offset }
Analyze stack offset frontward, for the first block or whole SSA.
Analyze stack offset frontward for the first block or whole SSA .
ssa
&SSAStorage
sp_name
String
bp_name
String
is_global
bool
ssa
&SSAStorage
sp_name
String
bp_name
String
is_global
bool