Skip to main content

rustc_target/callconv/
x86_win64.rs

1use rustc_abi::{BackendRepr, Integer, Primitive, Size, TyAbiInterface};
2
3use crate::callconv::{ArgAbi, FnAbi, Reg};
4use crate::spec::{HasTargetSpec, RustcAbi};
5
6// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
7
8pub(crate) fn compute_abi_info<'a, Ty, C: HasTargetSpec>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
9where
10    Ty: TyAbiInterface<'a, C> + Copy,
11{
12    let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| {
13        match a.layout.backend_repr {
14            BackendRepr::Memory { sized: false } => {}
15            BackendRepr::ScalarPair { .. } | BackendRepr::Memory { sized: true } => {
16                match a.layout.size.bits() {
17                    8 => a.cast_to(Reg::i8()),
18                    16 => a.cast_to(Reg::i16()),
19                    32 => a.cast_to(Reg::i32()),
20                    64 => 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::SimdScalableVector { .. } => {
    ::core::panicking::panic_fmt(format_args!("scalable vectors are unsupported"));
}panic!("scalable vectors are unsupported"),
29            BackendRepr::Scalar(scalar) => {
30                if is_ret && #[allow(non_exhaustive_omitted_patterns)] match scalar.primitive() {
    Primitive::Int(Integer::I128, _) => true,
    _ => false,
}matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) {
31                    if cx.target_spec().rustc_abi == Some(RustcAbi::Softfloat) {
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.
36                        a.cast_to(Reg::opaque_vector(Size::from_bits(128)));
37                    }
38                } else if a.layout.size.bytes() > 8 {
39                    a.make_indirect();
40                } else {
41                    a.extend_integer_width_to(32);
42                }
43            }
44        }
45    };
46
47    if !fn_abi.ret.is_ignore() {
48        fixup(&mut fn_abi.ret, true);
49    }
50
51    for arg in fn_abi.args.iter_mut() {
52        if arg.is_ignore() && arg.layout.is_zst() {
53            // Windows ABIs do not talk about ZST since such types do not exist in MSVC.
54            // In that sense we can do whatever we want here, and maybe we should throw an error
55            // (but of course that would be a massive breaking change now).
56            // We try to match clang and gcc (which allow ZST is their windows-gnu targets), so we
57            // pass ZST via pointer indirection.
58            arg.make_indirect_from_ignore();
59            continue;
60        }
61        if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
62            arg.make_indirect();
63            continue;
64        }
65        fixup(arg, false);
66    }
67    // FIXME: We should likely also do something about ZST return types, similar to above.
68    // However, that's non-trivial due to `()`.
69    // See <https://github.com/rust-lang/unsafe-code-guidelines/issues/552>.
70}