Skip to content

Commit d90de95

Browse files
authored
Unrolled build for #151590
Rollup merge of #151590 - folkertdev:cmse-unwrap-transparent, r=davidtwco cmse: don't use `BackendRepr` when checking return type tracking issue: #81391 tracking issue: #75835 r? davidtwco cc @RalfJung context: rust-lang/rfcs#3884 (comment) I believe this is more reliable, and no longer relies on `BackendRepr`. I also added a test specifically for using `repr(Rust)`.
2 parents 55bfca7 + eb9d515 commit d90de95

File tree

7 files changed

+95
-39
lines changed

7 files changed

+95
-39
lines changed

compiler/rustc_abi/src/layout/ty.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,19 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
290290
/// function call isn't allowed (a.k.a. `va_list`).
291291
///
292292
/// This function handles transparent types automatically.
293-
pub fn pass_indirectly_in_non_rustic_abis<C>(mut self, cx: &C) -> bool
293+
pub fn pass_indirectly_in_non_rustic_abis<C>(self, cx: &C) -> bool
294+
where
295+
Ty: TyAbiInterface<'a, C> + Copy,
296+
{
297+
let base = self.peel_transparent_wrappers(cx);
298+
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base)
299+
}
300+
301+
/// Recursively peel away transparent wrappers, returning the inner value.
302+
///
303+
/// The return value is not `repr(transparent)` and/or does
304+
/// not have a non-1zst field.
305+
pub fn peel_transparent_wrappers<C>(mut self, cx: &C) -> Self
294306
where
295307
Ty: TyAbiInterface<'a, C> + Copy,
296308
{
@@ -300,7 +312,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
300312
self = field;
301313
}
302314

303-
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self)
315+
self
304316
}
305317

306318
/// Finds the one field that is not a 1-ZST.

compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use rustc_abi::{BackendRepr, ExternAbi, Float, Integer, Primitive, Scalar};
1+
use rustc_abi::ExternAbi;
22
use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err};
33
use rustc_hir::{self as hir, HirId};
44
use rustc_middle::bug;
5-
use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
5+
use rustc_middle::ty::layout::{LayoutCx, LayoutError, TyAndLayout};
66
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
77
use rustc_span::Span;
88

@@ -150,34 +150,30 @@ fn is_valid_cmse_output<'tcx>(
150150

151151
let typing_env = ty::TypingEnv::fully_monomorphized();
152152
let layout = tcx.layout_of(typing_env.as_query_input(return_type))?;
153+
let layout_cx = LayoutCx::new(tcx, typing_env);
153154

154-
if !is_valid_cmse_output_layout(layout) {
155+
if !is_valid_cmse_output_layout(layout_cx, layout) {
155156
dcx.emit_err(errors::CmseOutputStackSpill { span: fn_decl.output.span(), abi });
156157
}
157158

158159
Ok(())
159160
}
160161

161162
/// Returns whether the output will fit into the available registers
162-
fn is_valid_cmse_output_layout<'tcx>(layout: TyAndLayout<'tcx>) -> bool {
163+
fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) -> bool {
163164
let size = layout.layout.size().bytes();
164165

165166
if size <= 4 {
166167
return true;
167-
} else if size > 8 {
168+
} else if size != 8 {
168169
return false;
169170
}
170171

171-
// Accept scalar 64-bit types.
172-
let BackendRepr::Scalar(scalar) = layout.layout.backend_repr else {
173-
return false;
174-
};
175-
176-
let Scalar::Initialized { value, .. } = scalar else {
177-
return false;
178-
};
179-
180-
matches!(value, Primitive::Int(Integer::I64, _) | Primitive::Float(Float::F64))
172+
// Accept (transparently wrapped) scalar 64-bit primitives.
173+
matches!(
174+
layout.peel_transparent_wrappers(&cx).ty.kind(),
175+
ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64)
176+
)
181177
}
182178

183179
fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool {

tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use minicore::*;
1313
#[repr(C)]
1414
pub struct ReprCU64(u64);
1515

16+
#[repr(Rust)]
17+
pub struct ReprRustU64(u64);
18+
1619
#[repr(C)]
1720
pub struct ReprCBytes(u8, u8, u8, u8, u8);
1821

@@ -25,10 +28,11 @@ pub struct ReprCAlign16(u16);
2528
#[no_mangle]
2629
pub fn test(
2730
f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798]
28-
f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798]
29-
f3: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798]
30-
f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798]
31-
f5: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798]
31+
f2: extern "cmse-nonsecure-call" fn() -> ReprRustU64, //~ ERROR [E0798]
32+
f3: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798]
33+
f4: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798]
34+
f5: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798]
35+
f6: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798]
3236
) {
3337
}
3438

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
2-
--> $DIR/return-via-stack.rs:37:48
2+
--> $DIR/return-via-stack.rs:41:48
33
|
44
LL | u128: extern "cmse-nonsecure-call" fn() -> u128,
55
| ^^^^ this type doesn't fit in the available registers
@@ -8,7 +8,7 @@ LL | u128: extern "cmse-nonsecure-call" fn() -> u128,
88
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
99

1010
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
11-
--> $DIR/return-via-stack.rs:38:48
11+
--> $DIR/return-via-stack.rs:42:48
1212
|
1313
LL | i128: extern "cmse-nonsecure-call" fn() -> i128,
1414
| ^^^^ this type doesn't fit in the available registers
@@ -17,7 +17,7 @@ LL | i128: extern "cmse-nonsecure-call" fn() -> i128,
1717
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
1818

1919
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
20-
--> $DIR/return-via-stack.rs:27:46
20+
--> $DIR/return-via-stack.rs:30:46
2121
|
2222
LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64,
2323
| ^^^^^^^^ this type doesn't fit in the available registers
@@ -26,43 +26,52 @@ LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64,
2626
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
2727

2828
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
29-
--> $DIR/return-via-stack.rs:28:46
29+
--> $DIR/return-via-stack.rs:31:46
30+
|
31+
LL | f2: extern "cmse-nonsecure-call" fn() -> ReprRustU64,
32+
| ^^^^^^^^^^^ this type doesn't fit in the available registers
3033
|
31-
LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes,
34+
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
35+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
36+
37+
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
38+
--> $DIR/return-via-stack.rs:32:46
39+
|
40+
LL | f3: extern "cmse-nonsecure-call" fn() -> ReprCBytes,
3241
| ^^^^^^^^^^ this type doesn't fit in the available registers
3342
|
3443
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
3544
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
3645

3746
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
38-
--> $DIR/return-via-stack.rs:29:46
47+
--> $DIR/return-via-stack.rs:33:46
3948
|
40-
LL | f3: extern "cmse-nonsecure-call" fn() -> U64Compound,
49+
LL | f4: extern "cmse-nonsecure-call" fn() -> U64Compound,
4150
| ^^^^^^^^^^^ this type doesn't fit in the available registers
4251
|
4352
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
4453
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
4554

4655
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
47-
--> $DIR/return-via-stack.rs:30:46
56+
--> $DIR/return-via-stack.rs:34:46
4857
|
49-
LL | f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16,
58+
LL | f5: extern "cmse-nonsecure-call" fn() -> ReprCAlign16,
5059
| ^^^^^^^^^^^^ this type doesn't fit in the available registers
5160
|
5261
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
5362
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
5463

5564
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
56-
--> $DIR/return-via-stack.rs:31:46
65+
--> $DIR/return-via-stack.rs:35:46
5766
|
58-
LL | f5: extern "cmse-nonsecure-call" fn() -> [u8; 5],
67+
LL | f6: extern "cmse-nonsecure-call" fn() -> [u8; 5],
5968
| ^^^^^^^ this type doesn't fit in the available registers
6069
|
6170
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
6271
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
6372

6473
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
65-
--> $DIR/return-via-stack.rs:53:46
74+
--> $DIR/return-via-stack.rs:57:46
6675
|
6776
LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64,
6877
| ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
@@ -71,14 +80,14 @@ LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64,
7180
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
7281

7382
error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers
74-
--> $DIR/return-via-stack.rs:54:46
83+
--> $DIR/return-via-stack.rs:58:46
7584
|
7685
LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64,
7786
| ^^^^^^^^^^^^^ this type doesn't fit in the available registers
7887
|
7988
= note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers
8089
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
8190

82-
error: aborting due to 9 previous errors
91+
error: aborting due to 10 previous errors
8392

8493
For more information about this error, try `rustc --explain E0798`.

tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,24 @@ pub extern "cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [
2424
#[no_mangle]
2525
#[allow(improper_ctypes_definitions)]
2626
pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798]
27+
28+
struct Four {
29+
a: u32,
30+
b: u32,
31+
c: u32,
32+
d: u32,
33+
}
34+
35+
struct Five {
36+
a: u32,
37+
b: u32,
38+
c: u32,
39+
d: u32,
40+
e: u32,
41+
}
42+
43+
#[no_mangle]
44+
pub extern "cmse-nonsecure-entry" fn four(_: Four) {}
45+
46+
#[no_mangle]
47+
pub extern "cmse-nonsecure-entry" fn five(_: Five) {} //~ ERROR [E0798]

tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ LL | pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {}
4040
|
4141
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit argument registers
4242

43-
error: aborting due to 5 previous errors
43+
error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers
44+
--> $DIR/params-via-stack.rs:47:46
45+
|
46+
LL | pub extern "cmse-nonsecure-entry" fn five(_: Five) {}
47+
| ^^^^ does not fit in the available registers
48+
|
49+
= note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit argument registers
50+
51+
error: aborting due to 6 previous errors
4452

4553
For more information about this error, try `rustc --explain E0798`.

tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@ pub extern "cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {}
4040
#[no_mangle]
4141
pub extern "cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct<u64>, _: U32Compound) {}
4242
#[no_mangle]
43-
#[allow(improper_ctypes_definitions)]
43+
#[expect(improper_ctypes_definitions)]
4444
pub extern "cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {}
4545

46+
// With zero-sized types we can actually have more than 4 arguments.
47+
#[expect(improper_ctypes_definitions)]
48+
pub extern "cmse-nonsecure-entry" fn inputs8(_: (), _: (), _: (), _: (), _: ()) {}
49+
#[expect(improper_ctypes_definitions)]
50+
pub extern "cmse-nonsecure-entry" fn inputs9(_: (), _: (), _: (), _: (), _: ()) {}
51+
4652
#[no_mangle]
4753
pub extern "cmse-nonsecure-entry" fn outputs1() -> u32 {
4854
0
@@ -69,8 +75,8 @@ pub extern "cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct<u64> {
6975
ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () }
7076
}
7177
#[no_mangle]
72-
pub extern "cmse-nonsecure-entry" fn outputs7(
73-
) -> ReprTransparentStruct<ReprTransparentStruct<u64>> {
78+
pub extern "cmse-nonsecure-entry" fn outputs7() -> ReprTransparentStruct<ReprTransparentStruct<u64>>
79+
{
7480
ReprTransparentStruct {
7581
_marker1: (),
7682
_marker2: (),

0 commit comments

Comments
 (0)