Rollup merge of #151590 - folkertdev:cmse-unwrap-transparent, r=davidtwco
cmse: don't use `BackendRepr` when checking return type tracking issue: https://github.com/rust-lang/rust/issues/81391 tracking issue: https://github.com/rust-lang/rust/issues/75835 r? davidtwco cc @RalfJung context: https://github.com/rust-lang/rfcs/pull/3884#discussion_r2715791429 I believe this is more reliable, and no longer relies on `BackendRepr`. I also added a test specifically for using `repr(Rust)`.
This commit is contained in:
commit
9f0eba2a06
7 changed files with 102 additions and 46 deletions
|
|
@ -290,7 +290,19 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||
/// function call isn't allowed (a.k.a. `va_list`).
|
||||
///
|
||||
/// This function handles transparent types automatically.
|
||||
pub fn pass_indirectly_in_non_rustic_abis<C>(mut self, cx: &C) -> bool
|
||||
pub fn pass_indirectly_in_non_rustic_abis<C>(self, cx: &C) -> bool
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
{
|
||||
let base = self.peel_transparent_wrappers(cx);
|
||||
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base)
|
||||
}
|
||||
|
||||
/// Recursively peel away transparent wrappers, returning the inner value.
|
||||
///
|
||||
/// The return value is not `repr(transparent)` and/or does
|
||||
/// not have a non-1zst field.
|
||||
pub fn peel_transparent_wrappers<C>(mut self, cx: &C) -> Self
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
{
|
||||
|
|
@ -300,7 +312,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||
self = field;
|
||||
}
|
||||
|
||||
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self)
|
||||
self
|
||||
}
|
||||
|
||||
/// Finds the one field that is not a 1-ZST.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use rustc_abi::{BackendRepr, ExternAbi, Float, Integer, Primitive, Scalar};
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
|
||||
use rustc_middle::ty::layout::{LayoutCx, LayoutError, TyAndLayout};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
|
@ -150,8 +150,9 @@ fn is_valid_cmse_output<'tcx>(
|
|||
|
||||
let typing_env = ty::TypingEnv::fully_monomorphized();
|
||||
let layout = tcx.layout_of(typing_env.as_query_input(return_type))?;
|
||||
let layout_cx = LayoutCx::new(tcx, typing_env);
|
||||
|
||||
if !is_valid_cmse_output_layout(layout) {
|
||||
if !is_valid_cmse_output_layout(layout_cx, layout) {
|
||||
dcx.emit_err(errors::CmseOutputStackSpill { span: fn_decl.output.span(), abi });
|
||||
}
|
||||
|
||||
|
|
@ -159,25 +160,20 @@ fn is_valid_cmse_output<'tcx>(
|
|||
}
|
||||
|
||||
/// Returns whether the output will fit into the available registers
|
||||
fn is_valid_cmse_output_layout<'tcx>(layout: TyAndLayout<'tcx>) -> bool {
|
||||
fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) -> bool {
|
||||
let size = layout.layout.size().bytes();
|
||||
|
||||
if size <= 4 {
|
||||
return true;
|
||||
} else if size > 8 {
|
||||
} else if size != 8 {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Accept scalar 64-bit types.
|
||||
let BackendRepr::Scalar(scalar) = layout.layout.backend_repr else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Scalar::Initialized { value, .. } = scalar else {
|
||||
return false;
|
||||
};
|
||||
|
||||
matches!(value, Primitive::Int(Integer::I64, _) | Primitive::Float(Float::F64))
|
||||
// Accept (transparently wrapped) scalar 64-bit primitives.
|
||||
matches!(
|
||||
layout.peel_transparent_wrappers(&cx).ty.kind(),
|
||||
ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64)
|
||||
)
|
||||
}
|
||||
|
||||
fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ use minicore::*;
|
|||
#[repr(C)]
|
||||
pub struct ReprCU64(u64);
|
||||
|
||||
#[repr(Rust)]
|
||||
pub struct ReprRustU64(u64);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ReprCBytes(u8, u8, u8, u8, u8);
|
||||
|
||||
|
|
@ -25,10 +28,11 @@ pub struct ReprCAlign16(u16);
|
|||
#[no_mangle]
|
||||
pub fn test(
|
||||
f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798]
|
||||
f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798]
|
||||
f3: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798]
|
||||
f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798]
|
||||
f5: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798]
|
||||
f2: extern "cmse-nonsecure-call" fn() -> ReprRustU64, //~ ERROR [E0798]
|
||||
f3: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798]
|
||||
f4: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798]
|
||||
f5: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798]
|
||||
f6: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798]
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:37:48
|
||||
--> $DIR/return-via-stack.rs:41:48
|
||||
|
|
||||
LL | u128: extern "cmse-nonsecure-call" fn() -> u128,
|
||||
| ^^^^ this type doesn't fit in the available registers
|
||||
|
|
@ -8,7 +8,7 @@ LL | u128: extern "cmse-nonsecure-call" fn() -> u128,
|
|||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:38:48
|
||||
--> $DIR/return-via-stack.rs:42:48
|
||||
|
|
||||
LL | i128: extern "cmse-nonsecure-call" fn() -> i128,
|
||||
| ^^^^ this type doesn't fit in the available registers
|
||||
|
|
@ -17,7 +17,7 @@ LL | i128: extern "cmse-nonsecure-call" fn() -> i128,
|
|||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:27:46
|
||||
--> $DIR/return-via-stack.rs:30:46
|
||||
|
|
||||
LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64,
|
||||
| ^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
@ -26,43 +26,52 @@ LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64,
|
|||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:28:46
|
||||
--> $DIR/return-via-stack.rs:31:46
|
||||
|
|
||||
LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes,
|
||||
| ^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:29:46
|
||||
|
|
||||
LL | f3: extern "cmse-nonsecure-call" fn() -> U64Compound,
|
||||
LL | f2: extern "cmse-nonsecure-call" fn() -> ReprRustU64,
|
||||
| ^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:30:46
|
||||
--> $DIR/return-via-stack.rs:32:46
|
||||
|
|
||||
LL | f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16,
|
||||
LL | f3: extern "cmse-nonsecure-call" fn() -> ReprCBytes,
|
||||
| ^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:33:46
|
||||
|
|
||||
LL | f4: extern "cmse-nonsecure-call" fn() -> U64Compound,
|
||||
| ^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:34:46
|
||||
|
|
||||
LL | f5: extern "cmse-nonsecure-call" fn() -> ReprCAlign16,
|
||||
| ^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:31:46
|
||||
--> $DIR/return-via-stack.rs:35:46
|
||||
|
|
||||
LL | f5: extern "cmse-nonsecure-call" fn() -> [u8; 5],
|
||||
LL | f6: extern "cmse-nonsecure-call" fn() -> [u8; 5],
|
||||
| ^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:53:46
|
||||
--> $DIR/return-via-stack.rs:57:46
|
||||
|
|
||||
LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64,
|
||||
| ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
@ -71,7 +80,7 @@ LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64,
|
|||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
|
||||
--> $DIR/return-via-stack.rs:54:46
|
||||
--> $DIR/return-via-stack.rs:58:46
|
||||
|
|
||||
LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64,
|
||||
| ^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
||||
|
|
@ -79,6 +88,6 @@ LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64,
|
|||
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
|
||||
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0798`.
|
||||
|
|
|
|||
|
|
@ -24,3 +24,24 @@ pub extern "cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [
|
|||
#[no_mangle]
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798]
|
||||
|
||||
struct Four {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
d: u32,
|
||||
}
|
||||
|
||||
struct Five {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
d: u32,
|
||||
e: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "cmse-nonsecure-entry" fn four(_: Four) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "cmse-nonsecure-entry" fn five(_: Five) {} //~ ERROR [E0798]
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@ LL | pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {}
|
|||
|
|
||||
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit argument registers
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers
|
||||
--> $DIR/params-via-stack.rs:47:46
|
||||
|
|
||||
LL | pub extern "cmse-nonsecure-entry" fn five(_: Five) {}
|
||||
| ^^^^ does not fit in the available registers
|
||||
|
|
||||
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit argument registers
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0798`.
|
||||
|
|
|
|||
|
|
@ -40,9 +40,15 @@ pub extern "cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {}
|
|||
#[no_mangle]
|
||||
pub extern "cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct<u64>, _: U32Compound) {}
|
||||
#[no_mangle]
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
#[expect(improper_ctypes_definitions)]
|
||||
pub extern "cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {}
|
||||
|
||||
// With zero-sized types we can actually have more than 4 arguments.
|
||||
#[expect(improper_ctypes_definitions)]
|
||||
pub extern "cmse-nonsecure-entry" fn inputs8(_: (), _: (), _: (), _: (), _: ()) {}
|
||||
#[expect(improper_ctypes_definitions)]
|
||||
pub extern "cmse-nonsecure-entry" fn inputs9(_: (), _: (), _: (), _: (), _: ()) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "cmse-nonsecure-entry" fn outputs1() -> u32 {
|
||||
0
|
||||
|
|
@ -69,8 +75,8 @@ pub extern "cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct<u64> {
|
|||
ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () }
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "cmse-nonsecure-entry" fn outputs7(
|
||||
) -> ReprTransparentStruct<ReprTransparentStruct<u64>> {
|
||||
pub extern "cmse-nonsecure-entry" fn outputs7() -> ReprTransparentStruct<ReprTransparentStruct<u64>>
|
||||
{
|
||||
ReprTransparentStruct {
|
||||
_marker1: (),
|
||||
_marker2: (),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue