Skip to content

improve error messages for C-cmse-nonsecure-entry functions #130747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
@@ -68,18 +68,21 @@ hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are fo
hir_analysis_cmse_call_generic =
function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
hir_analysis_cmse_call_inputs_stack_spill =
arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers
hir_analysis_cmse_entry_generic =
functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
hir_analysis_cmse_inputs_stack_spill =
arguments for `"{$abi_name}"` function too large to pass via registers
.label = {$plural ->
[false] this argument doesn't
*[true] these arguments don't
} fit in the available registers
.note = functions with the `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers
.note = functions with the `"{$abi_name}"` ABI must pass all their arguments via the 4 32-bit available argument registers
hir_analysis_cmse_call_output_stack_spill =
return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
hir_analysis_cmse_output_stack_spill =
return value of `"{$abi_name}"` function too large to pass via registers
.label = this type doesn't fit in the available registers
.note1 = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
17 changes: 13 additions & 4 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1627,23 +1627,25 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
pub(crate) struct EffectsWithoutNextSolver;

#[derive(Diagnostic)]
#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)]
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
#[note]
pub(crate) struct CmseCallInputsStackSpill {
pub(crate) struct CmseInputsStackSpill {
#[primary_span]
#[label]
pub span: Span,
pub plural: bool,
pub abi_name: &'static str,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)]
#[diag(hir_analysis_cmse_output_stack_spill, code = E0798)]
#[note(hir_analysis_note1)]
#[note(hir_analysis_note2)]
pub(crate) struct CmseCallOutputStackSpill {
pub(crate) struct CmseOutputStackSpill {
#[primary_span]
#[label]
pub span: Span,
pub abi_name: &'static str,
}

#[derive(Diagnostic)]
@@ -1659,3 +1661,10 @@ pub(crate) struct BadReturnTypeNotation {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_cmse_entry_generic, code = E0798)]
pub(crate) struct CmseEntryGeneric {
#[primary_span]
pub span: Span,
}
157 changes: 100 additions & 57 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
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;
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
use rustc_span::Span;
use rustc_target::spec::abi;

use crate::errors;
@@ -17,61 +17,104 @@ pub(crate) fn validate_cmse_abi<'tcx>(
abi: abi::Abi,
fn_sig: ty::PolyFnSig<'tcx>,
) {
if let abi::Abi::CCmseNonSecureCall = abi {
let hir_node = tcx.hir_node(hir_id);
let hir::Node::Ty(hir::Ty {
span: bare_fn_span,
kind: hir::TyKind::BareFn(bare_fn_ty),
..
}) = hir_node
else {
let span = match tcx.parent_hir_node(hir_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::ForeignMod { .. }, span, ..
}) => *span,
_ => tcx.hir().span(hir_id),
let abi_name = abi.name();

match abi {
abi::Abi::CCmseNonSecureCall => {
let hir_node = tcx.hir_node(hir_id);
let hir::Node::Ty(hir::Ty {
span: bare_fn_span,
kind: hir::TyKind::BareFn(bare_fn_ty),
..
}) = hir_node
else {
let span = match tcx.parent_hir_node(hir_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::ForeignMod { .. },
span,
..
}) => *span,
_ => tcx.hir().span(hir_id),
};
struct_span_code_err!(
tcx.dcx(),
span,
E0781,
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
)
.emit();
return;
};
struct_span_code_err!(
tcx.dcx(),
span,
E0781,
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
)
.emit();
return;
};

match is_valid_cmse_inputs(tcx, fn_sig) {
Ok(Ok(())) => {}
Ok(Err(index)) => {
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
// ^^^^^^
let span = bare_fn_ty.param_names[index]
.span
.to(bare_fn_ty.decl.inputs[index].span)
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
let plural = bare_fn_ty.param_names.len() - index != 1;
dcx.emit_err(errors::CmseCallInputsStackSpill { span, plural });
}
Err(layout_err) => {
if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
dcx.emit_err(err);
match is_valid_cmse_inputs(tcx, fn_sig) {
Ok(Ok(())) => {}
Ok(Err(index)) => {
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
// ^^^^^^
let span = bare_fn_ty.param_names[index]
.span
.to(bare_fn_ty.decl.inputs[index].span)
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
let plural = bare_fn_ty.param_names.len() - index != 1;
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name });
}
Err(layout_err) => {
if should_emit_generic_error(abi, layout_err) {
dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span });
}
}
}

match is_valid_cmse_output(tcx, fn_sig) {
Ok(true) => {}
Ok(false) => {
let span = bare_fn_ty.decl.output.span();
dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name });
}
Err(layout_err) => {
if should_emit_generic_error(abi, layout_err) {
dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span });
}
}
};
}
abi::Abi::CCmseNonSecureEntry => {
let hir_node = tcx.hir_node(hir_id);
let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else {
// might happen when this ABI is used incorrectly. That will be handled elsewhere
return;
};

match is_valid_cmse_output(tcx, fn_sig) {
Ok(true) => {}
Ok(false) => {
let span = bare_fn_ty.decl.output.span();
dcx.emit_err(errors::CmseCallOutputStackSpill { span });
}
Err(layout_err) => {
if let Some(err) = cmse_layout_err(layout_err, *bare_fn_span) {
dcx.emit_err(err);
match is_valid_cmse_inputs(tcx, fn_sig) {
Ok(Ok(())) => {}
Ok(Err(index)) => {
// fn f(x: u32, y: u32, z: u32, w: u16, q: u16) -> u32,
// ^^^^^^
let span = decl.inputs[index].span.to(decl.inputs.last().unwrap().span);
let plural = decl.inputs.len() - index != 1;
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi_name });
}
Err(layout_err) => {
if should_emit_generic_error(abi, layout_err) {
dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span });
}
}
}
};

match is_valid_cmse_output(tcx, fn_sig) {
Ok(true) => {}
Ok(false) => {
let span = decl.output.span();
dcx.emit_err(errors::CmseOutputStackSpill { span, abi_name });
}
Err(layout_err) => {
if should_emit_generic_error(abi, layout_err) {
dcx.emit_err(errors::CmseEntryGeneric { span: *fn_sig_span });
}
}
};
}
_ => (),
}
}

@@ -152,22 +195,22 @@ fn is_valid_cmse_output<'tcx>(
Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64)
}

fn cmse_layout_err<'tcx>(
layout_err: &'tcx LayoutError<'tcx>,
span: Span,
) -> Option<crate::errors::CmseCallGeneric> {
fn should_emit_generic_error<'tcx>(abi: abi::Abi, layout_err: &'tcx LayoutError<'tcx>) -> bool {
use LayoutError::*;

match layout_err {
Unknown(ty) => {
if ty.is_impl_trait() {
None // prevent double reporting of this error
} else {
Some(errors::CmseCallGeneric { span })
match abi {
abi::Abi::CCmseNonSecureCall => {
// prevent double reporting of this error
!ty.is_impl_trait()
}
abi::Abi::CCmseNonSecureEntry => true,
_ => bug!("invalid ABI: {abi}"),
}
}
SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => {
None // not our job to report these
false // not our job to report these
}
}
}
77 changes: 77 additions & 0 deletions tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, c_variadic, no_core, lang_items)]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
impl Copy for u32 {}

#[repr(C)]
struct Wrapper<T>(T);

impl<T: Copy> Wrapper<T> {
extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 {
//~^ ERROR [E0798]
0
}

extern "C-cmse-nonsecure-entry" fn ambient_generic_nested(
//~^ ERROR [E0798]
_: Wrapper<T>,
_: u32,
_: u32,
_: u32,
) -> u64 {
0
}
}

extern "C-cmse-nonsecure-entry" fn introduced_generic<U: Copy>(
//~^ ERROR [E0798]
_: U,
_: u32,
_: u32,
_: u32,
) -> u64 {
0
}

extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 {
//~^ ERROR [E0798]
0
}

extern "C-cmse-nonsecure-entry" fn reference(x: &usize) -> usize {
*x
}

trait Trait {}

extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait {
//~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x
}

extern "C-cmse-nonsecure-entry" fn static_trait_object(
x: &'static dyn Trait,
) -> &'static dyn Trait {
//~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x
}

#[repr(transparent)]
struct WrapperTransparent<'a>(&'a dyn Trait);

extern "C-cmse-nonsecure-entry" fn wrapped_trait_object(
x: WrapperTransparent,
) -> WrapperTransparent {
//~^ ERROR return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers [E0798]
x
}

extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
//~| ERROR requires `va_list` lang_item
}
78 changes: 78 additions & 0 deletions tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
--> $DIR/generics.rs:74:55
|
LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^

error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
--> $DIR/generics.rs:31:1
|
LL | / extern "C-cmse-nonsecure-entry" fn introduced_generic<U: Copy>(
LL | |
LL | | _: U,
LL | | _: u32,
LL | | _: u32,
LL | | _: u32,
LL | | ) -> u64 {
| |________^

error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
--> $DIR/generics.rs:41:1
|
LL | extern "C-cmse-nonsecure-entry" fn impl_trait(_: impl Copy, _: u32, _: u32, _: u32) -> u64 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
--> $DIR/generics.rs:15:5
|
LL | extern "C-cmse-nonsecure-entry" fn ambient_generic(_: T, _: u32, _: u32, _: u32) -> u64 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0798]: functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type
--> $DIR/generics.rs:20:5
|
LL | / extern "C-cmse-nonsecure-entry" fn ambient_generic_nested(
LL | |
LL | | _: Wrapper<T>,
LL | | _: u32,
LL | | _: u32,
LL | | _: u32,
LL | | ) -> u64 {
| |____________^

error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:52:67
|
LL | extern "C-cmse-nonsecure-entry" fn trait_object(x: &dyn Trait) -> &dyn Trait {
| ^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:59:6
|
LL | ) -> &'static dyn Trait {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/generics.rs:69:6
|
LL | ) -> WrapperTransparent {
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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: requires `va_list` lang_item
--> $DIR/generics.rs:74:55
|
LL | extern "C-cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) {
| ^^^^^^

error: aborting due to 9 previous errors

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

This file was deleted.

21 changes: 0 additions & 21 deletions tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs

This file was deleted.

This file was deleted.

26 changes: 26 additions & 0 deletions tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for u32 {}

#[repr(C, align(16))]
#[allow(unused)]
pub struct AlignRelevant(u32);

#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {} //~ ERROR [E0798]
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {} //~ ERROR [E0798]
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {} //~ ERROR [E0798]
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [E0798]

#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/params-via-stack.rs:16:78
|
LL | pub extern "C-cmse-nonsecure-entry" fn f1(_: u32, _: u32, _: u32, _: u32, _: u32, _: u32) {}
| ^^^^^^^^^^^ these arguments don't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers

error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/params-via-stack.rs:18:78
|
LL | pub extern "C-cmse-nonsecure-entry" fn f2(_: u32, _: u32, _: u32, _: u16, _: u16) {}
| ^^^ this argument doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers

error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/params-via-stack.rs:20:62
|
LL | pub extern "C-cmse-nonsecure-entry" fn f3(_: u32, _: u64, _: u32) {}
| ^^^ this argument doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers

error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/params-via-stack.rs:22:64
|
LL | pub extern "C-cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {}
| ^^^ this argument doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers

error[E0798]: arguments for `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/params-via-stack.rs:26:46
|
LL | pub extern "C-cmse-nonsecure-entry" fn f5(_: [u32; 5]) {}
| ^^^^^^^^ this argument doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit available argument registers

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0798`.
84 changes: 84 additions & 0 deletions tests/ui/cmse-nonsecure/cmse-nonsecure-entry/return-via-stack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
impl Copy for u32 {}
impl Copy for u8 {}

#[repr(C)]
pub struct ReprCU64(u64);

#[repr(C)]
pub struct ReprCBytes(u8, u8, u8, u8, u8);

#[repr(C)]
pub struct U64Compound(u32, u32);

#[repr(C, align(16))]
pub struct ReprCAlign16(u16);

#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 {
//~^ ERROR [E0798]
ReprCU64(0)
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes {
//~^ ERROR [E0798]
ReprCBytes(0, 1, 2, 3, 4)
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound {
//~^ ERROR [E0798]
U64Compound(2, 3)
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 {
//~^ ERROR [E0798]
ReprCAlign16(4)
}

#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] {
//~^ ERROR [E0798]
[0xAA; 5]
}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 {
//~^ ERROR [E0798]
123
}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 {
//~^ ERROR [E0798]
456
}

#[repr(Rust)]
pub union ReprRustUnionU64 {
_unused: u64,
}

#[repr(C)]
pub union ReprCUnionU64 {
_unused: u64,
}

#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 {
//~^ ERROR [E0798]
ReprRustUnionU64 { _unused: 1 }
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 {
//~^ ERROR [E0798]
ReprCUnionU64 { _unused: 2 }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
error[E0798]: return value of `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:25:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f1() -> ReprCU64 {
| ^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:30:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f2() -> ReprCBytes {
| ^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:35:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f3() -> U64Compound {
| ^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:40:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f4() -> ReprCAlign16 {
| ^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:47:48
|
LL | pub extern "C-cmse-nonsecure-entry" fn f5() -> [u8; 5] {
| ^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:53:50
|
LL | pub extern "C-cmse-nonsecure-entry" fn u128() -> u128 {
| ^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:59:50
|
LL | pub extern "C-cmse-nonsecure-entry" fn i128() -> i128 {
| ^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:76:56
|
LL | pub extern "C-cmse-nonsecure-entry" fn union_rust() -> ReprRustUnionU64 {
| ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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 `"C-cmse-nonsecure-entry"` function too large to pass via registers
--> $DIR/return-via-stack.rs:81:53
|
LL | pub extern "C-cmse-nonsecure-entry" fn union_c() -> ReprCUnionU64 {
| ^^^^^^^^^^^^^ this type doesn't fit in the available registers
|
= note: functions with the `"C-cmse-nonsecure-entry"` 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

For more information about this error, try `rustc --explain E0798`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
--> $DIR/trustzone-only.rs:5:1
|
LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0570`.
89 changes: 89 additions & 0 deletions tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//@ build-pass
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#![crate_type = "lib"]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for u32 {}
impl Copy for u8 {}

#[repr(transparent)]
pub struct ReprTransparentStruct<T> {
_marker1: (),
_marker2: (),
field: T,
_marker3: (),
}

#[repr(transparent)]
pub enum ReprTransparentEnumU64 {
A(u64),
}

#[repr(C)]
pub struct U32Compound(u16, u16);

#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn inputs1() {}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn inputs2(_: u32, _: u32, _: u32, _: u32) {}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn inputs3(_: u64, _: u64) {}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn inputs4(_: u128) {}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct<u64>, _: U32Compound) {}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {}

#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs1() -> u32 {
0
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs2() -> u64 {
0
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs3() -> i64 {
0
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs4() -> f64 {
0.0
}
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C-cmse-nonsecure-entry" fn outputs5() -> [u8; 4] {
[0xAA; 4]
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct<u64> {
ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () }
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs7(
) -> ReprTransparentStruct<ReprTransparentStruct<u64>> {
ReprTransparentStruct {
_marker1: (),
_marker2: (),
field: ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () },
_marker3: (),
}
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs8() -> ReprTransparentEnumU64 {
ReprTransparentEnumU64::A(0)
}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn outputs9() -> U32Compound {
U32Compound(1, 2)
}