on Windows, consistently pass ZST by-ref
This commit is contained in:
parent
d760bb6603
commit
675a1036ca
4 changed files with 22 additions and 57 deletions
|
@ -665,11 +665,11 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
||||||
"x86_64" => match abi {
|
"x86_64" => match abi {
|
||||||
ExternAbi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
|
ExternAbi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
|
||||||
ExternAbi::Win64 { .. } | ExternAbi::Vectorcall { .. } => {
|
ExternAbi::Win64 { .. } | ExternAbi::Vectorcall { .. } => {
|
||||||
x86_win64::compute_abi_info(cx, self, abi)
|
x86_win64::compute_abi_info(cx, self)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if cx.target_spec().is_like_windows {
|
if cx.target_spec().is_like_windows {
|
||||||
x86_win64::compute_abi_info(cx, self, abi)
|
x86_win64::compute_abi_info(cx, self)
|
||||||
} else {
|
} else {
|
||||||
x86_64::compute_abi_info(cx, self)
|
x86_64::compute_abi_info(cx, self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
use rustc_abi::{BackendRepr, ExternAbi, Float, Primitive};
|
use rustc_abi::{BackendRepr, Float, Primitive};
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg};
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
|
// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
|
||||||
|
|
||||||
pub(crate) fn compute_abi_info<Ty>(
|
pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
|
||||||
cx: &impl HasTargetSpec,
|
|
||||||
fn_abi: &mut FnAbi<'_, Ty>,
|
|
||||||
abi: ExternAbi,
|
|
||||||
) {
|
|
||||||
let fixup = |a: &mut ArgAbi<'_, Ty>| {
|
let fixup = |a: &mut ArgAbi<'_, Ty>| {
|
||||||
match a.layout.backend_repr {
|
match a.layout.backend_repr {
|
||||||
BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {}
|
BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {}
|
||||||
|
@ -48,16 +44,14 @@ pub(crate) fn compute_abi_info<Ty>(
|
||||||
// Windows ABIs do not talk about ZST since such types do not exist in MSVC.
|
// 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
|
// 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).
|
// (but of course that would be a massive breaking change now).
|
||||||
// We try to match clang and gcc, so we make windows-gnu and the native
|
// We try to match clang and gcc (which allow ZST is their windows-gnu targets), so we
|
||||||
// Windows ABIs (i.e., everything except for `extern "C"`) pass ZST via
|
// pass ZST via pointer indirection.
|
||||||
// pointer indirection. windows-msvc `extern "C"` still skips ZST.
|
|
||||||
if (cx.target_spec().os == "windows" && cx.target_spec().env == "gnu")
|
|
||||||
|| !matches!(abi, ExternAbi::C { .. })
|
|
||||||
{
|
|
||||||
arg.make_indirect_from_ignore();
|
arg.make_indirect_from_ignore();
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fixup(arg);
|
fixup(arg);
|
||||||
}
|
}
|
||||||
|
// FIXME: We should likely also do something about ZST return types, similar to above.
|
||||||
|
// However, that's non-trivial due to `()`.
|
||||||
|
// See <https://github.com/rust-lang/unsafe-code-guidelines/issues/552>.
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,10 +267,8 @@ fn fn_sig_for_fn_abi<'tcx>(
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv {
|
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv {
|
||||||
let target = &tcx.sess.target;
|
|
||||||
|
|
||||||
use rustc_abi::ExternAbi::*;
|
use rustc_abi::ExternAbi::*;
|
||||||
match target.adjust_abi(abi, c_variadic) {
|
match tcx.sess.target.adjust_abi(abi, c_variadic) {
|
||||||
RustIntrinsic | Rust | RustCall => Conv::Rust,
|
RustIntrinsic | Rust | RustCall => Conv::Rust,
|
||||||
|
|
||||||
// This is intentionally not using `Conv::Cold`, as that has to preserve
|
// This is intentionally not using `Conv::Cold`, as that has to preserve
|
||||||
|
@ -281,37 +279,10 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv
|
||||||
System { .. } => bug!("system abi should be selected elsewhere"),
|
System { .. } => bug!("system abi should be selected elsewhere"),
|
||||||
EfiApi => bug!("eficall abi should be selected elsewhere"),
|
EfiApi => bug!("eficall abi should be selected elsewhere"),
|
||||||
|
|
||||||
// See commentary in `is_abi_supported`: we map these to "C" on targets
|
Stdcall { .. } => Conv::X86Stdcall,
|
||||||
// where they do not make sense.
|
Fastcall { .. } => Conv::X86Fastcall,
|
||||||
Stdcall { .. } => {
|
Vectorcall { .. } => Conv::X86VectorCall,
|
||||||
if target.arch == "x86" {
|
Thiscall { .. } => Conv::X86ThisCall,
|
||||||
Conv::X86Stdcall
|
|
||||||
} else {
|
|
||||||
Conv::C
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Fastcall { .. } => {
|
|
||||||
if target.arch == "x86" {
|
|
||||||
Conv::X86Fastcall
|
|
||||||
} else {
|
|
||||||
Conv::C
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vectorcall { .. } => {
|
|
||||||
if ["x86", "x86_64"].contains(&&target.arch[..]) {
|
|
||||||
Conv::X86VectorCall
|
|
||||||
} else {
|
|
||||||
Conv::C
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Thiscall { .. } => {
|
|
||||||
if target.arch == "x86" {
|
|
||||||
Conv::X86ThisCall
|
|
||||||
} else {
|
|
||||||
Conv::C
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
C { .. } => Conv::C,
|
C { .. } => Conv::C,
|
||||||
Unadjusted => Conv::C,
|
Unadjusted => Conv::C,
|
||||||
Win64 { .. } => Conv::X86_64Win64,
|
Win64 { .. } => Conv::X86_64Win64,
|
||||||
|
|
|
@ -23,16 +23,16 @@ trait Sized {}
|
||||||
// Make sure the argument is always passed when explicitly requesting a Windows ABI.
|
// Make sure the argument is always passed when explicitly requesting a Windows ABI.
|
||||||
// Our goal here is to match clang: <https://clang.godbolt.org/z/Wr4jMWq3P>.
|
// Our goal here is to match clang: <https://clang.godbolt.org/z/Wr4jMWq3P>.
|
||||||
|
|
||||||
// CHECK: define win64cc void @pass_zst_win64(ptr {{.*}})
|
// CHECK: define win64cc void @pass_zst_win64(ptr {{[^,]*}})
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "win64" fn pass_zst_win64(_: ()) {}
|
extern "win64" fn pass_zst_win64(_: ()) {}
|
||||||
|
|
||||||
// CHECK: define x86_vectorcallcc void @pass_zst_vectorcall(ptr {{.*}})
|
// CHECK: define x86_vectorcallcc void @pass_zst_vectorcall(ptr {{[^,]*}})
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "vectorcall" fn pass_zst_vectorcall(_: ()) {}
|
extern "vectorcall" fn pass_zst_vectorcall(_: ()) {}
|
||||||
|
|
||||||
// windows-gnu: define void @pass_zst_fastcall(ptr {{.*}})
|
// windows-gnu: define void @pass_zst_fastcall(ptr {{[^,]*}})
|
||||||
// windows-msvc: define void @pass_zst_fastcall(ptr {{.*}})
|
// windows-msvc: define void @pass_zst_fastcall(ptr {{[^,]*}})
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[cfg(windows)] // "fastcall" is not valid on 64bit Linux
|
#[cfg(windows)] // "fastcall" is not valid on 64bit Linux
|
||||||
extern "fastcall" fn pass_zst_fastcall(_: ()) {}
|
extern "fastcall" fn pass_zst_fastcall(_: ()) {}
|
||||||
|
@ -43,10 +43,10 @@ extern "fastcall" fn pass_zst_fastcall(_: ()) {}
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "sysv64" fn pass_zst_sysv64(_: ()) {}
|
extern "sysv64" fn pass_zst_sysv64(_: ()) {}
|
||||||
|
|
||||||
// For `extern "C"` functions, ZST are ignored on windows-msvc.
|
// For `extern "C"` functions, ZST are ignored on Linux put passed on Windows.
|
||||||
|
|
||||||
// linux: define void @pass_zst_c()
|
// linux: define void @pass_zst_c()
|
||||||
// windows-msvc: define void @pass_zst_c()
|
// windows-msvc: define void @pass_zst_c(ptr {{[^,]*}})
|
||||||
// windows-gnu: define void @pass_zst_c(ptr {{.*}})
|
// windows-gnu: define void @pass_zst_c(ptr {{[^,]*}})
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn pass_zst_c(_: ()) {}
|
extern "C" fn pass_zst_c(_: ()) {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue