use std::cmp;

use libc::c_uint;
use rustc_abi::{
    ArmCall, BackendRepr, CanonAbi, HasDataLayout, InterruptKind, Primitive, Reg, RegKind, Size,
    X86Call,
};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
use rustc_codegen_ssa::traits::*;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::{bug, ty};
use rustc_session::{Session, config};
use rustc_target::callconv::{
    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode,
};
use rustc_target::spec::{Arch, SanitizerSet};
use smallvec::SmallVec;

use crate::attributes::{self, llfn_attrs_from_instance};
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::llvm::{self, Attribute, AttributePlace, Type, Value};
use crate::llvm_util;
use crate::type_of::LayoutLlvmExt;

trait ArgAttributesExt {
    fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value);
    fn apply_attrs_to_callsite(
        &self,
        idx: AttributePlace,
        cx: &CodegenCx<'_, '_>,
        callsite: &Value,
    );
}

const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
    [(ArgAttribute::InReg, llvm::AttributeKind::InReg)];

const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 4] = [
    (ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
    (ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
    (ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
    (ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
];

fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attribute; 8]> {
    let mut regular = this.regular;

    let mut attrs = SmallVec::new();

    // ABI-affecting attributes must always be applied
    for (attr, llattr) in ABI_AFFECTING_ATTRIBUTES {
        if regular.contains(attr) {
            attrs.push(llattr.create_attr(cx.llcx));
        }
    }
    if let Some(align) = this.pointee_align {
        attrs.push(llvm::CreateAlignmentAttr(cx.llcx, align.bytes()));
    }
    match this.arg_ext {
        ArgExtension::None => {}
        ArgExtension::Zext => attrs.push(llvm::AttributeKind::ZExt.create_attr(cx.llcx)),
        ArgExtension::Sext => attrs.push(llvm::AttributeKind::SExt.create_attr(cx.llcx)),
    }

    // Only apply remaining attributes when optimizing
    if cx.sess().opts.optimize != config::OptLevel::No {
        let deref = this.pointee_size.bytes();
        if deref != 0 {
            if regular.contains(ArgAttribute::NonNull) {
                attrs.push(llvm::CreateDereferenceableAttr(cx.llcx, deref));
            } else {
                attrs.push(llvm::CreateDereferenceableOrNullAttr(cx.llcx, deref));
            }
            regular -= ArgAttribute::NonNull;
        }
        for (attr, llattr) in OPTIMIZATION_ATTRIBUTES {
            if regular.contains(attr) {
                attrs.push(llattr.create_attr(cx.llcx));
            }
        }
        // captures(...) is only available since LLVM 21.
        if (21, 0, 0) <= llvm_util::get_version() {
            const CAPTURES_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 3] = [
                (ArgAttribute::CapturesNone, llvm::AttributeKind::CapturesNone),
                (ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress),
                (ArgAttribute::CapturesReadOnly, llvm::AttributeKind::CapturesReadOnly),
            ];
            for (attr, llattr) in CAPTURES_ATTRIBUTES {
                if regular.contains(attr) {
                    attrs.push(llattr.create_attr(cx.llcx));
                    break;
                }
            }
        }
    } else if cx.tcx.sess.sanitizers().contains(SanitizerSet::MEMORY) {
        // If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects
        // memory sanitizer's behavior.

        if regular.contains(ArgAttribute::NoUndef) {
            attrs.push(llvm::AttributeKind::NoUndef.create_attr(cx.llcx));
        }
    }

    attrs
}

impl ArgAttributesExt for ArgAttributes {
    fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value) {
        let attrs = get_attrs(self, cx);
        attributes::apply_to_llfn(llfn, idx, &attrs);
    }

    fn apply_attrs_to_callsite(
        &self,
        idx: AttributePlace,
        cx: &CodegenCx<'_, '_>,
        callsite: &Value,
    ) {
        let attrs = get_attrs(self, cx);
        attributes::apply_to_callsite(callsite, idx, &attrs);
    }
}

pub(crate) trait LlvmType {
    fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type;
}

impl LlvmType for Reg {
    fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
        match self.kind {
            RegKind::Integer => cx.type_ix(self.size.bits()),
            RegKind::Float => match self.size.bits() {
                16 => cx.type_f16(),
                32 => cx.type_f32(),
                64 => cx.type_f64(),
                128 => cx.type_f128(),
                _ => bug!("unsupported float: {:?}", self),
            },
            RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
        }
    }
}

impl LlvmType for CastTarget {
    fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
        let rest_ll_unit = self.rest.unit.llvm_type(cx);
        let rest_count = if self.rest.total == Size::ZERO {
            0
        } else {
            assert_ne!(
                self.rest.unit.size,
                Size::ZERO,
                "total size {:?} cannot be divided into units of zero size",
                self.rest.total
            );
            if !self.rest.total.bytes().is_multiple_of(self.rest.unit.size.bytes()) {
                assert_eq!(self.rest.unit.kind, RegKind::Integer, "only int regs can be split");
            }
            self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes())
        };

        // Simplify to a single unit or an array if there's no prefix.
        // This produces the same layout, but using a simpler type.
        if self.prefix.iter().all(|x| x.is_none()) {
            // We can't do this if is_consecutive is set and the unit would get
            // split on the target. Currently, this is only relevant for i128
            // registers.
            if rest_count == 1 && (!self.rest.is_consecutive || self.rest.unit != Reg::i128()) {
                return rest_ll_unit;
            }

            return cx.type_array(rest_ll_unit, rest_count);
        }

        // Generate a struct type with the prefix and the "rest" arguments.
        let prefix_args =
            self.prefix.iter().flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx)));
        let rest_args = (0..rest_count).map(|_| rest_ll_unit);
        let args: Vec<_> = prefix_args.chain(rest_args).collect();
        cx.type_struct(&args, false)
    }
}

trait ArgAbiExt<'ll, 'tcx> {
    fn store(
        &self,
        bx: &mut Builder<'_, 'll, 'tcx>,
        val: &'ll Value,
        dst: PlaceRef<'tcx, &'ll Value>,
    );
    fn store_fn_arg(
        &self,
        bx: &mut Builder<'_, 'll, 'tcx>,
        idx: &mut usize,
        dst: PlaceRef<'tcx, &'ll Value>,
    );
}

impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
    /// Stores a direct/indirect value described by this ArgAbi into a
    /// place for the original Rust type of this argument/return.
    /// Can be used for both storing formal arguments into Rust variables
    /// or results of call/invoke instructions into their destinations.
    fn store(
        &self,
        bx: &mut Builder<'_, 'll, 'tcx>,
        val: &'ll Value,
        dst: PlaceRef<'tcx, &'ll Value>,
    ) {
        match &self.mode {
            PassMode::Ignore => {}
            // Sized indirect arguments
            PassMode::Indirect { attrs, meta_attrs: None, on_stack: _ } => {
                let align = attrs.pointee_align.unwrap_or(self.layout.align.abi);
                OperandValue::Ref(PlaceValue::new_sized(val, align)).store(bx, dst);
            }
            // Unsized indirect arguments cannot be stored
            PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
                bug!("unsized `ArgAbi` cannot be stored");
            }
            PassMode::Cast { cast, pad_i32: _ } => {
                // The ABI mandates that the value is passed as a different struct representation.
                // Spill and reload it from the stack to convert from the ABI representation to
                // the Rust 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(), self.layout.size.bytes());
                // Allocate some scratch space...
                let llscratch = bx.alloca(scratch_size, scratch_align);
                bx.lifetime_start(llscratch, scratch_size);
                // ...store the value...
                rustc_codegen_ssa::mir::store_cast(bx, cast, val, llscratch, scratch_align);
                // ... and then memcpy it to the intended destination.
                bx.memcpy(
                    dst.val.llval,
                    self.layout.align.abi,
                    llscratch,
                    scratch_align,
                    bx.const_usize(copy_bytes),
                    MemFlags::empty(),
                    None,
                );
                bx.lifetime_end(llscratch, scratch_size);
            }
            PassMode::Pair(..) | PassMode::Direct { .. } => {
                OperandRef::from_immediate_or_packed_pair(bx, val, self.layout).val.store(bx, dst);
            }
        }
    }

    fn store_fn_arg(
        &self,
        bx: &mut Builder<'_, 'll, 'tcx>,
        idx: &mut usize,
        dst: PlaceRef<'tcx, &'ll Value>,
    ) {
        let mut next = || {
            let val = llvm::get_param(bx.llfn(), *idx as c_uint);
            *idx += 1;
            val
        };
        match self.mode {
            PassMode::Ignore => {}
            PassMode::Pair(..) => {
                OperandValue::Pair(next(), next()).store(bx, dst);
            }
            PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
                bug!("unsized `ArgAbi` cannot be stored");
            }
            PassMode::Direct(_)
            | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ }
            | PassMode::Cast { .. } => {
                let next_arg = next();
                self.store(bx, next_arg, dst);
            }
        }
    }
}

impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
    fn store_fn_arg(
        &mut self,
        arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
        idx: &mut usize,
        dst: PlaceRef<'tcx, Self::Value>,
    ) {
        arg_abi.store_fn_arg(self, idx, dst)
    }
    fn store_arg(
        &mut self,
        arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
        val: &'ll Value,
        dst: PlaceRef<'tcx, &'ll Value>,
    ) {
        arg_abi.store(self, val, dst)
    }
}

pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
    fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
    fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
    fn llvm_cconv(&self, cx: &CodegenCx<'ll, 'tcx>) -> llvm::CallConv;

    /// Apply attributes to a function declaration/definition.
    fn apply_attrs_llfn(
        &self,
        cx: &CodegenCx<'ll, 'tcx>,
        llfn: &'ll Value,
        instance: Option<ty::Instance<'tcx>>,
    );

    /// Apply attributes to a function call.
    fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value);
}

impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
    fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
        // Ignore "extra" args from the call site for C variadic functions.
        // Only the "fixed" args are part of the LLVM function signature.
        let args =
            if self.c_variadic { &self.args[..self.fixed_count as usize] } else { &self.args };

        // This capacity calculation is approximate.
        let mut llargument_tys = Vec::with_capacity(
            self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 },
        );

        let llreturn_ty = match &self.ret.mode {
            PassMode::Ignore => cx.type_void(),
            PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
            PassMode::Cast { cast, pad_i32: _ } => cast.llvm_type(cx),
            PassMode::Indirect { .. } => {
                llargument_tys.push(cx.type_ptr());
                cx.type_void()
            }
        };

        for arg in args {
            // Note that the exact number of arguments pushed here is carefully synchronized with
            // code all over the place, both in the codegen_llvm and codegen_ssa crates. That's how
            // other code then knows which LLVM argument(s) correspond to the n-th Rust argument.
            let llarg_ty = match &arg.mode {
                PassMode::Ignore => continue,
                PassMode::Direct(_) => {
                    // ABI-compatible Rust types have the same `layout.abi` (up to validity ranges),
                    // and for Scalar ABIs the LLVM type is fully determined by `layout.abi`,
                    // guaranteeing that we generate ABI-compatible LLVM IR.
                    arg.layout.immediate_llvm_type(cx)
                }
                PassMode::Pair(..) => {
                    // ABI-compatible Rust types have the same `layout.abi` (up to validity ranges),
                    // so for ScalarPair we can easily be sure that we are generating ABI-compatible
                    // LLVM IR.
                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true));
                    llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
                    continue;
                }
                PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
                    // Construct the type of a (wide) pointer to `ty`, and pass its two fields.
                    // Any two ABI-compatible unsized types have the same metadata type and
                    // moreover the same metadata value leads to the same dynamic size and
                    // alignment, so this respects ABI compatibility.
                    let ptr_ty = Ty::new_mut_ptr(cx.tcx, arg.layout.ty);
                    let ptr_layout = cx.layout_of(ptr_ty);
                    llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true));
                    llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true));
                    continue;
                }
                PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => cx.type_ptr(),
                PassMode::Cast { cast, pad_i32 } => {
                    // add padding
                    if *pad_i32 {
                        llargument_tys.push(Reg::i32().llvm_type(cx));
                    }
                    // Compute the LLVM type we use for this function from the cast type.
                    // We assume here that ABI-compatible Rust types have the same cast type.
                    cast.llvm_type(cx)
                }
            };
            llargument_tys.push(llarg_ty);
        }

        if self.c_variadic {
            cx.type_variadic_func(&llargument_tys, llreturn_ty)
        } else {
            cx.type_func(&llargument_tys, llreturn_ty)
        }
    }

    fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
        cx.type_ptr_ext(cx.data_layout().instruction_address_space)
    }

    fn llvm_cconv(&self, cx: &CodegenCx<'ll, 'tcx>) -> llvm::CallConv {
        to_llvm_calling_convention(cx.tcx.sess, self.conv)
    }

    fn apply_attrs_llfn(
        &self,
        cx: &CodegenCx<'ll, 'tcx>,
        llfn: &'ll Value,
        instance: Option<ty::Instance<'tcx>>,
    ) {
        let mut func_attrs = SmallVec::<[_; 3]>::new();
        if self.ret.layout.is_uninhabited() {
            func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
        }
        if !self.can_unwind {
            func_attrs.push(llvm::AttributeKind::NoUnwind.create_attr(cx.llcx));
        }
        match self.conv {
            CanonAbi::Interrupt(InterruptKind::RiscvMachine) => {
                func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", "machine"))
            }
            CanonAbi::Interrupt(InterruptKind::RiscvSupervisor) => {
                func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", "supervisor"))
            }
            CanonAbi::Arm(ArmCall::CCmseNonSecureEntry) => {
                func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"))
            }
            _ => (),
        }
        attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });

        let mut i = 0;
        let mut apply = |attrs: &ArgAttributes| {
            attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), cx, llfn);
            i += 1;
            i - 1
        };

        let apply_range_attr = |idx: AttributePlace, scalar: rustc_abi::Scalar| {
            if cx.sess().opts.optimize != config::OptLevel::No
                && matches!(scalar.primitive(), Primitive::Int(..))
                // If the value is a boolean, the range is 0..2 and that ultimately
                // become 0..0 when the type becomes i1, which would be rejected
                // by the LLVM verifier.
                && !scalar.is_bool()
                // LLVM also rejects full range.
                && !scalar.is_always_valid(cx)
            {
                attributes::apply_to_llfn(
                    llfn,
                    idx,
                    &[llvm::CreateRangeAttr(cx.llcx, scalar.size(cx), scalar.valid_range(cx))],
                );
            }
        };

        match &self.ret.mode {
            PassMode::Direct(attrs) => {
                attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
                if let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr {
                    apply_range_attr(llvm::AttributePlace::ReturnValue, scalar);
                }
            }
            PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
                assert!(!on_stack);
                let i = apply(attrs);
                let sret = llvm::CreateStructRetAttr(
                    cx.llcx,
                    cx.type_array(cx.type_i8(), self.ret.layout.size.bytes()),
                );
                attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
                if cx.sess().opts.optimize != config::OptLevel::No {
                    attributes::apply_to_llfn(
                        llfn,
                        llvm::AttributePlace::Argument(i),
                        &[
                            llvm::AttributeKind::Writable.create_attr(cx.llcx),
                            llvm::AttributeKind::DeadOnUnwind.create_attr(cx.llcx),
                        ],
                    );
                }
            }
            PassMode::Cast { cast, pad_i32: _ } => {
                cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
            }
            _ => {}
        }
        for arg in self.args.iter() {
            match &arg.mode {
                PassMode::Ignore => {}
                PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
                    let i = apply(attrs);
                    let byval = llvm::CreateByValAttr(
                        cx.llcx,
                        cx.type_array(cx.type_i8(), arg.layout.size.bytes()),
                    );
                    attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]);
                }
                PassMode::Direct(attrs) => {
                    let i = apply(attrs);
                    if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
                        apply_range_attr(llvm::AttributePlace::Argument(i), scalar);
                    }
                }
                PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
                    let i = apply(attrs);
                    if cx.sess().opts.optimize != config::OptLevel::No
                        && llvm_util::get_version() >= (21, 0, 0)
                    {
                        attributes::apply_to_llfn(
                            llfn,
                            llvm::AttributePlace::Argument(i),
                            &[llvm::AttributeKind::DeadOnReturn.create_attr(cx.llcx)],
                        );
                    }
                }
                PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
                    assert!(!on_stack);
                    apply(attrs);
                    apply(meta_attrs);
                }
                PassMode::Pair(a, b) => {
                    let i = apply(a);
                    let ii = apply(b);
                    if let BackendRepr::ScalarPair(scalar_a, scalar_b) = arg.layout.backend_repr {
                        apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a);
                        let primitive_b = scalar_b.primitive();
                        let scalar_b = if let rustc_abi::Primitive::Int(int, false) = primitive_b
                            && let ty::Ref(_, pointee_ty, _) = *arg.layout.ty.kind()
                            && let ty::Slice(element_ty) = *pointee_ty.kind()
                            && let elem_size = cx.layout_of(element_ty).size
                            && elem_size != rustc_abi::Size::ZERO
                        {
                            // Ideally the layout calculations would have set the range,
                            // but that's complicated due to cycles, so in the mean time
                            // we calculate and apply it here.
                            debug_assert!(scalar_b.is_always_valid(cx));
                            let isize_max = int.signed_max() as u64;
                            rustc_abi::Scalar::Initialized {
                                value: primitive_b,
                                valid_range: rustc_abi::WrappingRange {
                                    start: 0,
                                    end: u128::from(isize_max / elem_size.bytes()),
                                },
                            }
                        } else {
                            scalar_b
                        };
                        apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b);
                    }
                }
                PassMode::Cast { cast, pad_i32 } => {
                    if *pad_i32 {
                        apply(&ArgAttributes::new());
                    }
                    apply(&cast.attrs);
                }
            }
        }

        // If the declaration has an associated instance, compute extra attributes based on that.
        if let Some(instance) = instance {
            llfn_attrs_from_instance(
                cx,
                cx.tcx,
                llfn,
                &cx.tcx.codegen_instance_attrs(instance.def),
                Some(instance),
            );
        }
    }

    fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) {
        let mut func_attrs = SmallVec::<[_; 2]>::new();
        if self.ret.layout.is_uninhabited() {
            func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(bx.cx.llcx));
        }
        if !self.can_unwind {
            func_attrs.push(llvm::AttributeKind::NoUnwind.create_attr(bx.cx.llcx));
        }
        attributes::apply_to_callsite(callsite, llvm::AttributePlace::Function, &{ func_attrs });

        let mut i = 0;
        let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| {
            attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), cx, callsite);
            i += 1;
            i - 1
        };
        match &self.ret.mode {
            PassMode::Direct(attrs) => {
                attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, bx.cx, callsite);
            }
            PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
                assert!(!on_stack);
                let i = apply(bx.cx, attrs);
                let sret = llvm::CreateStructRetAttr(
                    bx.cx.llcx,
                    bx.cx.type_array(bx.cx.type_i8(), self.ret.layout.size.bytes()),
                );
                attributes::apply_to_callsite(callsite, llvm::AttributePlace::Argument(i), &[sret]);
            }
            PassMode::Cast { cast, pad_i32: _ } => {
                cast.attrs.apply_attrs_to_callsite(
                    llvm::AttributePlace::ReturnValue,
                    bx.cx,
                    callsite,
                );
            }
            _ => {}
        }
        for arg in self.args.iter() {
            match &arg.mode {
                PassMode::Ignore => {}
                PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
                    let i = apply(bx.cx, attrs);
                    let byval = llvm::CreateByValAttr(
                        bx.cx.llcx,
                        bx.cx.type_array(bx.cx.type_i8(), arg.layout.size.bytes()),
                    );
                    attributes::apply_to_callsite(
                        callsite,
                        llvm::AttributePlace::Argument(i),
                        &[byval],
                    );
                }
                PassMode::Direct(attrs)
                | PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
                    apply(bx.cx, attrs);
                }
                PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack: _ } => {
                    apply(bx.cx, attrs);
                    apply(bx.cx, meta_attrs);
                }
                PassMode::Pair(a, b) => {
                    apply(bx.cx, a);
                    apply(bx.cx, b);
                }
                PassMode::Cast { cast, pad_i32 } => {
                    if *pad_i32 {
                        apply(bx.cx, &ArgAttributes::new());
                    }
                    apply(bx.cx, &cast.attrs);
                }
            }
        }

        let cconv = self.llvm_cconv(&bx.cx);
        if cconv != llvm::CCallConv {
            llvm::SetInstructionCallConv(callsite, cconv);
        }

        if self.conv == CanonAbi::Arm(ArmCall::CCmseNonSecureCall) {
            // This will probably get ignored on all targets but those supporting the TrustZone-M
            // extension (thumbv8m targets).
            let cmse_nonsecure_call = llvm::CreateAttrString(bx.cx.llcx, "cmse_nonsecure_call");
            attributes::apply_to_callsite(
                callsite,
                llvm::AttributePlace::Function,
                &[cmse_nonsecure_call],
            );
        }

        // Some intrinsics require that an elementtype attribute (with the pointee type of a
        // pointer argument) is added to the callsite.
        let element_type_index = unsafe { llvm::LLVMRustGetElementTypeArgIndex(callsite) };
        if element_type_index >= 0 {
            let arg_ty = self.args[element_type_index as usize].layout.ty;
            let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument");
            let element_type_attr = unsafe {
                llvm::LLVMRustCreateElementTypeAttr(bx.llcx, bx.layout_of(pointee_ty).llvm_type(bx))
            };
            attributes::apply_to_callsite(
                callsite,
                llvm::AttributePlace::Argument(element_type_index as u32),
                &[element_type_attr],
            );
        }
    }
}

impl AbiBuilderMethods for Builder<'_, '_, '_> {
    fn get_param(&mut self, index: usize) -> Self::Value {
        llvm::get_param(self.llfn(), index as c_uint)
    }
}

/// Determines the appropriate [`llvm::CallConv`] to use for a given function
/// ABI, for the current target.
pub(crate) fn to_llvm_calling_convention(sess: &Session, abi: CanonAbi) -> llvm::CallConv {
    match abi {
        CanonAbi::C | CanonAbi::Rust => llvm::CCallConv,
        CanonAbi::RustCold => llvm::PreserveMost,
        // Functions with this calling convention can only be called from assembly, but it is
        // possible to declare an `extern "custom"` block, so the backend still needs a calling
        // convention for declaring foreign functions.
        CanonAbi::Custom => llvm::CCallConv,
        CanonAbi::GpuKernel => match &sess.target.arch {
            Arch::AmdGpu => llvm::AmdgpuKernel,
            Arch::Nvptx64 => llvm::PtxKernel,
            arch => panic!("Architecture {arch} does not support GpuKernel calling convention"),
        },
        CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
            InterruptKind::Avr => llvm::AvrInterrupt,
            InterruptKind::AvrNonBlocking => llvm::AvrNonBlockingInterrupt,
            InterruptKind::Msp430 => llvm::Msp430Intr,
            InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => llvm::CCallConv,
            InterruptKind::X86 => llvm::X86_Intr,
        },
        CanonAbi::Arm(arm_call) => match arm_call {
            ArmCall::Aapcs => llvm::ArmAapcsCallConv,
            ArmCall::CCmseNonSecureCall | ArmCall::CCmseNonSecureEntry => llvm::CCallConv,
        },
        CanonAbi::X86(x86_call) => match x86_call {
            X86Call::Fastcall => llvm::X86FastcallCallConv,
            X86Call::Stdcall => llvm::X86StdcallCallConv,
            X86Call::SysV64 => llvm::X86_64_SysV,
            X86Call::Thiscall => llvm::X86_ThisCall,
            X86Call::Vectorcall => llvm::X86_VectorCall,
            X86Call::Win64 => llvm::X86_64_Win64,
        },
    }
}
