Rollup merge of #132729 - bjorn3:fn_abi_extra_sanity_checks, r=compiler-errors
Make fn_abi_sanity_check a bit stricter The Rust ABI must ignore all ZST arguments, all ignored arguments must be either ZST or uninhabited. And finally ScalarPair should never be passed as PassMode::Direct.
This commit is contained in:
commit
bf0de1f308
@ -463,43 +463,64 @@ fn fn_arg_sanity_check<'tcx>(
|
|||||||
arg: &ArgAbi<'tcx, Ty<'tcx>>,
|
arg: &ArgAbi<'tcx, Ty<'tcx>>,
|
||||||
) {
|
) {
|
||||||
let tcx = cx.tcx();
|
let tcx = cx.tcx();
|
||||||
|
|
||||||
|
if spec_abi == ExternAbi::Rust
|
||||||
|
|| spec_abi == ExternAbi::RustCall
|
||||||
|
|| spec_abi == ExternAbi::RustCold
|
||||||
|
{
|
||||||
|
if arg.layout.is_zst() {
|
||||||
|
// Casting closures to function pointers depends on ZST closure types being
|
||||||
|
// omitted entirely in the calling convention.
|
||||||
|
assert!(arg.is_ignore());
|
||||||
|
}
|
||||||
|
if let PassMode::Indirect { on_stack, .. } = arg.mode {
|
||||||
|
assert!(!on_stack, "rust abi shouldn't use on_stack");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match &arg.mode {
|
match &arg.mode {
|
||||||
PassMode::Ignore => {}
|
PassMode::Ignore => {
|
||||||
|
assert!(arg.layout.is_zst() || arg.layout.is_uninhabited());
|
||||||
|
}
|
||||||
PassMode::Direct(_) => {
|
PassMode::Direct(_) => {
|
||||||
// Here the Rust type is used to determine the actual ABI, so we have to be very
|
// Here the Rust type is used to determine the actual ABI, so we have to be very
|
||||||
// careful. Scalar/ScalarPair is fine, since backends will generally use
|
// careful. Scalar/Vector is fine, since backends will generally use
|
||||||
// `layout.abi` and ignore everything else. We should just reject `Aggregate`
|
// `layout.backend_repr` and ignore everything else. We should just reject
|
||||||
// entirely here, but some targets need to be fixed first.
|
//`Aggregate` entirely here, but some targets need to be fixed first.
|
||||||
if matches!(arg.layout.backend_repr, BackendRepr::Memory { .. }) {
|
match arg.layout.backend_repr {
|
||||||
// For an unsized type we'd only pass the sized prefix, so there is no universe
|
BackendRepr::Uninhabited
|
||||||
// in which we ever want to allow this.
|
| BackendRepr::Scalar(_)
|
||||||
assert!(
|
| BackendRepr::Vector { .. } => {}
|
||||||
arg.layout.is_sized(),
|
BackendRepr::ScalarPair(..) => {
|
||||||
"`PassMode::Direct` for unsized type in ABI: {:#?}",
|
panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty)
|
||||||
fn_abi
|
}
|
||||||
);
|
BackendRepr::Memory { sized } => {
|
||||||
// This really shouldn't happen even for sized aggregates, since
|
// For an unsized type we'd only pass the sized prefix, so there is no universe
|
||||||
// `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an
|
// in which we ever want to allow this.
|
||||||
// LLVM type. This means all sorts of Rust type details leak into the ABI.
|
assert!(sized, "`PassMode::Direct` for unsized type in ABI: {:#?}", fn_abi);
|
||||||
// However wasm sadly *does* currently use this mode so we have to allow it --
|
// This really shouldn't happen even for sized aggregates, since
|
||||||
// but we absolutely shouldn't let any more targets do that.
|
// `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an
|
||||||
// (Also see <https://github.com/rust-lang/rust/issues/115666>.)
|
// LLVM type. This means all sorts of Rust type details leak into the ABI.
|
||||||
//
|
// However wasm sadly *does* currently use this mode so we have to allow it --
|
||||||
// The unstable abi `PtxKernel` also uses Direct for now.
|
// but we absolutely shouldn't let any more targets do that.
|
||||||
// It needs to switch to something else before stabilization can happen.
|
// (Also see <https://github.com/rust-lang/rust/issues/115666>.)
|
||||||
// (See issue: https://github.com/rust-lang/rust/issues/117271)
|
//
|
||||||
assert!(
|
// The unstable abi `PtxKernel` also uses Direct for now.
|
||||||
matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64")
|
// It needs to switch to something else before stabilization can happen.
|
||||||
|| matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted),
|
// (See issue: https://github.com/rust-lang/rust/issues/117271)
|
||||||
"`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\
|
assert!(
|
||||||
|
matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64")
|
||||||
|
|| matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted),
|
||||||
|
"`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\
|
||||||
Problematic type: {:#?}",
|
Problematic type: {:#?}",
|
||||||
arg.layout,
|
arg.layout,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PassMode::Pair(_, _) => {
|
PassMode::Pair(_, _) => {
|
||||||
// Similar to `Direct`, we need to make sure that backends use `layout.abi` and
|
// Similar to `Direct`, we need to make sure that backends use `layout.backend_repr`
|
||||||
// ignore the rest of the layout.
|
// and ignore the rest of the layout.
|
||||||
assert!(
|
assert!(
|
||||||
matches!(arg.layout.backend_repr, BackendRepr::ScalarPair(..)),
|
matches!(arg.layout.backend_repr, BackendRepr::ScalarPair(..)),
|
||||||
"PassMode::Pair for type {}",
|
"PassMode::Pair for type {}",
|
||||||
|
Loading…
Reference in New Issue
Block a user