/// Collect all addends that feed into an address computation, with extend-modes
/// on each.  Note that a load/store may have multiple address components (and
/// the CLIF semantics are that these components are added to form the final
/// address), but sometimes the CLIF that we receive still has arguments that
/// refer to `iadd` instructions. We also want to handle uextend/sextend below
/// the add(s).
///
/// We match any 64-bit add (and descend into its inputs), and we match any
/// 32-to-64-bit sign or zero extension. The returned addend-list will use
/// NarrowValueMode values to indicate how to extend each input:
///
/// - NarrowValueMode::None: the associated input is 64 bits wide; no extend.
/// - NarrowValueMode::SignExtend64: the associated input is 32 bits wide;
///                                  do a sign-extension.
/// - NarrowValueMode::ZeroExtend64: the associated input is 32 bits wide;
///                                  do a zero-extension.
///
/// We do not descend further into the inputs of extensions, because supporting
/// (e.g.) a 32-bit add that is later extended would require additional masking
/// of high-order bits, which is too complex. So, in essence, we descend any
/// number of adds from the roots, collecting all 64-bit address addends; then
/// possibly support extensions at these leaves.
Collect all addends that feed into an address computation, with extend-modes
on each.  Note that a load/store may have multiple address components (and
the CLIF semantics are that these components are added to form the final
address), but sometimes the CLIF that we receive still has arguments that
refer to `iadd` instructions. We also want to handle uextend/sextend below
the add(s).

We match any 64-bit add (and descend into its inputs), and we match any
32-to-64-bit sign or zero extension. The returned addend-list will use
NarrowValueMode values to indicate how to extend each input.

:None: the associated input is 64 bits wide; no extend.
NarrowValueMode::SignExtend64: the associated input is 32 bits wide;
do a sign-extension.
NarrowValueMode::ZeroExtend64: the associated input is 32 bits wide;
do a zero-extension.

We do not descend further into the inputs of extensions, because supporting
a 32-bit add that is later extended would require additional masking
of high-order bits, which is too complex. So, in essence, we descend any
number of adds from the roots, collecting all 64-bit address addends; then
possibly support extensions at these leaves.
Collect all addends that feed into an address computation with extend - modes on each . Note that a load / store may have multiple address components ( and the CLIF semantics are that these components are added to form the final address ) but sometimes the CLIF that we receive still has arguments that refer to ` iadd ` instructions . We also want to handle uextend / sextend below the add ( s ) . We match any 64 - bit add ( and descend into its inputs ) and we match any 32 - to - 64 - bit sign or zero extension . The returned addend - list will use NarrowValueMode values to indicate how to extend each input . : None : the associated input is 64 bits wide ; no extend . NarrowValueMode :: SignExtend64 : the associated input is 32 bits wide ; do a sign - extension . NarrowValueMode :: ZeroExtend64 : the associated input is 32 bits wide ; do a zero - extension . We do not descend further into the inputs of extensions because supporting a 32 - bit add that is later extended would require additional masking of high - order bits which is too complex . So in essence we descend any number of adds from the roots collecting all 64 - bit address addends ; then possibly support extensions at these leaves .
fn collect_address_addends<C: LowerCtx<I = Inst>>(
    ctx: &mut C,
    roots: &[InsnInput],
) -> (AddressAddend64List, AddressAddend32List, i64) {
    let mut result32: AddressAddend32List = SmallVec::new();
    let mut result64: AddressAddend64List = SmallVec::new();
    let mut offset: i64 = 0;
    let mut workqueue: SmallVec<[InsnInput; 4]> = roots.iter().cloned().collect();
    while let Some(input) = workqueue.pop() {
        debug_assert!(ty_bits(ctx.input_ty(input.insn, input.input)) == 64);
        if let Some((op, insn)) = maybe_input_insn_multi(
            ctx,
            input,
            &[
                Opcode::Uextend,
                Opcode::Sextend,
                Opcode::Iadd,
                Opcode::Iconst,
            ],
        ) {
            match op {
                Opcode::Uextend | Opcode::Sextend if ty_bits(ctx.input_ty(insn, 0)) == 32 => {
                    let extendop = if op == Opcode::Uextend {
                        ExtendOp::UXTW
                    } else {
                        ExtendOp::SXTW
                    };
                    let extendee_input = InsnInput { insn, input: 0 };
                    let reg = put_input_in_reg(ctx, extendee_input, NarrowValueMode::None);
                    result32.push((reg, extendop));
                }
                Opcode::Uextend | Opcode::Sextend => {
                    let reg = put_input_in_reg(ctx, input, NarrowValueMode::None);
                    result64.push(reg);
                }
                Opcode::Iadd => {
                    for input in 0..ctx.num_inputs(insn) {
                        let addend = InsnInput { insn, input };
                        workqueue.push(addend);
                    }
                }
                Opcode::Iconst => {
                    let value: i64 = ctx.get_constant(insn).unwrap() as i64;
                    offset += value;
                }
                _ => panic!("Unexpected opcode from maybe_input_insn_multi"),
            }
        } else {
            let reg = put_input_in_reg(ctx, input, NarrowValueMode::ZeroExtend64);
            result64.push(reg);
        }
    }
    (result64, result32, offset)
}
fn collect_address_addends < C : LowerCtx < I = Inst > > ( ctx : & mut C , roots : & [ InsnInput ] , ) -> ( AddressAddend64List , AddressAddend32List , i64 ) { let mut result32 : AddressAddend32List = SmallVec :: new ( ) ; let mut result64 : AddressAddend64List = SmallVec :: new ( ) ; let mut offset : i64 = 0 ; let mut workqueue : SmallVec < [ InsnInput ; 4 ] > = roots . iter ( ) . cloned ( ) . collect ( ) ; while let Some ( input ) = workqueue . pop ( ) { debug_assert ! ( ty_bits ( ctx input_ty ( input insn input input ) ) 64 ) ; if let Some ( ( op , insn ) ) = maybe_input_insn_multi ( ctx , input , & [ Opcode :: Uextend , Opcode :: Sextend , Opcode :: Iadd , Opcode :: Iconst , ] , ) { match op { Opcode :: Uextend | Opcode :: Sextend if ty_bits ( ctx . input_ty ( insn , 0 ) ) == 32 => { let extendop = if op == Opcode :: Uextend { ExtendOp :: UXTW } else { ExtendOp :: SXTW } ; let extendee_input = InsnInput { insn , input : 0 } ; let reg = put_input_in_reg ( ctx , extendee_input , NarrowValueMode :: None ) ; result32 . push ( ( reg , extendop ) ) ; } Opcode :: Uextend | Opcode :: Sextend => { let reg = put_input_in_reg ( ctx , input , NarrowValueMode :: None ) ; result64 . push ( reg ) ; } Opcode :: Iadd => { for input in 0 .. ctx . num_inputs ( insn ) { let addend = InsnInput { insn , input } ; workqueue . push ( addend ) ; } } Opcode :: Iconst => { let value : i64 = ctx . get_constant ( insn ) . unwrap ( ) as i64 ; offset += value ; } _ => panic ! ( " " ) , } } else { let reg = put_input_in_reg ( ctx , input , NarrowValueMode :: ZeroExtend64 ) ; result64 . push ( reg ) ; } } ( result64 , result32 , offset ) }
Collect all addends that feed into an address computation, with extend-modes
on each.
Collect all addends that feed into an address computation with extend - modes on each .
ctx
&mut C
roots
&[InsnInput]