use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size}; use crate::callconv::{ArgAbi, FnAbi, Reg}; use crate::spec::{HasTargetSpec, RustcAbi}; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing pub(crate) fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| { match a.layout.backend_repr { BackendRepr::Memory { sized: false } => {} BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => { match a.layout.size.bits() { 8 => a.cast_to(Reg::i8()), 16 => a.cast_to(Reg::i16()), 32 => a.cast_to(Reg::i32()), 64 => a.cast_to(Reg::i64()), _ => a.make_indirect(), } } BackendRepr::SimdVector { .. } => { // FIXME(eddyb) there should be a size cap here // (probably what clang calls "illegal vectors"). } BackendRepr::Scalar(scalar) => { if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) { if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) { // Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing. } else { // `i128` is returned in xmm0 by Clang and GCC // FIXME(#134288): This may change for the `-msvc` targets in the future. let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) }; a.cast_to(reg); } } else if a.layout.size.bytes() > 8 && !matches!(scalar.primitive(), Primitive::Float(Float::F128)) { // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up // with what LLVM expects. a.make_indirect(); } else { a.extend_integer_width_to(32); } } } }; if !fn_abi.ret.is_ignore() { fixup(&mut fn_abi.ret, true); } for arg in fn_abi.args.iter_mut() { if arg.is_ignore() && arg.layout.is_zst() { // Windows ABIs do not talk about ZST since such types do not exist in MSVC. // In that sense we can do whatever we want here, and maybe we should throw an error // (but of course that would be a massive breaking change now). // We try to match clang and gcc (which allow ZST is their windows-gnu targets), so we // pass ZST via pointer indirection. arg.make_indirect_from_ignore(); continue; } fixup(arg, false); } // FIXME: We should likely also do something about ZST return types, similar to above. // However, that's non-trivial due to `()`. // See . }