use std::cmp;

use rustc_abi::{Align, BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange};
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::packed::Pu128;
use rustc_hir::lang_items::LangItem;
use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER;
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
use rustc_span::{Span, Spanned};
use rustc_target::callconv::{ArgAbi, ArgAttributes, CastTarget, FnAbi, PassMode};
use tracing::{debug, info};

use super::operand::OperandRef;
use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
use super::place::{PlaceRef, PlaceValue};
use super::{CachedLlbb, FunctionCx, LocalRef};
use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization};
use crate::common::{self, IntPredicate};
use crate::errors::CompilerBuiltinsCannotCall;
use crate::traits::*;
use crate::{MemFlags, meth};

// Indicates if we are in the middle of merging a BB's successor into it. This
// can happen when BB jumps directly to its successor and the successor has no
// other predecessors.
#[derive(Debug, PartialEq)]
enum MergingSucc {
    False,
    True,
}

/// Indicates to the call terminator codegen whether a call
/// is a normal call or an explicit tail call.
#[derive(Debug, PartialEq)]
enum CallKind {
    Normal,
    Tail,
}

/// Used by `FunctionCx::codegen_terminator` for emitting common patterns
/// e.g., creating a basic block, calling a function, etc.
struct TerminatorCodegenHelper<'tcx> {
    bb: mir::BasicBlock,
    terminator: &'tcx mir::Terminator<'tcx>,
}

impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
    /// Returns the appropriate `Funclet` for the current funclet, if on MSVC,
    /// either already previously cached, or newly created, by `landing_pad_for`.
    fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
        &self,
        fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
    ) -> Option<&'b Bx::Funclet> {
        let cleanup_kinds = fx.cleanup_kinds.as_ref()?;
        let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb)?;
        // If `landing_pad_for` hasn't been called yet to create the `Funclet`,
        // it has to be now. This may not seem necessary, as RPO should lead
        // to all the unwind edges being visited (and so to `landing_pad_for`
        // getting called for them), before building any of the blocks inside
        // the funclet itself - however, if MIR contains edges that end up not
        // being needed in the LLVM IR after monomorphization, the funclet may
        // be unreachable, and we don't have yet a way to skip building it in
        // such an eventuality (which may be a better solution than this).
        if fx.funclets[funclet_bb].is_none() {
            fx.landing_pad_for(funclet_bb);
        }
        Some(
            fx.funclets[funclet_bb]
                .as_ref()
                .expect("landing_pad_for didn't also create funclets entry"),
        )
    }

    /// Get a basic block (creating it if necessary), possibly with cleanup
    /// stuff in it or next to it.
    fn llbb_with_cleanup<Bx: BuilderMethods<'a, 'tcx>>(
        &self,
        fx: &mut FunctionCx<'a, 'tcx, Bx>,
        target: mir::BasicBlock,
    ) -> Bx::BasicBlock {
        let (needs_landing_pad, is_cleanupret) = self.llbb_characteristics(fx, target);
        let mut lltarget = fx.llbb(target);
        if needs_landing_pad {
            lltarget = fx.landing_pad_for(target);
        }
        if is_cleanupret {
            // Cross-funclet jump - need a trampoline
            assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
            debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
            let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
            let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
            let mut trampoline_bx = Bx::build(fx.cx, trampoline_llbb);
            trampoline_bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
            trampoline_llbb
        } else {
            lltarget
        }
    }

    fn llbb_characteristics<Bx: BuilderMethods<'a, 'tcx>>(
        &self,
        fx: &mut FunctionCx<'a, 'tcx, Bx>,
        target: mir::BasicBlock,
    ) -> (bool, bool) {
        if let Some(ref cleanup_kinds) = fx.cleanup_kinds {
            let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb);
            let target_funclet = cleanup_kinds[target].funclet_bb(target);
            let (needs_landing_pad, is_cleanupret) = match (funclet_bb, target_funclet) {
                (None, None) => (false, false),
                (None, Some(_)) => (true, false),
                (Some(f), Some(t_f)) => (f != t_f, f != t_f),
                (Some(_), None) => {
                    let span = self.terminator.source_info.span;
                    span_bug!(span, "{:?} - jump out of cleanup?", self.terminator);
                }
            };
            (needs_landing_pad, is_cleanupret)
        } else {
            let needs_landing_pad = !fx.mir[self.bb].is_cleanup && fx.mir[target].is_cleanup;
            let is_cleanupret = false;
            (needs_landing_pad, is_cleanupret)
        }
    }

    fn funclet_br<Bx: BuilderMethods<'a, 'tcx>>(
        &self,
        fx: &mut FunctionCx<'a, 'tcx, Bx>,
        bx: &mut Bx,
        target: mir::BasicBlock,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let (needs_landing_pad, is_cleanupret) = self.llbb_characteristics(fx, target);
        if mergeable_succ && !needs_landing_pad && !is_cleanupret {
            // We can merge the successor into this bb, so no need for a `br`.
            MergingSucc::True
        } else {
            let mut lltarget = fx.llbb(target);
            if needs_landing_pad {
                lltarget = fx.landing_pad_for(target);
            }
            if is_cleanupret {
                // micro-optimization: generate a `ret` rather than a jump
                // to a trampoline.
                bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
            } else {
                bx.br(lltarget);
            }
            MergingSucc::False
        }
    }

    /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional
    /// return destination `destination` and the unwind action `unwind`.
    fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
        &self,
        fx: &mut FunctionCx<'a, 'tcx, Bx>,
        bx: &mut Bx,
        fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
        fn_ptr: Bx::Value,
        llargs: &[Bx::Value],
        destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
        mut unwind: mir::UnwindAction,
        lifetime_ends_after_call: &[(Bx::Value, Size)],
        instance: Option<Instance<'tcx>>,
        kind: CallKind,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let tcx = bx.tcx();
        if let Some(instance) = instance
            && is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance)
        {
            if destination.is_some() {
                let caller_def = fx.instance.def_id();
                let e = CompilerBuiltinsCannotCall {
                    span: tcx.def_span(caller_def),
                    caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)),
                    callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())),
                };
                tcx.dcx().emit_err(e);
            } else {
                info!(
                    "compiler_builtins call to diverging function {:?} replaced with abort",
                    instance.def_id()
                );
                bx.abort();
                bx.unreachable();
                return MergingSucc::False;
            }
        }

        // If there is a cleanup block and the function we're calling can unwind, then
        // do an invoke, otherwise do a call.
        let fn_ty = bx.fn_decl_backend_type(fn_abi);

        let caller_attrs = if bx.tcx().def_kind(fx.instance.def_id()).has_codegen_attrs() {
            Some(bx.tcx().codegen_instance_attrs(fx.instance.def))
        } else {
            None
        };
        let caller_attrs = caller_attrs.as_deref();

        if !fn_abi.can_unwind {
            unwind = mir::UnwindAction::Unreachable;
        }

        let unwind_block = match unwind {
            mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
            mir::UnwindAction::Continue => None,
            mir::UnwindAction::Unreachable => None,
            mir::UnwindAction::Terminate(reason) => {
                if fx.mir[self.bb].is_cleanup && base::wants_wasm_eh(fx.cx.tcx().sess) {
                    // For wasm, we need to generate a nested `cleanuppad within %outer_pad`
                    // to catch exceptions during cleanup and call `panic_in_cleanup`.
                    Some(fx.terminate_block(reason, Some(self.bb)))
                } else if fx.mir[self.bb].is_cleanup
                    && base::wants_new_eh_instructions(fx.cx.tcx().sess)
                {
                    // MSVC SEH will abort automatically if an exception tries to
                    // propagate out from cleanup.
                    None
                } else {
                    Some(fx.terminate_block(reason, None))
                }
            }
        };

        if kind == CallKind::Tail {
            bx.tail_call(fn_ty, caller_attrs, fn_abi, fn_ptr, llargs, self.funclet(fx), instance);
            return MergingSucc::False;
        }

        if let Some(unwind_block) = unwind_block {
            let ret_llbb = if let Some((_, target)) = destination {
                self.llbb_with_cleanup(fx, target)
            } else {
                fx.unreachable_block()
            };
            let invokeret = bx.invoke(
                fn_ty,
                caller_attrs,
                Some(fn_abi),
                fn_ptr,
                llargs,
                ret_llbb,
                unwind_block,
                self.funclet(fx),
                instance,
            );
            if fx.mir[self.bb].is_cleanup {
                bx.apply_attrs_to_cleanup_callsite(invokeret);
            }

            if let Some((ret_dest, target)) = destination {
                bx.switch_to_block(fx.llbb(target));
                fx.set_debug_loc(bx, self.terminator.source_info);
                for &(tmp, size) in lifetime_ends_after_call {
                    bx.lifetime_end(tmp, size);
                }
                fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret);
            }
            MergingSucc::False
        } else {
            let llret = bx.call(
                fn_ty,
                caller_attrs,
                Some(fn_abi),
                fn_ptr,
                llargs,
                self.funclet(fx),
                instance,
            );
            if fx.mir[self.bb].is_cleanup {
                bx.apply_attrs_to_cleanup_callsite(llret);
            }

            if let Some((ret_dest, target)) = destination {
                for &(tmp, size) in lifetime_ends_after_call {
                    bx.lifetime_end(tmp, size);
                }
                fx.store_return(bx, ret_dest, &fn_abi.ret, llret);
                self.funclet_br(fx, bx, target, mergeable_succ)
            } else {
                bx.unreachable();
                MergingSucc::False
            }
        }
    }

    /// Generates inline assembly with optional `destination` and `unwind`.
    fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
        &self,
        fx: &mut FunctionCx<'a, 'tcx, Bx>,
        bx: &mut Bx,
        template: &[InlineAsmTemplatePiece],
        operands: &[InlineAsmOperandRef<'tcx, Bx>],
        options: InlineAsmOptions,
        line_spans: &[Span],
        destination: Option<mir::BasicBlock>,
        unwind: mir::UnwindAction,
        instance: Instance<'_>,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let unwind_target = match unwind {
            mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
            mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason, None)),
            mir::UnwindAction::Continue => None,
            mir::UnwindAction::Unreachable => None,
        };

        if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) {
            assert!(unwind_target.is_none());
            let ret_llbb = if let Some(target) = destination {
                self.llbb_with_cleanup(fx, target)
            } else {
                fx.unreachable_block()
            };

            bx.codegen_inline_asm(
                template,
                operands,
                options,
                line_spans,
                instance,
                Some(ret_llbb),
                None,
            );
            MergingSucc::False
        } else if let Some(cleanup) = unwind_target {
            let ret_llbb = if let Some(target) = destination {
                self.llbb_with_cleanup(fx, target)
            } else {
                fx.unreachable_block()
            };

            bx.codegen_inline_asm(
                template,
                operands,
                options,
                line_spans,
                instance,
                Some(ret_llbb),
                Some((cleanup, self.funclet(fx))),
            );
            MergingSucc::False
        } else {
            bx.codegen_inline_asm(template, operands, options, line_spans, instance, None, None);

            if let Some(target) = destination {
                self.funclet_br(fx, bx, target, mergeable_succ)
            } else {
                bx.unreachable();
                MergingSucc::False
            }
        }
    }
}

/// Codegen implementations for some terminator variants.
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
    /// Generates code for a `Resume` terminator.
    fn codegen_resume_terminator(&mut self, helper: TerminatorCodegenHelper<'tcx>, bx: &mut Bx) {
        if let Some(funclet) = helper.funclet(self) {
            bx.cleanup_ret(funclet, None);
        } else {
            let slot = self.get_personality_slot(bx);
            let exn0 = slot.project_field(bx, 0);
            let exn0 = bx.load_operand(exn0).immediate();
            let exn1 = slot.project_field(bx, 1);
            let exn1 = bx.load_operand(exn1).immediate();
            slot.storage_dead(bx);

            bx.resume(exn0, exn1);
        }
    }

    fn codegen_switchint_terminator(
        &mut self,
        helper: TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        discr: &mir::Operand<'tcx>,
        targets: &SwitchTargets,
    ) {
        let discr = self.codegen_operand(bx, discr);
        let discr_value = discr.immediate();
        let switch_ty = discr.layout.ty;
        // If our discriminant is a constant we can branch directly
        if let Some(const_discr) = bx.const_to_opt_u128(discr_value, false) {
            let target = targets.target_for_value(const_discr);
            bx.br(helper.llbb_with_cleanup(self, target));
            return;
        };

        let mut target_iter = targets.iter();
        if target_iter.len() == 1 {
            // If there are two targets (one conditional, one fallback), emit `br` instead of
            // `switch`.
            let (test_value, target) = target_iter.next().unwrap();
            let otherwise = targets.otherwise();
            let lltarget = helper.llbb_with_cleanup(self, target);
            let llotherwise = helper.llbb_with_cleanup(self, otherwise);
            let target_cold = self.cold_blocks[target];
            let otherwise_cold = self.cold_blocks[otherwise];
            // If `target_cold == otherwise_cold`, the branches have the same weight
            // so there is no expectation. If they differ, the `target` branch is expected
            // when the `otherwise` branch is cold.
            let expect = if target_cold == otherwise_cold { None } else { Some(otherwise_cold) };
            if switch_ty == bx.tcx().types.bool {
                // Don't generate trivial icmps when switching on bool.
                match test_value {
                    0 => {
                        let expect = expect.map(|e| !e);
                        bx.cond_br_with_expect(discr_value, llotherwise, lltarget, expect);
                    }
                    1 => {
                        bx.cond_br_with_expect(discr_value, lltarget, llotherwise, expect);
                    }
                    _ => bug!(),
                }
            } else {
                let switch_llty = bx.immediate_backend_type(bx.layout_of(switch_ty));
                let llval = bx.const_uint_big(switch_llty, test_value);
                let cmp = bx.icmp(IntPredicate::IntEQ, discr_value, llval);
                bx.cond_br_with_expect(cmp, lltarget, llotherwise, expect);
            }
        } else if target_iter.len() == 2
            && self.mir[targets.otherwise()].is_empty_unreachable()
            && targets.all_values().contains(&Pu128(0))
            && targets.all_values().contains(&Pu128(1))
        {
            // This is the really common case for `bool`, `Option`, etc.
            // By using `trunc nuw` we communicate that other values are
            // impossible without needing `switch` or `assume`s.
            let true_bb = targets.target_for_value(1);
            let false_bb = targets.target_for_value(0);
            let true_ll = helper.llbb_with_cleanup(self, true_bb);
            let false_ll = helper.llbb_with_cleanup(self, false_bb);

            let expected_cond_value = if self.cx.sess().opts.optimize == OptLevel::No {
                None
            } else {
                match (self.cold_blocks[true_bb], self.cold_blocks[false_bb]) {
                    // Same coldness, no expectation
                    (true, true) | (false, false) => None,
                    // Different coldness, expect the non-cold one
                    (true, false) => Some(false),
                    (false, true) => Some(true),
                }
            };

            let bool_ty = bx.tcx().types.bool;
            let cond = if switch_ty == bool_ty {
                discr_value
            } else {
                let bool_llty = bx.immediate_backend_type(bx.layout_of(bool_ty));
                bx.unchecked_utrunc(discr_value, bool_llty)
            };
            bx.cond_br_with_expect(cond, true_ll, false_ll, expected_cond_value);
        } else if self.cx.sess().opts.optimize == OptLevel::No
            && target_iter.len() == 2
            && self.mir[targets.otherwise()].is_empty_unreachable()
        {
            // In unoptimized builds, if there are two normal targets and the `otherwise` target is
            // an unreachable BB, emit `br` instead of `switch`. This leaves behind the unreachable
            // BB, which will usually (but not always) be dead code.
            //
            // Why only in unoptimized builds?
            // - In unoptimized builds LLVM uses FastISel which does not support switches, so it
            //   must fall back to the slower SelectionDAG isel. Therefore, using `br` gives
            //   significant compile time speedups for unoptimized builds.
            // - In optimized builds the above doesn't hold, and using `br` sometimes results in
            //   worse generated code because LLVM can no longer tell that the value being switched
            //   on can only have two values, e.g. 0 and 1.
            //
            let (test_value1, target1) = target_iter.next().unwrap();
            let (_test_value2, target2) = target_iter.next().unwrap();
            let ll1 = helper.llbb_with_cleanup(self, target1);
            let ll2 = helper.llbb_with_cleanup(self, target2);
            let switch_llty = bx.immediate_backend_type(bx.layout_of(switch_ty));
            let llval = bx.const_uint_big(switch_llty, test_value1);
            let cmp = bx.icmp(IntPredicate::IntEQ, discr_value, llval);
            bx.cond_br(cmp, ll1, ll2);
        } else {
            let otherwise = targets.otherwise();
            let otherwise_cold = self.cold_blocks[otherwise];
            let otherwise_unreachable = self.mir[otherwise].is_empty_unreachable();
            let cold_count = targets.iter().filter(|(_, target)| self.cold_blocks[*target]).count();
            let none_cold = cold_count == 0;
            let all_cold = cold_count == targets.iter().len();
            if (none_cold && (!otherwise_cold || otherwise_unreachable))
                || (all_cold && (otherwise_cold || otherwise_unreachable))
            {
                // All targets have the same weight,
                // or `otherwise` is unreachable and it's the only target with a different weight.
                bx.switch(
                    discr_value,
                    helper.llbb_with_cleanup(self, targets.otherwise()),
                    target_iter
                        .map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))),
                );
            } else {
                // Targets have different weights
                bx.switch_with_weights(
                    discr_value,
                    helper.llbb_with_cleanup(self, targets.otherwise()),
                    otherwise_cold,
                    target_iter.map(|(value, target)| {
                        (value, helper.llbb_with_cleanup(self, target), self.cold_blocks[target])
                    }),
                );
            }
        }
    }

    fn codegen_return_terminator(&mut self, bx: &mut Bx) {
        // Call `va_end` if this is the definition of a C-variadic function.
        if self.fn_abi.c_variadic {
            // The `VaList` "spoofed" argument is just after all the real arguments.
            let va_list_arg_idx = self.fn_abi.args.len();
            match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] {
                LocalRef::Place(va_list) => {
                    bx.va_end(va_list.val.llval);

                    // Explicitly end the lifetime of the `va_list`, improves LLVM codegen.
                    bx.lifetime_end(va_list.val.llval, va_list.layout.size);
                }
                _ => bug!("C-variadic function must have a `VaList` place"),
            }
        }
        if self.fn_abi.ret.layout.is_uninhabited() {
            // Functions with uninhabited return values are marked `noreturn`,
            // so we should make sure that we never actually do.
            // We play it safe by using a well-defined `abort`, but we could go for immediate UB
            // if that turns out to be helpful.
            bx.abort();
            // `abort` does not terminate the block, so we still need to generate
            // an `unreachable` terminator after it.
            bx.unreachable();
            return;
        }
        let llval = match &self.fn_abi.ret.mode {
            PassMode::Ignore | PassMode::Indirect { .. } => {
                bx.ret_void();
                return;
            }

            PassMode::Direct(_) | PassMode::Pair(..) => {
                let op = self.codegen_consume(bx, mir::Place::return_place().as_ref());
                if let Ref(place_val) = op.val {
                    bx.load_from_place(bx.backend_type(op.layout), place_val)
                } else {
                    op.immediate_or_packed_pair(bx)
                }
            }

            PassMode::Cast { cast: cast_ty, pad_i32: _ } => {
                let op = match self.locals[mir::RETURN_PLACE] {
                    LocalRef::Operand(op) => op,
                    LocalRef::PendingOperand => bug!("use of return before def"),
                    LocalRef::Place(cg_place) => OperandRef {
                        val: Ref(cg_place.val),
                        layout: cg_place.layout,
                        move_annotation: None,
                    },
                    LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
                };
                let llslot = match op.val {
                    Immediate(_) | Pair(..) => {
                        let scratch = PlaceRef::alloca(bx, self.fn_abi.ret.layout);
                        op.val.store(bx, scratch);
                        scratch.val.llval
                    }
                    Ref(place_val) => {
                        assert_eq!(
                            place_val.align, op.layout.align.abi,
                            "return place is unaligned!"
                        );
                        place_val.llval
                    }
                    ZeroSized => bug!("ZST return value shouldn't be in PassMode::Cast"),
                };
                load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align.abi)
            }
        };
        bx.ret(llval);
    }

    #[tracing::instrument(level = "trace", skip(self, helper, bx))]
    fn codegen_drop_terminator(
        &mut self,
        helper: TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        source_info: &mir::SourceInfo,
        location: mir::Place<'tcx>,
        target: mir::BasicBlock,
        unwind: mir::UnwindAction,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let ty = location.ty(self.mir, bx.tcx()).ty;
        let ty = self.monomorphize(ty);
        let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);

        if let ty::InstanceKind::DropGlue(_, None) = drop_fn.def {
            // we don't actually need to drop anything.
            return helper.funclet_br(self, bx, target, mergeable_succ);
        }

        let place = self.codegen_place(bx, location.as_ref());
        let (args1, args2);
        let mut args = if let Some(llextra) = place.val.llextra {
            args2 = [place.val.llval, llextra];
            &args2[..]
        } else {
            args1 = [place.val.llval];
            &args1[..]
        };
        let (maybe_null, drop_fn, fn_abi, drop_instance) = match ty.kind() {
            // FIXME(eddyb) perhaps move some of this logic into
            // `Instance::resolve_drop_in_place`?
            ty::Dynamic(_, _) => {
                // IN THIS ARM, WE HAVE:
                // ty = *mut (dyn Trait)
                // which is: exists<T> ( *mut T,    Vtable<T: Trait> )
                //                       args[0]    args[1]
                //
                // args = ( Data, Vtable )
                //                  |
                //                  v
                //                /-------\
                //                | ...   |
                //                \-------/
                //
                let virtual_drop = Instance {
                    def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
                    args: drop_fn.args,
                };
                debug!("ty = {:?}", ty);
                debug!("drop_fn = {:?}", drop_fn);
                debug!("args = {:?}", args);
                let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
                let vtable = args[1];
                // Truncate vtable off of args list
                args = &args[..1];
                (
                    true,
                    meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
                        .get_optional_fn(bx, vtable, ty, fn_abi),
                    fn_abi,
                    virtual_drop,
                )
            }
            _ => (
                false,
                bx.get_fn_addr(drop_fn),
                bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
                drop_fn,
            ),
        };

        // We generate a null check for the drop_fn. This saves a bunch of relocations being
        // generated for no-op drops.
        if maybe_null {
            let is_not_null = bx.append_sibling_block("is_not_null");
            let llty = bx.fn_ptr_backend_type(fn_abi);
            let null = bx.const_null(llty);
            let non_null =
                bx.icmp(base::bin_op_to_icmp_predicate(mir::BinOp::Ne, false), drop_fn, null);
            bx.cond_br(non_null, is_not_null, helper.llbb_with_cleanup(self, target));
            bx.switch_to_block(is_not_null);
            self.set_debug_loc(bx, *source_info);
        }

        helper.do_call(
            self,
            bx,
            fn_abi,
            drop_fn,
            args,
            Some((ReturnDest::Nothing, target)),
            unwind,
            &[],
            Some(drop_instance),
            CallKind::Normal,
            !maybe_null && mergeable_succ,
        )
    }

    fn codegen_assert_terminator(
        &mut self,
        helper: TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        terminator: &mir::Terminator<'tcx>,
        cond: &mir::Operand<'tcx>,
        expected: bool,
        msg: &mir::AssertMessage<'tcx>,
        target: mir::BasicBlock,
        unwind: mir::UnwindAction,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let span = terminator.source_info.span;
        let cond = self.codegen_operand(bx, cond).immediate();
        let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1);

        // This case can currently arise only from functions marked
        // with #[rustc_inherit_overflow_checks] and inlined from
        // another crate (mostly core::num generic/#[inline] fns),
        // while the current crate doesn't use overflow checks.
        if !bx.sess().overflow_checks() && msg.is_optional_overflow_check() {
            const_cond = Some(expected);
        }

        // Don't codegen the panic block if success if known.
        if const_cond == Some(expected) {
            return helper.funclet_br(self, bx, target, mergeable_succ);
        }

        // Because we're branching to a panic block (either a `#[cold]` one
        // or an inlined abort), there's no need to `expect` it.

        // Create the failure block and the conditional branch to it.
        let lltarget = helper.llbb_with_cleanup(self, target);
        let panic_block = bx.append_sibling_block("panic");
        if expected {
            bx.cond_br(cond, lltarget, panic_block);
        } else {
            bx.cond_br(cond, panic_block, lltarget);
        }

        // After this point, bx is the block for the call to panic.
        bx.switch_to_block(panic_block);
        self.set_debug_loc(bx, terminator.source_info);

        // Get the location information.
        let location = self.get_caller_location(bx, terminator.source_info).immediate();

        // Put together the arguments to the panic entry point.
        let (lang_item, args) = match msg {
            AssertKind::BoundsCheck { len, index } => {
                let len = self.codegen_operand(bx, len).immediate();
                let index = self.codegen_operand(bx, index).immediate();
                // It's `fn panic_bounds_check(index: usize, len: usize)`,
                // and `#[track_caller]` adds an implicit third argument.
                (LangItem::PanicBoundsCheck, vec![index, len, location])
            }
            AssertKind::MisalignedPointerDereference { required, found } => {
                let required = self.codegen_operand(bx, required).immediate();
                let found = self.codegen_operand(bx, found).immediate();
                // It's `fn panic_misaligned_pointer_dereference(required: usize, found: usize)`,
                // and `#[track_caller]` adds an implicit third argument.
                (LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
            }
            AssertKind::NullPointerDereference => {
                // It's `fn panic_null_pointer_dereference()`,
                // `#[track_caller]` adds an implicit argument.
                (LangItem::PanicNullPointerDereference, vec![location])
            }
            AssertKind::InvalidEnumConstruction(source) => {
                let source = self.codegen_operand(bx, source).immediate();
                // It's `fn panic_invalid_enum_construction(source: u128)`,
                // `#[track_caller]` adds an implicit argument.
                (LangItem::PanicInvalidEnumConstruction, vec![source, location])
            }
            _ => {
                // It's `pub fn panic_...()` and `#[track_caller]` adds an implicit argument.
                (msg.panic_function(), vec![location])
            }
        };

        let (fn_abi, llfn, instance) = common::build_langcall(bx, span, lang_item);

        // Codegen the actual panic invoke/call.
        let merging_succ = helper.do_call(
            self,
            bx,
            fn_abi,
            llfn,
            &args,
            None,
            unwind,
            &[],
            Some(instance),
            CallKind::Normal,
            false,
        );
        assert_eq!(merging_succ, MergingSucc::False);
        MergingSucc::False
    }

    fn codegen_terminate_terminator(
        &mut self,
        helper: TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        terminator: &mir::Terminator<'tcx>,
        reason: UnwindTerminateReason,
    ) {
        let span = terminator.source_info.span;
        self.set_debug_loc(bx, terminator.source_info);

        // Obtain the panic entry point.
        let (fn_abi, llfn, instance) = common::build_langcall(bx, span, reason.lang_item());

        // Codegen the actual panic invoke/call.
        let merging_succ = helper.do_call(
            self,
            bx,
            fn_abi,
            llfn,
            &[],
            None,
            mir::UnwindAction::Unreachable,
            &[],
            Some(instance),
            CallKind::Normal,
            false,
        );
        assert_eq!(merging_succ, MergingSucc::False);
    }

    /// Returns `Some` if this is indeed a panic intrinsic and codegen is done.
    fn codegen_panic_intrinsic(
        &mut self,
        helper: &TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        intrinsic: ty::IntrinsicDef,
        instance: Instance<'tcx>,
        source_info: mir::SourceInfo,
        target: Option<mir::BasicBlock>,
        unwind: mir::UnwindAction,
        mergeable_succ: bool,
    ) -> Option<MergingSucc> {
        // Emit a panic or a no-op for `assert_*` intrinsics.
        // These are intrinsics that compile to panics so that we can get a message
        // which mentions the offending type, even from a const context.
        let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) else {
            return None;
        };

        let ty = instance.args.type_at(0);

        let is_valid = bx
            .tcx()
            .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
            .expect("expect to have layout during codegen");

        if is_valid {
            // a NOP
            let target = target.unwrap();
            return Some(helper.funclet_br(self, bx, target, mergeable_succ));
        }

        let layout = bx.layout_of(ty);

        let msg_str = with_no_visible_paths!({
            with_no_trimmed_paths!({
                if layout.is_uninhabited() {
                    // Use this error even for the other intrinsics as it is more precise.
                    format!("attempted to instantiate uninhabited type `{ty}`")
                } else if requirement == ValidityRequirement::Zero {
                    format!("attempted to zero-initialize type `{ty}`, which is invalid")
                } else {
                    format!("attempted to leave type `{ty}` uninitialized, which is invalid")
                }
            })
        });
        let msg = bx.const_str(&msg_str);

        // Obtain the panic entry point.
        let (fn_abi, llfn, instance) =
            common::build_langcall(bx, source_info.span, LangItem::PanicNounwind);

        // Codegen the actual panic invoke/call.
        Some(helper.do_call(
            self,
            bx,
            fn_abi,
            llfn,
            &[msg.0, msg.1],
            target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
            unwind,
            &[],
            Some(instance),
            CallKind::Normal,
            mergeable_succ,
        ))
    }

    fn codegen_call_terminator(
        &mut self,
        helper: TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        terminator: &mir::Terminator<'tcx>,
        func: &mir::Operand<'tcx>,
        args: &[Spanned<mir::Operand<'tcx>>],
        destination: mir::Place<'tcx>,
        target: Option<mir::BasicBlock>,
        unwind: mir::UnwindAction,
        fn_span: Span,
        kind: CallKind,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let source_info = mir::SourceInfo { span: fn_span, ..terminator.source_info };

        // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
        let callee = self.codegen_operand(bx, func);

        let (instance, mut llfn) = match *callee.layout.ty.kind() {
            ty::FnDef(def_id, generic_args) => {
                let instance = ty::Instance::expect_resolve(
                    bx.tcx(),
                    bx.typing_env(),
                    def_id,
                    generic_args,
                    fn_span,
                );

                match instance.def {
                    // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
                    // it is `func returning noop future`
                    ty::InstanceKind::DropGlue(_, None) => {
                        // Empty drop glue; a no-op.
                        let target = target.unwrap();
                        return helper.funclet_br(self, bx, target, mergeable_succ);
                    }
                    ty::InstanceKind::Intrinsic(def_id) => {
                        let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
                        if let Some(merging_succ) = self.codegen_panic_intrinsic(
                            &helper,
                            bx,
                            intrinsic,
                            instance,
                            source_info,
                            target,
                            unwind,
                            mergeable_succ,
                        ) {
                            return merging_succ;
                        }

                        let result_layout =
                            self.cx.layout_of(self.monomorphized_place_ty(destination.as_ref()));

                        let (result, store_in_local) = if result_layout.is_zst() {
                            (
                                PlaceRef::new_sized(bx.const_undef(bx.type_ptr()), result_layout),
                                None,
                            )
                        } else if let Some(local) = destination.as_local() {
                            match self.locals[local] {
                                LocalRef::Place(dest) => (dest, None),
                                LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
                                LocalRef::PendingOperand => {
                                    // Currently, intrinsics always need a location to store
                                    // the result, so we create a temporary `alloca` for the
                                    // result.
                                    let tmp = PlaceRef::alloca(bx, result_layout);
                                    tmp.storage_live(bx);
                                    (tmp, Some(local))
                                }
                                LocalRef::Operand(_) => {
                                    bug!("place local already assigned to");
                                }
                            }
                        } else {
                            (self.codegen_place(bx, destination.as_ref()), None)
                        };

                        if result.val.align < result.layout.align.abi {
                            // Currently, MIR code generation does not create calls
                            // that store directly to fields of packed structs (in
                            // fact, the calls it creates write only to temps).
                            //
                            // If someone changes that, please update this code path
                            // to create a temporary.
                            span_bug!(self.mir.span, "can't directly store to unaligned value");
                        }

                        let args: Vec<_> =
                            args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();

                        match self.codegen_intrinsic_call(bx, instance, &args, result, source_info)
                        {
                            Ok(()) => {
                                if let Some(local) = store_in_local {
                                    let op = bx.load_operand(result);
                                    result.storage_dead(bx);
                                    self.overwrite_local(local, LocalRef::Operand(op));
                                    self.debug_introduce_local(bx, local);
                                }

                                return if let Some(target) = target {
                                    helper.funclet_br(self, bx, target, mergeable_succ)
                                } else {
                                    bx.unreachable();
                                    MergingSucc::False
                                };
                            }
                            Err(instance) => {
                                if intrinsic.must_be_overridden {
                                    span_bug!(
                                        fn_span,
                                        "intrinsic {} must be overridden by codegen backend, but isn't",
                                        intrinsic.name,
                                    );
                                }
                                (Some(instance), None)
                            }
                        }
                    }

                    _ if kind == CallKind::Tail
                        && instance.def.requires_caller_location(bx.tcx()) =>
                    {
                        if let Some(hir_id) =
                            terminator.source_info.scope.lint_root(&self.mir.source_scopes)
                        {
                            bx.tcx().emit_node_lint(TAIL_CALL_TRACK_CALLER, hir_id, rustc_errors::DiagDecorator(|d| {
                                _ = d.primary_message("tail calling a function marked with `#[track_caller]` has no special effect").span(fn_span)
                            }));
                        }

                        let instance = ty::Instance::resolve_for_fn_ptr(
                            bx.tcx(),
                            bx.typing_env(),
                            def_id,
                            generic_args,
                        )
                        .unwrap();

                        (None, Some(bx.get_fn_addr(instance)))
                    }
                    _ => (Some(instance), None),
                }
            }
            ty::FnPtr(..) => (None, Some(callee.immediate())),
            _ => bug!("{} is not callable", callee.layout.ty),
        };

        if let Some(instance) = instance
            && let Some(name) = bx.tcx().codegen_fn_attrs(instance.def_id()).symbol_name
            && name.as_str().starts_with("llvm.")
            // This is the only LLVM intrinsic we use that unwinds
            // FIXME either add unwind support to codegen_llvm_intrinsic_call or replace usage of
            // this intrinsic with something else
            && name.as_str() != "llvm.wasm.throw"
        {
            assert!(!instance.args.has_infer());
            assert!(!instance.args.has_escaping_bound_vars());

            let result_layout =
                self.cx.layout_of(self.monomorphized_place_ty(destination.as_ref()));

            let return_dest = if result_layout.is_zst() {
                ReturnDest::Nothing
            } else if let Some(index) = destination.as_local() {
                match self.locals[index] {
                    LocalRef::Place(dest) => ReturnDest::Store(dest),
                    LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
                    LocalRef::PendingOperand => {
                        // Handle temporary places, specifically `Operand` ones, as
                        // they don't have `alloca`s.
                        ReturnDest::DirectOperand(index)
                    }
                    LocalRef::Operand(_) => bug!("place local already assigned to"),
                }
            } else {
                ReturnDest::Store(self.codegen_place(bx, destination.as_ref()))
            };

            let args =
                args.into_iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect::<Vec<_>>();

            self.set_debug_loc(bx, source_info);

            let llret =
                bx.codegen_llvm_intrinsic_call(instance, &args, self.mir[helper.bb].is_cleanup);

            if let Some(target) = target {
                self.store_return(
                    bx,
                    return_dest,
                    &ArgAbi { layout: result_layout, mode: PassMode::Direct(ArgAttributes::new()) },
                    llret,
                );
                return helper.funclet_br(self, bx, target, mergeable_succ);
            } else {
                bx.unreachable();
                return MergingSucc::False;
            }
        }

        // FIXME(eddyb) avoid computing this if possible, when `instance` is
        // available - right now `sig` is only needed for getting the `abi`
        // and figuring out how many extra args were passed to a C-variadic `fn`.
        let sig = callee.layout.ty.fn_sig(bx.tcx());

        let extra_args = &args[sig.inputs().skip_binder().len()..];
        let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
            let op_ty = op_arg.node.ty(self.mir, bx.tcx());
            self.monomorphize(op_ty)
        }));

        let fn_abi = match instance {
            Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
            None => bx.fn_abi_of_fn_ptr(sig, extra_args),
        };

        // The arguments we'll be passing. Plus one to account for outptr, if used.
        let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;

        let mut llargs = Vec::with_capacity(arg_count);

        // We still need to call `make_return_dest` even if there's no `target`, since
        // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
        // and `make_return_dest` adds the return-place indirect pointer to `llargs`.
        let destination = match kind {
            CallKind::Normal => {
                let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs);
                target.map(|target| (return_dest, target))
            }
            CallKind::Tail => {
                if fn_abi.ret.is_indirect() {
                    match self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs) {
                        ReturnDest::Nothing => {}
                        _ => bug!(
                            "tail calls to functions with indirect returns cannot store into a destination"
                        ),
                    }
                }
                None
            }
        };

        // Split the rust-call tupled arguments off.
        let (first_args, untuple) = if sig.abi() == ExternAbi::RustCall
            && let Some((tup, args)) = args.split_last()
        {
            (args, Some(tup))
        } else {
            (args, None)
        };

        // Special logic for tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments.
        //
        // Normally an indirect argument with `on_stack: false` would be passed as a pointer into
        // the caller's stack frame. For tail calls, that would be unsound, because the caller's
        // stack frame is overwritten by the callee's stack frame.
        //
        // Therefore we store the argument for the callee in the corresponding caller's slot.
        // Because guaranteed tail calls demand that the caller's signature matches the callee's,
        // the corresponding slot has the correct type.
        //
        // To handle cases like the one below, the tail call arguments must first be copied to a
        // temporary, and only then copied to the caller's argument slots.
        //
        // ```
        // // A struct big enough that it is not passed via registers.
        // pub struct Big([u64; 4]);
        //
        // fn swapper(a: Big, b: Big) -> (Big, Big) {
        //     become swapper_helper(b, a);
        // }
        // ```
        let mut tail_call_temporaries = vec![];
        if kind == CallKind::Tail {
            tail_call_temporaries = vec![None; first_args.len()];
            // Copy the arguments that use `PassMode::Indirect { on_stack: false , ..}`
            // to temporary stack allocations. See the comment above.
            for (i, arg) in first_args.iter().enumerate() {
                if !matches!(fn_abi.args[i].mode, PassMode::Indirect { on_stack: false, .. }) {
                    continue;
                }

                let op = self.codegen_operand(bx, &arg.node);
                let tmp = PlaceRef::alloca(bx, op.layout);
                bx.lifetime_start(tmp.val.llval, tmp.layout.size);
                op.store_with_annotation(bx, tmp);

                tail_call_temporaries[i] = Some(tmp);
            }
        }

        // When generating arguments we sometimes introduce temporary allocations with lifetime
        // that extend for the duration of a call. Keep track of those allocations and their sizes
        // to generate `lifetime_end` when the call returns.
        let mut lifetime_ends_after_call: Vec<(Bx::Value, Size)> = Vec::new();
        'make_args: for (i, arg) in first_args.iter().enumerate() {
            let mut op = self.codegen_operand(bx, &arg.node);

            if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, instance.map(|i| i.def)) {
                match op.val {
                    Pair(data_ptr, meta) => {
                        // In the case of Rc<Self>, we need to explicitly pass a
                        // *mut RcInner<Self> with a Scalar (not ScalarPair) ABI. This is a hack
                        // that is understood elsewhere in the compiler as a method on
                        // `dyn Trait`.
                        // To get a `*mut RcInner<Self>`, we just keep unwrapping newtypes until
                        // we get a value of a built-in pointer type.
                        //
                        // This is also relevant for `Pin<&mut Self>`, where we need to peel the
                        // `Pin`.
                        while !op.layout.ty.is_raw_ptr() && !op.layout.ty.is_ref() {
                            let (idx, _) = op.layout.non_1zst_field(bx).expect(
                                "not exactly one non-1-ZST field in a `DispatchFromDyn` type",
                            );
                            op = op.extract_field(self, bx, idx.as_usize());
                        }

                        // Now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
                        // data pointer and vtable. Look up the method in the vtable, and pass
                        // the data pointer as the first argument.
                        llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(
                            bx,
                            meta,
                            op.layout.ty,
                            fn_abi,
                        ));
                        llargs.push(data_ptr);
                        continue 'make_args;
                    }
                    Ref(PlaceValue { llval: data_ptr, llextra: Some(meta), .. }) => {
                        // by-value dynamic dispatch
                        llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(
                            bx,
                            meta,
                            op.layout.ty,
                            fn_abi,
                        ));
                        llargs.push(data_ptr);
                        continue;
                    }
                    _ => {
                        span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
                    }
                }
            }

            match kind {
                CallKind::Normal => {
                    // The callee needs to own the argument memory if we pass it
                    // by-ref, so make a local copy of non-immediate constants.
                    if let &mir::Operand::Copy(_) | &mir::Operand::Constant(_) = &arg.node
                        && let Ref(PlaceValue { llextra: None, .. }) = op.val
                    {
                        let tmp = PlaceRef::alloca(bx, op.layout);
                        bx.lifetime_start(tmp.val.llval, tmp.layout.size);
                        op.store_with_annotation(bx, tmp);
                        op.val = Ref(tmp.val);
                        lifetime_ends_after_call.push((tmp.val.llval, tmp.layout.size));
                    }
                }
                CallKind::Tail => {
                    if let PassMode::Indirect { on_stack: false, .. } = fn_abi.args[i].mode {
                        let Some(tmp) = tail_call_temporaries[i].take() else {
                            span_bug!(
                                fn_span,
                                "missing temporary for indirect tail call argument #{i}"
                            )
                        };

                        let local = self.mir.args_iter().nth(i).unwrap();

                        match &self.locals[local] {
                            LocalRef::Place(arg) => {
                                bx.typed_place_copy(arg.val, tmp.val, fn_abi.args[i].layout);
                                op.val = Ref(arg.val);
                            }
                            LocalRef::Operand(arg) => {
                                let Ref(place_value) = arg.val else {
                                    bug!("only `Ref` should use `PassMode::Indirect`");
                                };
                                bx.typed_place_copy(place_value, tmp.val, fn_abi.args[i].layout);
                                op.val = arg.val;
                            }
                            LocalRef::UnsizedPlace(_) => {
                                span_bug!(fn_span, "unsized types are not supported")
                            }
                            LocalRef::PendingOperand => {
                                span_bug!(fn_span, "argument local should not be pending")
                            }
                        };

                        bx.lifetime_end(tmp.val.llval, tmp.layout.size);
                    }
                }
            }

            self.codegen_argument(
                bx,
                op,
                &mut llargs,
                &fn_abi.args[i],
                &mut lifetime_ends_after_call,
            );
        }
        let num_untupled = untuple.map(|tup| {
            self.codegen_arguments_untupled(
                bx,
                &tup.node,
                &mut llargs,
                &fn_abi.args[first_args.len()..],
                &mut lifetime_ends_after_call,
            )
        });

        let needs_location =
            instance.is_some_and(|i| i.def.requires_caller_location(self.cx.tcx()));
        if needs_location {
            let mir_args = if let Some(num_untupled) = num_untupled {
                first_args.len() + num_untupled
            } else {
                args.len()
            };
            assert_eq!(
                fn_abi.args.len(),
                mir_args + 1,
                "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {instance:?} {fn_span:?} {fn_abi:?}",
            );
            let location = self.get_caller_location(bx, source_info);
            debug!(
                "codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
                terminator, location, fn_span
            );

            let last_arg = fn_abi.args.last().unwrap();
            self.codegen_argument(
                bx,
                location,
                &mut llargs,
                last_arg,
                &mut lifetime_ends_after_call,
            );
        }

        let fn_ptr = match (instance, llfn) {
            (Some(instance), None) => bx.get_fn_addr(instance),
            (_, Some(llfn)) => llfn,
            _ => span_bug!(fn_span, "no instance or llfn for call"),
        };
        self.set_debug_loc(bx, source_info);
        helper.do_call(
            self,
            bx,
            fn_abi,
            fn_ptr,
            &llargs,
            destination,
            unwind,
            &lifetime_ends_after_call,
            instance,
            kind,
            mergeable_succ,
        )
    }

    fn codegen_asm_terminator(
        &mut self,
        helper: TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        asm_macro: InlineAsmMacro,
        terminator: &mir::Terminator<'tcx>,
        template: &[ast::InlineAsmTemplatePiece],
        operands: &[mir::InlineAsmOperand<'tcx>],
        options: ast::InlineAsmOptions,
        line_spans: &[Span],
        targets: &[mir::BasicBlock],
        unwind: mir::UnwindAction,
        instance: Instance<'_>,
        mergeable_succ: bool,
    ) -> MergingSucc {
        let span = terminator.source_info.span;

        let operands: Vec<_> = operands
            .iter()
            .map(|op| match *op {
                mir::InlineAsmOperand::In { reg, ref value } => {
                    let value = self.codegen_operand(bx, value);
                    InlineAsmOperandRef::In { reg, value }
                }
                mir::InlineAsmOperand::Out { reg, late, ref place } => {
                    let place = place.map(|place| self.codegen_place(bx, place.as_ref()));
                    InlineAsmOperandRef::Out { reg, late, place }
                }
                mir::InlineAsmOperand::InOut { reg, late, ref in_value, ref out_place } => {
                    let in_value = self.codegen_operand(bx, in_value);
                    let out_place =
                        out_place.map(|out_place| self.codegen_place(bx, out_place.as_ref()));
                    InlineAsmOperandRef::InOut { reg, late, in_value, out_place }
                }
                mir::InlineAsmOperand::Const { ref value } => {
                    let const_value = self.eval_mir_constant(value);
                    let string = common::asm_const_to_str(
                        bx.tcx(),
                        span,
                        const_value,
                        bx.layout_of(value.ty()),
                    );
                    InlineAsmOperandRef::Const { string }
                }
                mir::InlineAsmOperand::SymFn { ref value } => {
                    let const_ = self.monomorphize(value.const_);
                    if let ty::FnDef(def_id, args) = *const_.ty().kind() {
                        let instance = ty::Instance::resolve_for_fn_ptr(
                            bx.tcx(),
                            bx.typing_env(),
                            def_id,
                            args,
                        )
                        .unwrap();
                        InlineAsmOperandRef::SymFn { instance }
                    } else {
                        span_bug!(span, "invalid type for asm sym (fn)");
                    }
                }
                mir::InlineAsmOperand::SymStatic { def_id } => {
                    InlineAsmOperandRef::SymStatic { def_id }
                }
                mir::InlineAsmOperand::Label { target_index } => {
                    InlineAsmOperandRef::Label { label: self.llbb(targets[target_index]) }
                }
            })
            .collect();

        helper.do_inlineasm(
            self,
            bx,
            template,
            &operands,
            options,
            line_spans,
            if asm_macro.diverges(options) { None } else { targets.get(0).copied() },
            unwind,
            instance,
            mergeable_succ,
        )
    }

    pub(crate) fn codegen_block(&mut self, mut bb: mir::BasicBlock) {
        let llbb = match self.try_llbb(bb) {
            Some(llbb) => llbb,
            None => return,
        };
        let bx = &mut Bx::build(self.cx, llbb);
        let mir = self.mir;

        // MIR basic blocks stop at any function call. This may not be the case
        // for the backend's basic blocks, in which case we might be able to
        // combine multiple MIR basic blocks into a single backend basic block.
        loop {
            let data = &mir[bb];

            debug!("codegen_block({:?}={:?})", bb, data);

            for statement in &data.statements {
                self.codegen_statement(bx, statement);
            }
            self.codegen_stmt_debuginfos(bx, &data.after_last_stmt_debuginfos);

            let merging_succ = self.codegen_terminator(bx, bb, data.terminator());
            if let MergingSucc::False = merging_succ {
                break;
            }

            // We are merging the successor into the produced backend basic
            // block. Record that the successor should be skipped when it is
            // reached.
            //
            // Note: we must not have already generated code for the successor.
            // This is implicitly ensured by the reverse postorder traversal,
            // and the assertion explicitly guarantees that.
            let mut successors = data.terminator().successors();
            let succ = successors.next().unwrap();
            assert!(matches!(self.cached_llbbs[succ], CachedLlbb::None));
            self.cached_llbbs[succ] = CachedLlbb::Skip;
            bb = succ;
        }
    }

    pub(crate) fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) {
        let llbb = match self.try_llbb(bb) {
            Some(llbb) => llbb,
            None => return,
        };
        let bx = &mut Bx::build(self.cx, llbb);
        debug!("codegen_block_as_unreachable({:?})", bb);
        bx.unreachable();
    }

    fn codegen_terminator(
        &mut self,
        bx: &mut Bx,
        bb: mir::BasicBlock,
        terminator: &'tcx mir::Terminator<'tcx>,
    ) -> MergingSucc {
        debug!("codegen_terminator: {:?}", terminator);

        let helper = TerminatorCodegenHelper { bb, terminator };

        let mergeable_succ = || {
            // Note: any call to `switch_to_block` will invalidate a `true` value
            // of `mergeable_succ`.
            let mut successors = terminator.successors();
            if let Some(succ) = successors.next()
                && successors.next().is_none()
                && let &[succ_pred] = self.mir.basic_blocks.predecessors()[succ].as_slice()
            {
                // bb has a single successor, and bb is its only predecessor. This
                // makes it a candidate for merging.
                assert_eq!(succ_pred, bb);
                true
            } else {
                false
            }
        };

        self.set_debug_loc(bx, terminator.source_info);
        match terminator.kind {
            mir::TerminatorKind::UnwindResume => {
                self.codegen_resume_terminator(helper, bx);
                MergingSucc::False
            }

            mir::TerminatorKind::UnwindTerminate(reason) => {
                self.codegen_terminate_terminator(helper, bx, terminator, reason);
                MergingSucc::False
            }

            mir::TerminatorKind::Goto { target } => {
                helper.funclet_br(self, bx, target, mergeable_succ())
            }

            mir::TerminatorKind::SwitchInt { ref discr, ref targets } => {
                self.codegen_switchint_terminator(helper, bx, discr, targets);
                MergingSucc::False
            }

            mir::TerminatorKind::Return => {
                self.codegen_return_terminator(bx);
                MergingSucc::False
            }

            mir::TerminatorKind::Unreachable => {
                bx.unreachable();
                MergingSucc::False
            }

            mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
                assert!(
                    async_fut.is_none() && drop.is_none(),
                    "Async Drop must be expanded or reset to sync before codegen"
                );
                self.codegen_drop_terminator(
                    helper,
                    bx,
                    &terminator.source_info,
                    place,
                    target,
                    unwind,
                    mergeable_succ(),
                )
            }

            mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
                .codegen_assert_terminator(
                    helper,
                    bx,
                    terminator,
                    cond,
                    expected,
                    msg,
                    target,
                    unwind,
                    mergeable_succ(),
                ),

            mir::TerminatorKind::Call {
                ref func,
                ref args,
                destination,
                target,
                unwind,
                call_source: _,
                fn_span,
            } => self.codegen_call_terminator(
                helper,
                bx,
                terminator,
                func,
                args,
                destination,
                target,
                unwind,
                fn_span,
                CallKind::Normal,
                mergeable_succ(),
            ),
            mir::TerminatorKind::TailCall { ref func, ref args, fn_span } => self
                .codegen_call_terminator(
                    helper,
                    bx,
                    terminator,
                    func,
                    args,
                    mir::Place::from(mir::RETURN_PLACE),
                    None,
                    mir::UnwindAction::Unreachable,
                    fn_span,
                    CallKind::Tail,
                    mergeable_succ(),
                ),
            mir::TerminatorKind::CoroutineDrop | mir::TerminatorKind::Yield { .. } => {
                bug!("coroutine ops in codegen")
            }
            mir::TerminatorKind::FalseEdge { .. } | mir::TerminatorKind::FalseUnwind { .. } => {
                bug!("borrowck false edges in codegen")
            }

            mir::TerminatorKind::InlineAsm {
                asm_macro,
                template,
                ref operands,
                options,
                line_spans,
                ref targets,
                unwind,
            } => self.codegen_asm_terminator(
                helper,
                bx,
                asm_macro,
                terminator,
                template,
                operands,
                options,
                line_spans,
                targets,
                unwind,
                self.instance,
                mergeable_succ(),
            ),
        }
    }

    fn codegen_argument(
        &mut self,
        bx: &mut Bx,
        op: OperandRef<'tcx, Bx::Value>,
        llargs: &mut Vec<Bx::Value>,
        arg: &ArgAbi<'tcx, Ty<'tcx>>,
        lifetime_ends_after_call: &mut Vec<(Bx::Value, Size)>,
    ) {
        match arg.mode {
            PassMode::Ignore => return,
            PassMode::Cast { pad_i32: true, .. } => {
                // Fill padding with undef value, where applicable.
                llargs.push(bx.const_undef(bx.reg_backend_type(&Reg::i32())));
            }
            PassMode::Pair(..) => match op.val {
                Pair(a, b) => {
                    llargs.push(a);
                    llargs.push(b);
                    return;
                }
                _ => bug!("codegen_argument: {:?} invalid for pair argument", op),
            },
            PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => match op.val {
                Ref(PlaceValue { llval: a, llextra: Some(b), .. }) => {
                    llargs.push(a);
                    llargs.push(b);
                    return;
                }
                _ => bug!("codegen_argument: {:?} invalid for unsized indirect argument", op),
            },
            _ => {}
        }

        // Force by-ref if we have to load through a cast pointer.
        let (mut llval, align, by_ref) = match op.val {
            Immediate(_) | Pair(..) => match arg.mode {
                PassMode::Indirect { attrs, .. } => {
                    // Indirect argument may have higher alignment requirements than the type's
                    // alignment. This can happen, e.g. when passing types with <4 byte alignment
                    // on the stack on x86.
                    let required_align = match attrs.pointee_align {
                        Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
                        None => arg.layout.align.abi,
                    };
                    let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
                    bx.lifetime_start(scratch.llval, arg.layout.size);
                    op.store_with_annotation(bx, scratch.with_type(arg.layout));
                    lifetime_ends_after_call.push((scratch.llval, arg.layout.size));
                    (scratch.llval, scratch.align, true)
                }
                PassMode::Cast { .. } => {
                    let scratch = PlaceRef::alloca(bx, arg.layout);
                    op.store_with_annotation(bx, scratch);
                    (scratch.val.llval, scratch.val.align, true)
                }
                _ => (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false),
            },
            Ref(op_place_val) => match arg.mode {
                PassMode::Indirect { attrs, .. } => {
                    let required_align = match attrs.pointee_align {
                        Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
                        None => arg.layout.align.abi,
                    };
                    if op_place_val.align < required_align {
                        // For `foo(packed.large_field)`, and types with <4 byte alignment on x86,
                        // alignment requirements may be higher than the type's alignment, so copy
                        // to a higher-aligned alloca.
                        let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
                        bx.lifetime_start(scratch.llval, arg.layout.size);
                        bx.typed_place_copy(scratch, op_place_val, op.layout);
                        lifetime_ends_after_call.push((scratch.llval, arg.layout.size));
                        (scratch.llval, scratch.align, true)
                    } else {
                        (op_place_val.llval, op_place_val.align, true)
                    }
                }
                _ => (op_place_val.llval, op_place_val.align, true),
            },
            ZeroSized => match arg.mode {
                PassMode::Indirect { on_stack, .. } => {
                    if on_stack {
                        // It doesn't seem like any target can have `byval` ZSTs, so this assert
                        // is here to replace a would-be untested codepath.
                        bug!("ZST {op:?} passed on stack with abi {arg:?}");
                    }
                    // Though `extern "Rust"` doesn't pass ZSTs, some ABIs pass
                    // a pointer for `repr(C)` structs even when empty, so get
                    // one from an `alloca` (which can be left uninitialized).
                    let scratch = PlaceRef::alloca(bx, arg.layout);
                    (scratch.val.llval, scratch.val.align, true)
                }
                _ => bug!("ZST {op:?} wasn't ignored, but was passed with abi {arg:?}"),
            },
        };

        if by_ref && !arg.is_indirect() {
            // Have to load the argument, maybe while casting it.
            if let PassMode::Cast { cast, pad_i32: _ } = &arg.mode {
                // The ABI mandates that the value is passed as a different struct representation.
                // Spill and reload it from the stack to convert from the Rust representation to
                // the ABI representation.
                let scratch_size = cast.size(bx);
                let scratch_align = cast.align(bx);
                // Note that the ABI type may be either larger or smaller than the Rust type,
                // due to the presence or absence of trailing padding. For example:
                // - On some ABIs, the Rust layout { f64, f32, <f32 padding> } may omit padding
                //   when passed by value, making it smaller.
                // - On some ABIs, the Rust layout { u16, u16, u16 } may be padded up to 8 bytes
                //   when passed by value, making it larger.
                let copy_bytes = cmp::min(cast.unaligned_size(bx).bytes(), arg.layout.size.bytes());
                // Allocate some scratch space...
                let llscratch = bx.alloca(scratch_size, scratch_align);
                bx.lifetime_start(llscratch, scratch_size);
                // ...memcpy the value...
                bx.memcpy(
                    llscratch,
                    scratch_align,
                    llval,
                    align,
                    bx.const_usize(copy_bytes),
                    MemFlags::empty(),
                    None,
                );
                // ...and then load it with the ABI type.
                llval = load_cast(bx, cast, llscratch, scratch_align);
                bx.lifetime_end(llscratch, scratch_size);
            } else {
                // We can't use `PlaceRef::load` here because the argument
                // may have a type we don't treat as immediate, but the ABI
                // used for this call is passing it by-value. In that case,
                // the load would just produce `OperandValue::Ref` instead
                // of the `OperandValue::Immediate` we need for the call.
                llval = bx.load(bx.backend_type(arg.layout), llval, align);
                if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
                    if scalar.is_bool() {
                        bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
                    }
                    // We store bools as `i8` so we need to truncate to `i1`.
                    llval = bx.to_immediate_scalar(llval, scalar);
                }
            }
        }

        llargs.push(llval);
    }

    fn codegen_arguments_untupled(
        &mut self,
        bx: &mut Bx,
        operand: &mir::Operand<'tcx>,
        llargs: &mut Vec<Bx::Value>,
        args: &[ArgAbi<'tcx, Ty<'tcx>>],
        lifetime_ends_after_call: &mut Vec<(Bx::Value, Size)>,
    ) -> usize {
        let tuple = self.codegen_operand(bx, operand);

        // Handle both by-ref and immediate tuples.
        if let Ref(place_val) = tuple.val {
            if place_val.llextra.is_some() {
                bug!("closure arguments must be sized");
            }
            let tuple_ptr = place_val.with_type(tuple.layout);
            for i in 0..tuple.layout.fields.count() {
                let field_ptr = tuple_ptr.project_field(bx, i);
                let field = bx.load_operand(field_ptr);
                self.codegen_argument(bx, field, llargs, &args[i], lifetime_ends_after_call);
            }
        } else {
            // If the tuple is immediate, the elements are as well.
            for i in 0..tuple.layout.fields.count() {
                let op = tuple.extract_field(self, bx, i);
                self.codegen_argument(bx, op, llargs, &args[i], lifetime_ends_after_call);
            }
        }
        tuple.layout.fields.count()
    }

    pub(super) fn get_caller_location(
        &mut self,
        bx: &mut Bx,
        source_info: mir::SourceInfo,
    ) -> OperandRef<'tcx, Bx::Value> {
        self.mir.caller_location_span(source_info, self.caller_location, bx.tcx(), |span: Span| {
            let const_loc = bx.tcx().span_as_caller_location(span);
            OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
        })
    }

    fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> {
        let cx = bx.cx();
        if let Some(slot) = self.personality_slot {
            slot
        } else {
            let layout = cx.layout_of(Ty::new_tup(
                cx.tcx(),
                &[Ty::new_mut_ptr(cx.tcx(), cx.tcx().types.u8), cx.tcx().types.i32],
            ));
            let slot = PlaceRef::alloca(bx, layout);
            self.personality_slot = Some(slot);
            slot
        }
    }

    /// Returns the landing/cleanup pad wrapper around the given basic block.
    // FIXME(eddyb) rename this to `eh_pad_for`.
    fn landing_pad_for(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
        if let Some(landing_pad) = self.landing_pads[bb] {
            return landing_pad;
        }

        let landing_pad = self.landing_pad_for_uncached(bb);
        self.landing_pads[bb] = Some(landing_pad);
        landing_pad
    }

    // FIXME(eddyb) rename this to `eh_pad_for_uncached`.
    fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
        let llbb = self.llbb(bb);
        if base::wants_new_eh_instructions(self.cx.sess()) {
            let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{bb:?}"));
            let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
            let funclet = cleanup_bx.cleanup_pad(None, &[]);
            cleanup_bx.br(llbb);
            self.funclets[bb] = Some(funclet);
            cleanup_bb
        } else {
            let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup");
            let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);

            let llpersonality = self.cx.eh_personality();
            let (exn0, exn1) = cleanup_bx.cleanup_landing_pad(llpersonality);

            let slot = self.get_personality_slot(&mut cleanup_bx);
            slot.storage_live(&mut cleanup_bx);
            Pair(exn0, exn1).store(&mut cleanup_bx, slot);

            cleanup_bx.br(llbb);
            cleanup_llbb
        }
    }

    fn unreachable_block(&mut self) -> Bx::BasicBlock {
        self.unreachable_block.unwrap_or_else(|| {
            let llbb = Bx::append_block(self.cx, self.llfn, "unreachable");
            let mut bx = Bx::build(self.cx, llbb);
            bx.unreachable();
            self.unreachable_block = Some(llbb);
            llbb
        })
    }

    fn terminate_block(
        &mut self,
        reason: UnwindTerminateReason,
        outer_catchpad_bb: Option<mir::BasicBlock>,
    ) -> Bx::BasicBlock {
        // mb_funclet_bb should be present if and only if the target is wasm and
        // we're terminating because of an unwind in a cleanup block. In that
        // case we have nested funclets and the inner catch_switch needs to know
        // what outer catch_pad it is contained in.
        debug_assert!(
            outer_catchpad_bb.is_some()
                == (base::wants_wasm_eh(self.cx.tcx().sess)
                    && reason == UnwindTerminateReason::InCleanup)
        );

        // When we aren't in a wasm InCleanup block, there's only one terminate
        // block needed so we cache at START_BLOCK index.
        let mut cache_bb = mir::START_BLOCK;
        // In wasm eh InCleanup, use the outer funclet's cleanup BB as the cache
        // key.
        if let Some(outer_bb) = outer_catchpad_bb {
            let cleanup_kinds =
                self.cleanup_kinds.as_ref().expect("cleanup_kinds required for funclets");
            cache_bb = cleanup_kinds[outer_bb]
                .funclet_bb(outer_bb)
                .expect("funclet_bb should be in a funclet");

            // Ensure the outer funclet is created first
            if self.funclets[cache_bb].is_none() {
                self.landing_pad_for(cache_bb);
            }
        }
        if let Some((cached_bb, cached_reason)) = self.terminate_blocks[cache_bb]
            && reason == cached_reason
        {
            return cached_bb;
        }

        let funclet;
        let llbb;
        let mut bx;
        if base::wants_new_eh_instructions(self.cx.sess()) {
            // This is a basic block that we're aborting the program for,
            // notably in an `extern` function. These basic blocks are inserted
            // so that we assert that `extern` functions do indeed not panic,
            // and if they do we abort the process.
            //
            // On MSVC these are tricky though (where we're doing funclets). If
            // we were to do a cleanuppad (like below) the normal functions like
            // `longjmp` would trigger the abort logic, terminating the
            // program. Instead we insert the equivalent of `catch(...)` for C++
            // which magically doesn't trigger when `longjmp` files over this
            // frame.
            //
            // Lots more discussion can be found on #48251 but this codegen is
            // modeled after clang's for:
            //
            //      try {
            //          foo();
            //      } catch (...) {
            //          bar();
            //      }
            //
            // which creates an IR snippet like
            //
            //      cs_terminate:
            //         %cs = catchswitch within none [%cp_terminate] unwind to caller
            //      cp_terminate:
            //         %cp = catchpad within %cs [null, i32 64, null]
            //         ...
            //
            // By contrast, on WebAssembly targets, we specifically _do_ want to
            // catch foreign exceptions. The situation with MSVC is a
            // regrettable hack which we don't want to extend to other targets
            // unless necessary. For WebAssembly, to generate catch(...) and
            // catch only C++ exception instead of generating a catch_all, we
            // need to call the intrinsics @llvm.wasm.get.exception and
            // @llvm.wasm.get.ehselector in the catch pad. Since we don't do
            // this, we generate a catch_all. We originally got this behavior
            // by accident but it luckily matches our intention.

            llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");

            let mut cs_bx = Bx::build(self.cx, llbb);

            // For wasm InCleanup blocks, our catch_switch is nested within the
            // outer catchpad, so we need to provide it as the parent value to
            // catch_switch.
            let mut outer_cleanuppad = None;
            if outer_catchpad_bb.is_some() {
                // Get the outer funclet's catchpad
                let outer_funclet = self.funclets[cache_bb]
                    .as_ref()
                    .expect("landing_pad_for didn't create funclet");
                outer_cleanuppad = Some(cs_bx.get_funclet_cleanuppad(outer_funclet));
            }
            let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
            let cs = cs_bx.catch_switch(outer_cleanuppad, None, &[cp_llbb]);
            drop(cs_bx);

            bx = Bx::build(self.cx, cp_llbb);
            let null =
                bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));

            // The `null` in first argument here is actually a RTTI type
            // descriptor for the C++ personality function, but `catch (...)`
            // has no type so it's null.
            let args = if base::wants_msvc_seh(self.cx.sess()) {
                // This bitmask is a single `HT_IsStdDotDot` flag, which
                // represents that this is a C++-style `catch (...)` block that
                // only captures programmatic exceptions, not all SEH
                // exceptions. The second `null` points to a non-existent
                // `alloca` instruction, which an LLVM pass would inline into
                // the initial SEH frame allocation.
                let adjectives = bx.const_i32(0x40);
                &[null, adjectives, null] as &[_]
            } else {
                // Specifying more arguments than necessary usually doesn't
                // hurt, but the `WasmEHPrepare` LLVM pass does not recognize
                // anything other than a single `null` as a `catch_all` block,
                // leading to problems down the line during instruction
                // selection.
                &[null] as &[_]
            };

            funclet = Some(bx.catch_pad(cs, args));
            // On wasm, if we wanted to generate a catch(...) and only catch C++
            // exceptions, we'd call @llvm.wasm.get.exception and
            // @llvm.wasm.get.ehselector selectors here. We want a catch_all so
            // we leave them out. This is intentionally diverging from the MSVC
            // behavior.
        } else {
            llbb = Bx::append_block(self.cx, self.llfn, "terminate");
            bx = Bx::build(self.cx, llbb);

            let llpersonality = self.cx.eh_personality();
            bx.filter_landing_pad(llpersonality);

            funclet = None;
        }

        self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));

        let (fn_abi, fn_ptr, instance) =
            common::build_langcall(&bx, self.mir.span, reason.lang_item());
        if is_call_from_compiler_builtins_to_upstream_monomorphization(bx.tcx(), instance) {
            bx.abort();
        } else {
            let fn_ty = bx.fn_decl_backend_type(fn_abi);

            let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref(), None);
            bx.apply_attrs_to_cleanup_callsite(llret);
        }

        bx.unreachable();

        self.terminate_blocks[cache_bb] = Some((llbb, reason));
        llbb
    }

    /// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already
    /// cached in `self.cached_llbbs`, or created on demand (and cached).
    // FIXME(eddyb) rename `llbb` and other `ll`-prefixed things to use a
    // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbb`).
    pub fn llbb(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
        self.try_llbb(bb).unwrap()
    }

    /// Like `llbb`, but may fail if the basic block should be skipped.
    pub(crate) fn try_llbb(&mut self, bb: mir::BasicBlock) -> Option<Bx::BasicBlock> {
        match self.cached_llbbs[bb] {
            CachedLlbb::None => {
                let llbb = Bx::append_block(self.cx, self.llfn, &format!("{bb:?}"));
                self.cached_llbbs[bb] = CachedLlbb::Some(llbb);
                Some(llbb)
            }
            CachedLlbb::Some(llbb) => Some(llbb),
            CachedLlbb::Skip => None,
        }
    }

    fn make_return_dest(
        &mut self,
        bx: &mut Bx,
        dest: mir::Place<'tcx>,
        fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
        llargs: &mut Vec<Bx::Value>,
    ) -> ReturnDest<'tcx, Bx::Value> {
        // If the return is ignored, we can just return a do-nothing `ReturnDest`.
        if fn_ret.is_ignore() {
            return ReturnDest::Nothing;
        }
        let dest = if let Some(index) = dest.as_local() {
            match self.locals[index] {
                LocalRef::Place(dest) => dest,
                LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
                LocalRef::PendingOperand => {
                    // Handle temporary places, specifically `Operand` ones, as
                    // they don't have `alloca`s.
                    return if fn_ret.is_indirect() {
                        // Odd, but possible, case, we have an operand temporary,
                        // but the calling convention has an indirect return.
                        let tmp = PlaceRef::alloca(bx, fn_ret.layout);
                        tmp.storage_live(bx);
                        llargs.push(tmp.val.llval);
                        ReturnDest::IndirectOperand(tmp, index)
                    } else {
                        ReturnDest::DirectOperand(index)
                    };
                }
                LocalRef::Operand(_) => {
                    bug!("place local already assigned to");
                }
            }
        } else {
            self.codegen_place(bx, dest.as_ref())
        };
        if fn_ret.is_indirect() {
            if dest.val.align < dest.layout.align.abi {
                // Currently, MIR code generation does not create calls
                // that store directly to fields of packed structs (in
                // fact, the calls it creates write only to temps).
                //
                // If someone changes that, please update this code path
                // to create a temporary.
                span_bug!(self.mir.span, "can't directly store to unaligned value");
            }
            llargs.push(dest.val.llval);
            ReturnDest::Nothing
        } else {
            ReturnDest::Store(dest)
        }
    }

    // Stores the return value of a function call into it's final location.
    fn store_return(
        &mut self,
        bx: &mut Bx,
        dest: ReturnDest<'tcx, Bx::Value>,
        ret_abi: &ArgAbi<'tcx, Ty<'tcx>>,
        llval: Bx::Value,
    ) {
        use self::ReturnDest::*;

        match dest {
            Nothing => (),
            Store(dst) => bx.store_arg(ret_abi, llval, dst),
            IndirectOperand(tmp, index) => {
                let op = bx.load_operand(tmp);
                tmp.storage_dead(bx);
                self.overwrite_local(index, LocalRef::Operand(op));
                self.debug_introduce_local(bx, index);
            }
            DirectOperand(index) => {
                // If there is a cast, we have to store and reload.
                let op = if let PassMode::Cast { .. } = ret_abi.mode {
                    let tmp = PlaceRef::alloca(bx, ret_abi.layout);
                    tmp.storage_live(bx);
                    bx.store_arg(ret_abi, llval, tmp);
                    let op = bx.load_operand(tmp);
                    tmp.storage_dead(bx);
                    op
                } else {
                    OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout)
                };
                self.overwrite_local(index, LocalRef::Operand(op));
                self.debug_introduce_local(bx, index);
            }
        }
    }
}

enum ReturnDest<'tcx, V> {
    /// Do nothing; the return value is indirect or ignored.
    Nothing,
    /// Store the return value to the pointer.
    Store(PlaceRef<'tcx, V>),
    /// Store an indirect return value to an operand local place.
    IndirectOperand(PlaceRef<'tcx, V>, mir::Local),
    /// Store a direct return value to an operand local place.
    DirectOperand(mir::Local),
}

fn load_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
    bx: &mut Bx,
    cast: &CastTarget,
    ptr: Bx::Value,
    align: Align,
) -> Bx::Value {
    let cast_ty = bx.cast_backend_type(cast);
    if let Some(offset_from_start) = cast.rest_offset {
        assert!(cast.prefix[1..].iter().all(|p| p.is_none()));
        assert_eq!(cast.rest.unit.size, cast.rest.total);
        let first_ty = bx.reg_backend_type(&cast.prefix[0].unwrap());
        let second_ty = bx.reg_backend_type(&cast.rest.unit);
        let first = bx.load(first_ty, ptr, align);
        let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes()));
        let second = bx.load(second_ty, second_ptr, align.restrict_for_offset(offset_from_start));
        let res = bx.cx().const_poison(cast_ty);
        let res = bx.insert_value(res, first, 0);
        bx.insert_value(res, second, 1)
    } else {
        bx.load(cast_ty, ptr, align)
    }
}

pub fn store_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
    bx: &mut Bx,
    cast: &CastTarget,
    value: Bx::Value,
    ptr: Bx::Value,
    align: Align,
) {
    if let Some(offset_from_start) = cast.rest_offset {
        assert!(cast.prefix[1..].iter().all(|p| p.is_none()));
        assert_eq!(cast.rest.unit.size, cast.rest.total);
        assert!(cast.prefix[0].is_some());
        let first = bx.extract_value(value, 0);
        let second = bx.extract_value(value, 1);
        bx.store(first, ptr, align);
        let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes()));
        bx.store(second, second_ptr, align.restrict_for_offset(offset_from_start));
    } else {
        bx.store(value, ptr, align);
    };
}
