pub fn mem_finalize(
    insn_off: CodeOffset,
    mem: &AMode,
    state: &EmitState,
) -> (SmallVec<[Inst; 4]>, AMode) {
    match mem {
        &AMode::RegOffset(_, off, ty)
        | &AMode::SPOffset(off, ty)
        | &AMode::FPOffset(off, ty)
        | &AMode::NominalSPOffset(off, ty) => {
            let basereg = match mem {
                &AMode::RegOffset(reg, _, _) => reg,
                &AMode::SPOffset(..) | &AMode::NominalSPOffset(..) => stack_reg(),
                &AMode::FPOffset(..) => fp_reg(),
                _ => unreachable!(),
            };
            let adj = match mem {
                &AMode::NominalSPOffset(..) => {
                    debug!(
                        "mem_finalize: nominal SP offset {} + adj {} -> {}",
                        off,
                        state.virtual_sp_offset,
                        off + state.virtual_sp_offset
                    );
                    state.virtual_sp_offset
                }
                _ => 0,
            };
            let off = off + adj;

            if let Some(simm9) = SImm9::maybe_from_i64(off) {
                let mem = AMode::Unscaled(basereg, simm9);
                (smallvec![], mem)
            } else if let Some(uimm12s) = UImm12Scaled::maybe_from_i64(off, ty) {
                let mem = AMode::UnsignedOffset(basereg, uimm12s);
                (smallvec![], mem)
            } else {
                let tmp = writable_spilltmp_reg();
                let mut const_insts = Inst::load_constant(tmp, off as u64);
                // N.B.: we must use AluRRRExtend because AluRRR uses the "shifted register" form
                // (AluRRRShift) instead, which interprets register 31 as the zero reg, not SP. SP
                // is a valid base (for SPOffset) which we must handle here.
                // Also, SP needs to be the first arg, not second.
                let add_inst = Inst::AluRRRExtend {
                    alu_op: ALUOp::Add64,
                    rd: tmp,
                    rn: basereg,
                    rm: tmp.to_reg(),
                    extendop: ExtendOp::UXTX,
                };
                const_insts.push(add_inst);
                (const_insts, AMode::reg(tmp.to_reg()))
            }
        }

        &AMode::Label(ref label) => {
            let off = memlabel_finalize(insn_off, label);
            (smallvec![], AMode::Label(MemLabel::PCRel(off)))
        }

        _ => (smallvec![], mem.clone()),
    }
}
/// Memory addressing mode finalization: convert "special" modes (e.g.,
/// generic arbitrary stack offset) into real addressing modes, possibly by
/// emitting some helper instructions that come immediately before the use
/// of this amode.
Memory addressing mode finalization: convert "special" modes  into real addressing modes, possibly by
emitting some helper instructions that come immediately before the use
of this amode.
Memory addressing mode finalization : convert " special " modes into real addressing modes possibly by emitting some helper instructions that come immediately before the use of this amode .
pub fn mem_finalize(
    insn_off: CodeOffset,
    mem: &AMode,
    state: &EmitState,
) -> (SmallVec<[Inst; 4]>, AMode) {
    match mem {
        &AMode::RegOffset(_, off, ty)
        | &AMode::SPOffset(off, ty)
        | &AMode::FPOffset(off, ty)
        | &AMode::NominalSPOffset(off, ty) => {
            let basereg = match mem {
                &AMode::RegOffset(reg, _, _) => reg,
                &AMode::SPOffset(..) | &AMode::NominalSPOffset(..) => stack_reg(),
                &AMode::FPOffset(..) => fp_reg(),
                _ => unreachable!(),
            };
            let adj = match mem {
                &AMode::NominalSPOffset(..) => {
                    debug!(
                        "mem_finalize: nominal SP offset {} + adj {} -> {}",
                        off,
                        state.virtual_sp_offset,
                        off + state.virtual_sp_offset
                    );
                    state.virtual_sp_offset
                }
                _ => 0,
            };
            let off = off + adj;
            if let Some(simm9) = SImm9::maybe_from_i64(off) {
                let mem = AMode::Unscaled(basereg, simm9);
                (smallvec![], mem)
            } else if let Some(uimm12s) = UImm12Scaled::maybe_from_i64(off, ty) {
                let mem = AMode::UnsignedOffset(basereg, uimm12s);
                (smallvec![], mem)
            } else {
                let tmp = writable_spilltmp_reg();
                let mut const_insts = Inst::load_constant(tmp, off as u64);
                // N.B.: we must use AluRRRExtend because AluRRR uses the "shifted register" form
                // (AluRRRShift) instead, which interprets register 31 as the zero reg, not SP. SP
                // is a valid base (for SPOffset) which we must handle here.
                // Also, SP needs to be the first arg, not second.
                let add_inst = Inst::AluRRRExtend {
                    alu_op: ALUOp::Add64,
                    rd: tmp,
                    rn: basereg,
                    rm: tmp.to_reg(),
                    extendop: ExtendOp::UXTX,
                };
                const_insts.push(add_inst);
                (const_insts, AMode::reg(tmp.to_reg()))
            }
        }
        &AMode::Label(ref label) => {
            let off = memlabel_finalize(insn_off, label);
            (smallvec![], AMode::Label(MemLabel::PCRel(off)))
        }
        _ => (smallvec![], mem.clone()),
    }
}
pub fn mem_finalize ( insn_off : CodeOffset , mem : & AMode , state : & EmitState , ) -> ( SmallVec < [ Inst ; 4 ] > , AMode ) { match mem { & AMode :: RegOffset ( _ , off , ty ) | & AMode :: SPOffset ( off , ty ) | & AMode :: FPOffset ( off , ty ) | & AMode :: NominalSPOffset ( off , ty ) => { let basereg = match mem { & AMode :: RegOffset ( reg , _ , _ ) => reg , & AMode :: SPOffset ( .. ) | & AMode :: NominalSPOffset ( .. ) => stack_reg ( ) , & AMode :: FPOffset ( .. ) => fp_reg ( ) , _ => unreachable ! ( ) , } ; let adj = match mem { & AMode :: NominalSPOffset ( .. ) => { debug ! ( " " off state virtual_sp_offset off state virtual_sp_offset ) ; state . virtual_sp_offset } _ => 0 , } ; let off = off + adj ; if let Some ( simm9 ) = SImm9 :: maybe_from_i64 ( off ) { let mem = AMode :: Unscaled ( basereg , simm9 ) ; ( smallvec ! [ ] , mem ) } else if let Some ( uimm12s ) = UImm12Scaled :: maybe_from_i64 ( off , ty ) { let mem = AMode :: UnsignedOffset ( basereg , uimm12s ) ; ( smallvec ! [ ] , mem ) } else { let tmp = writable_spilltmp_reg ( ) ; let mut const_insts = Inst :: load_constant ( tmp , off as u64 ) ; // N.B.: we must use AluRRRExtend because AluRRR uses the "shifted register" form // (AluRRRShift) instead, which interprets register 31 as the zero reg, not SP. SP // is a valid base (for SPOffset) which we must handle here. // Also, SP needs to be the first arg, not second. let add_inst = Inst :: AluRRRExtend { alu_op : ALUOp :: Add64 , rd : tmp , rn : basereg , rm : tmp . to_reg ( ) , extendop : ExtendOp :: UXTX , } ; const_insts . push ( add_inst ) ; ( const_insts , AMode :: reg ( tmp . to_reg ( ) ) ) } } & AMode :: Label ( ref label ) => { let off = memlabel_finalize ( insn_off , label ) ; ( smallvec ! [ ] , AMode :: Label ( MemLabel :: PCRel ( off ) ) ) } _ => ( smallvec ! [ ] , mem . clone ( ) ) , } }
Memory addressing mode finalization: convert "special" modes (e.g.,
generic arbitrary stack offset) into real addressing modes, possibly by
emitting some helper instructions that come immediately before the use
of this amode.
Memory addressing mode finalization : convert " special " modes ( e . g . generic arbitrary stack offset ) into real addressing modes possibly by emitting some helper instructions that come immediately before the use of this amode .
insn_off
CodeOffset
mem
&AMode
state
&EmitState
insn_off
CodeOffset
mem
&AMode
state
&EmitState