cmse: don't use BackendRepr when checking return type
This commit is contained in:
parent
66daca1a85
commit
43ee28aa16
3 changed files with 60 additions and 39 deletions
|
|
@ -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,32 @@ 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>, mut 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;
|
||||
};
|
||||
// Find the wrapped inner type of a transparent wrapper.
|
||||
loop {
|
||||
match layout.ty.kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.repr().transparent() => {
|
||||
// Find the non-1-ZST field, and recurse.
|
||||
(_, layout) = layout.non_1zst_field(&cx).unwrap();
|
||||
}
|
||||
// Not a transparent type, no further unfolding.
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
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.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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue