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::{self, 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::mir::IntrinsicResult;
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);

                // If the return value was retagged as it was stored,
                // then we might be in a different basic block now.
                // Update the cached block for `target` to point to this new
                // block, where codegen will continue.
                fx.cached_llbbs[target] = CachedLlbb::Some(bx.llbb());
            }
            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::arg(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_glue(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_glue`?
            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_place, store_in_local) =
                            if let Some(local) = destination.as_local() {
                                match self.locals[local] {
                                    LocalRef::Place(dest) => (Some(dest.val), None),
                                    LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
                                    LocalRef::PendingOperand => (None, Some(local)),
                                    LocalRef::Operand(_) => {
                                        if result_layout.is_zst() {
                                            let place = PlaceRef::new_sized(
                                                bx.const_undef(bx.type_ptr()),
                                                result_layout,
                                            );
                                            (Some(place.val), None)
                                        } else {
                                            bug!("place local already assigned to");
                                        }
                                    }
                                }
                            } else {
                                (Some(self.codegen_place(bx, destination.as_ref()).val), None)
                            };

                        if let Some(place) = result_place
                            && place.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();

                        let intrinsic_result = self.codegen_intrinsic_call(
                            bx,
                            instance,
                            &args,
                            result_layout,
                            result_place,
                            source_info,
                        );

                        if let IntrinsicResult::Operand(op_val) = intrinsic_result {
                            match (result_place, store_in_local) {
                                (None, Some(local)) => {
                                    let op = OperandRef {
                                        val: op_val,
                                        layout: result_layout,
                                        move_annotation: None,
                                    };
                                    self.overwrite_local(local, LocalRef::Operand(op));
                                    self.debug_introduce_local(bx, local);
                                }
                                (Some(place_val), None) => {
                                    let dest = PlaceRef { val: place_val, layout: result_layout };
                                    op_val.store(bx, dest);
                                }
                                _ => bug!(),
                            }
                        }

                        match intrinsic_result {
                            IntrinsicResult::Operand(_) | IntrinsicResult::WroteIntoPlace => {
                                return if let Some(target) = target {
                                    helper.funclet_br(self, bx, target, mergeable_succ)
                                } else {
                                    bx.unreachable();
                                    MergingSucc::False
                                };
                            }
                            IntrinsicResult::Err(_) => {
                                // Even though we're definitely going to error, we need it initialize
                                // the local or `maybe_codegen_consume_direct` might ICE later
                                // when it goes to use the result from this intrinsic.
                                if let Some(local) = store_in_local {
                                    let op = OperandRef {
                                        val: OperandValue::poison(bx, result_layout),
                                        layout: result_layout,
                                        move_annotation: None,
                                    };
                                    self.overwrite_local(local, LocalRef::Operand(op));
                                }
                                // Also we need to terminate the block to avoid an LLVM assertion,
                                // even though we're not going to actually use the IR.
                                bx.abort();
                                return MergingSucc::False;
                            }
                            IntrinsicResult::Fallback(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 that is allocated in the caller's stack frame
        // would be passed as a pointer into the callee'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);
                    }
                }
            }

            let by_move = if let PassMode::Indirect { on_stack: false, .. } = fn_abi.args[i].mode
                && kind == CallKind::Tail
            {
                // Special logic for tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments.
                //
                // Normally an indirect argument that is allocated in the caller's stack frame
                // would be passed as a pointer into the callee's stack frame.
                // For tail calls, that would be unsound, because the caller's
                // stack frame is overwritten by the callee's stack frame.
                //
                // To handle the case, we introduce `tail_call_temporaries` to copy arguments into
                // temporaries, then copy back to the caller's argument slots.
                // Finally, we pass the caller's argument slots as arguments.
                //
                // To do that, the argument must be MUST-by-move value.
                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);
                true
            } else {
                matches!(arg.node, mir::Operand::Move(_))
            };

            self.codegen_argument(
                bx,
                op,
                by_move,
                &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,
                /* by_move */ false,
                &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 } => {
                assert!(
                    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>,
        by_move: bool,
        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)
                }
                PassMode::Direct(_) => (op.immediate(), arg.layout.align.abi, false),
                PassMode::Ignore | PassMode::Pair(..) => unreachable!("handled above"),
            },
            Ref(op_place_val) => match arg.mode {
                PassMode::Indirect { attrs, on_stack, .. } => {
                    // 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 required_align = match attrs.pointee_align {
                        Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi),
                        None => arg.layout.align.abi,
                    };
                    // Copy to an alloca when the argument is neither by-val nor by-move.
                    if op_place_val.align < required_align || (!on_stack && !by_move) {
                        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)
                    } 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);
        let by_move = matches!(operand, mir::Operand::Move(_));

        // 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,
                    by_move,
                    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, by_move, 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::*;
        let retags_enabled = bx.tcx().sess.opts.unstable_opts.codegen_emit_retag.is_some();
        match dest {
            Nothing => (),
            Store(dst) => {
                bx.store_arg(ret_abi, llval, dst);
                if retags_enabled {
                    self.codegen_retag_place(bx, dst, false);
                }
            }
            IndirectOperand(tmp, index) => {
                let mut op = bx.load_operand(tmp);
                tmp.storage_dead(bx);
                if retags_enabled {
                    op = self.codegen_retag_operand(bx, op, false);
                }
                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 mut 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)
                };
                if retags_enabled {
                    op = self.codegen_retag_operand(bx, op, false);
                }
                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_eq!(cast.prefix.len(), 1);
        assert_eq!(cast.rest.unit.size, cast.rest.total);
        let first_ty = bx.reg_backend_type(&cast.prefix[0]);
        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_eq!(cast.prefix.len(), 1);
        assert_eq!(cast.rest.unit.size, cast.rest.total);
        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);
    };
}
