1use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size, TyAbiInterface};
23use crate::callconv::{ArgAbi, FnAbi, Reg};
4use crate::spec::{HasTargetSpec, RustcAbi};
56// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
78pub(crate) fn compute_abi_info<'a, Ty, C: HasTargetSpec>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
9where
10Ty: TyAbiInterface<'a, C> + Copy,
11{
12let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| {
13match a.layout.backend_repr {
14 BackendRepr::Memory { sized: false } => {}
15 BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => {
16match a.layout.size.bits() {
178 => a.cast_to(Reg::i8()),
1816 => a.cast_to(Reg::i16()),
1932 => a.cast_to(Reg::i32()),
2064 => a.cast_to(Reg::i64()),
21_ => a.make_indirect(),
22 }
23 }
24 BackendRepr::SimdVector { .. } => {
25// FIXME(eddyb) there should be a size cap here
26 // (probably what clang calls "illegal vectors").
27}
28 BackendRepr::ScalableVector { .. } => {
::core::panicking::panic_fmt(format_args!("scalable vectors are unsupported"));
}panic!("scalable vectors are unsupported"),
29 BackendRepr::Scalar(scalar) => {
30if is_ret && #[allow(non_exhaustive_omitted_patterns)] match scalar.primitive() {
Primitive::Int(Integer::I128, _) => true,
_ => false,
}matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) {
31if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) {
32// Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing.
33} else {
34// `i128` is returned in xmm0 by Clang and GCC
35 // FIXME(#134288): This may change for the `-msvc` targets in the future.
36let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) };
37a.cast_to(reg);
38 }
39 } else if a.layout.size.bytes() > 8
40 && !#[allow(non_exhaustive_omitted_patterns)] match scalar.primitive() {
Primitive::Float(Float::F128) => true,
_ => false,
}matches!(scalar.primitive(), Primitive::Float(Float::F128))41 {
42// Match what LLVM does for `f128` so that `compiler-builtins` builtins match up
43 // with what LLVM expects.
44a.make_indirect();
45 } else {
46a.extend_integer_width_to(32);
47 }
48 }
49 }
50 };
5152if !fn_abi.ret.is_ignore() {
53fixup(&mut fn_abi.ret, true);
54 }
5556for arg in fn_abi.args.iter_mut() {
57if arg.is_ignore() && arg.layout.is_zst() {
58// Windows ABIs do not talk about ZST since such types do not exist in MSVC.
59 // In that sense we can do whatever we want here, and maybe we should throw an error
60 // (but of course that would be a massive breaking change now).
61 // We try to match clang and gcc (which allow ZST is their windows-gnu targets), so we
62 // pass ZST via pointer indirection.
63arg.make_indirect_from_ignore();
64continue;
65 }
66if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
67 arg.make_indirect();
68continue;
69 }
70 fixup(arg, false);
71 }
72// FIXME: We should likely also do something about ZST return types, similar to above.
73 // However, that's non-trivial due to `()`.
74 // See <https://github.com/rust-lang/unsafe-code-guidelines/issues/552>.
75}