From 7b6373496107807327094ec990d317b98e34fd63 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 17 Jul 2024 16:47:03 +0200 Subject: [PATCH] move CMSE validation to hir_analysis --- .../src/error_codes/E0798.md | 1 + compiler/rustc_hir_analysis/messages.ftl | 13 ++ .../rustc_hir_analysis/src/check/check.rs | 7 +- compiler/rustc_hir_analysis/src/errors.rs | 25 +++ .../src/hir_ty_lowering/cmse.rs | 152 ++++++++++++++++++ .../src/hir_ty_lowering/mod.rs | 10 +- .../cmse-nonsecure-call/generics.rs | 21 +++ .../cmse-nonsecure-call/generics.stderr | 47 ++++++ .../cmse-nonsecure-call/params-via-stack.rs | 18 +-- .../params-via-stack.stderr | 65 +++----- .../cmse-nonsecure-call/return-via-stack.rs | 34 ++-- .../return-via-stack.stderr | 136 +++++----------- .../cmse-nonsecure-call/via-registers.rs | 31 +--- 13 files changed, 363 insertions(+), 197 deletions(-) create mode 100644 compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0798.md b/compiler/rustc_error_codes/src/error_codes/E0798.md index 89e6f4d5718..da08cde3010 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0798.md +++ b/compiler/rustc_error_codes/src/error_codes/E0798.md @@ -5,6 +5,7 @@ inputs and outputs. is relevant. - outputs must either fit in 4 bytes, or be a foundational type of size 8 (`i64`, `u64`, `f64`). +- no generics can be used in the signature For more information, see [arm's aapcs32](https://github.com/ARM-software/abi-aa/releases). diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 24c5377a3b1..83618041133 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -58,6 +58,19 @@ hir_analysis_cannot_capture_late_bound_ty = hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present .label = `for<...>` is here +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 + .label = 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 + +hir_analysis_cmse_call_output_stack_spill = + return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + .label = this type doesn't fit in the available registers + .note = functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index bf8ef18c04f..aa302e4c25f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1287,9 +1287,10 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) (span, trivial, check_non_exhaustive(tcx, ty).break_value()) }); - let non_trivial_fields = field_infos - .clone() - .filter_map(|(span, trivial, _non_exhaustive)| if !trivial { Some(span) } else { None }); + let non_trivial_fields = + field_infos.clone().filter_map( + |(span, trivial, _non_exhaustive)| if !trivial { Some(span) } else { None }, + ); let non_trivial_count = non_trivial_fields.clone().count(); if non_trivial_count >= 2 { bad_non_zero_sized_fields( diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 0ee87a13e9e..f6783364f16 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1682,3 +1682,28 @@ pub struct InvalidReceiverTy<'tcx> { #[note] #[help] pub struct EffectsWithoutNextSolver; + +#[derive(Diagnostic)] +#[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)] +#[note] +pub struct CmseCallInputsStackSpill { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)] +#[note] +pub struct CmseCallOutputStackSpill { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cmse_call_generic, code = E0798)] +pub struct CmseCallGeneric { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs new file mode 100644 index 00000000000..8980173f738 --- /dev/null +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -0,0 +1,152 @@ +use rustc_errors::DiagCtxtHandle; +use rustc_hir as hir; +use rustc_hir::HirId; +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; + +/// Check conditions on inputs and outputs that the cmse ABIs impose: arguments and results MUST be +/// returned via registers (i.e. MUST NOT spill to the stack). LLVM will also validate these +/// conditions, but by checking them here rustc can emit nicer error messages. +pub fn validate_cmse_abi<'tcx>( + tcx: TyCtxt<'tcx>, + dcx: &DiagCtxtHandle<'_>, + hir_id: HirId, + 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 { + // might happen when this ABI is used incorrectly. That will be handled elsewhere + return; + }; + + // fn(u32, u32, u32, u16, u16) -> u32, + // ^^^^^^^^^^^^^^^^^^^^^^^ ^^^ + let output_span = bare_fn_ty.decl.output.span(); + let inputs_span = match ( + bare_fn_ty.param_names.first(), + bare_fn_ty.decl.inputs.first(), + bare_fn_ty.decl.inputs.last(), + ) { + (Some(ident), Some(ty1), Some(ty2)) => ident.span.to(ty1.span).to(ty2.span), + _ => *bare_fn_span, + }; + + match is_valid_cmse_inputs(tcx, fn_sig) { + Ok(true) => {} + Ok(false) => { + dcx.emit_err(errors::CmseCallInputsStackSpill { span: inputs_span }); + } + Err(layout_err) => { + if let Some(err) = cmse_layout_err(layout_err, inputs_span) { + dcx.emit_err(err); + } + } + } + + match is_valid_cmse_output(tcx, fn_sig) { + Ok(true) => {} + Ok(false) => { + dcx.emit_err(errors::CmseCallOutputStackSpill { span: output_span }); + } + Err(layout_err) => { + if let Some(err) = cmse_layout_err(layout_err, output_span) { + dcx.emit_err(err); + } + } + }; + } +} + +/// Returns whether the inputs will fit into the available registers +fn is_valid_cmse_inputs<'tcx>( + tcx: TyCtxt<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, +) -> Result> { + let mut accum = 0u64; + + for arg_def in fn_sig.inputs().iter() { + let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?; + + let align = layout.layout.align().abi.bytes(); + let size = layout.layout.size().bytes(); + + accum += size; + accum = accum.next_multiple_of(Ord::max(4, align)); + } + + // i.e. 4 32-bit registers + Ok(accum <= 16) +} + +/// Returns whether the output will fit into the available registers +fn is_valid_cmse_output<'tcx>( + tcx: TyCtxt<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, +) -> Result> { + let mut ret_ty = fn_sig.output().skip_binder(); + let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?; + let size = layout.layout.size().bytes(); + + if size <= 4 { + return Ok(true); + } else if size > 8 { + return Ok(false); + } + + // next we need to peel any repr(transparent) layers off + 'outer: loop { + let ty::Adt(adt_def, args) = ret_ty.kind() else { + break; + }; + + if !adt_def.repr().transparent() { + break; + } + + // the first field with non-trivial size and alignment must be the data + for variant_def in adt_def.variants() { + for field_def in variant_def.fields.iter() { + let ty = field_def.ty(tcx, args); + let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty))?; + + if !layout.layout.is_1zst() { + ret_ty = ty; + continue 'outer; + } + } + } + } + + 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 { + use LayoutError::*; + + match layout_err { + Unknown(ty) => { + if ty.is_impl_trait() { + None // prevent double reporting of this error + } else { + Some(errors::CmseCallGeneric { span }) + } + } + SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => { + None // not our job to report these + } + } +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a665306f2c6..5a98e4d79bb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -14,6 +14,7 @@ //! trait references and bounds. mod bounds; +mod cmse; pub mod errors; pub mod generics; mod lint; @@ -1748,7 +1749,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect(); let _ = self.prohibit_generic_args( path.segments.iter().enumerate().filter_map(|(index, seg)| { - if !indices.contains(&index) { Some(seg) } else { None } + if !indices.contains(&index) { + Some(seg) + } else { + None + } }), GenericsArgsErrExtend::DefVariant, ); @@ -2324,6 +2329,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); + // reject function types that violate cmse ABI requirements + cmse::validate_cmse_abi(self.tcx(), &self.dcx(), hir_id, abi, bare_fn_ty); + // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not well-formed. // diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs new file mode 100644 index 00000000000..e6b0bf3e686 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs @@ -0,0 +1,21 @@ +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, 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); + +struct Test { + f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, //~ ERROR cannot find type `U` in this scope + //~^ ERROR function pointer types may not have generic parameters + f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, + //~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters + f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798] + f4: extern "C-cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, //~ ERROR [E0798] +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr new file mode 100644 index 00000000000..b255d261938 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr @@ -0,0 +1,47 @@ +error: function pointer types may not have generic parameters + --> $DIR/generics.rs:15:42 + | +LL | f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, + | ^^^^^^^^^ + +error[E0412]: cannot find type `U` in this scope + --> $DIR/generics.rs:15:52 + | +LL | struct Test { + | - similarly named type parameter `T` defined here +LL | f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, + | ^ + | +help: a type parameter with a similar name exists + | +LL | f1: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, + | ~ +help: you might be missing a type parameter + | +LL | struct Test { + | +++ + +error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters + --> $DIR/generics.rs:17:43 + | +LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, + | ^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods + +error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type + --> $DIR/generics.rs:19:43 + | +LL | f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, + | ^^^^^^^^^^^^^^^^ + +error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type + --> $DIR/generics.rs:20:43 + | +LL | f4: extern "C-cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0412, E0562, E0798. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs index a4cc74f716f..f8ef4419921 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.rs @@ -1,7 +1,6 @@ -//@ build-fail //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} @@ -15,15 +14,10 @@ pub struct AlignRelevant(u32); #[no_mangle] pub fn test( - f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32, - f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16) -> u32, - f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32) -> u32, - f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32) -> u32, - f5: extern "C-cmse-nonsecure-call" fn([u32; 5]) -> u32, + f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32), //~ ERROR [E0798] + f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), //~ ERROR [E0798] + f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32), //~ ERROR [E0798] + f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32), //~ ERROR [E0798] + f5: extern "C-cmse-nonsecure-call" fn([u32; 5]), //~ ERROR [E0798] ) { - f1(1, 2, 3, 4, 5); //~ ERROR [E0798] - f2(1, 2, 3, 4, 5); //~ ERROR [E0798] - f3(1, 2, 3); //~ ERROR [E0798] - f4(AlignRelevant(1), 2); //~ ERROR [E0798] - f5([0xAA; 5]); //~ ERROR [E0798] } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr index b161c90d01a..499122ab2c5 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-via-stack.stderr @@ -1,57 +1,42 @@ -error[E0798]: arguments for `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/params-via-stack.rs:24:5 +error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:17:43 | -LL | f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f1(1, 2, 3, 4, 5); - | ^^^^^^^^^^^^^^^^^ but its arguments don't fit in the available registers +LL | f1: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^^ 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 `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/params-via-stack.rs:25:5 +error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:18:43 | -LL | f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16) -> u32, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f2(1, 2, 3, 4, 5); - | ^^^^^^^^^^^^^^^^^ but its arguments don't fit in the available registers +LL | f2: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u16, u16), + | ^^^^^^^^^^^^^^^^^^^^^^^ 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 `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/params-via-stack.rs:26:5 +error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:19:43 | -LL | f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32) -> u32, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f3(1, 2, 3); - | ^^^^^^^^^^^ but its arguments don't fit in the available registers +LL | f3: extern "C-cmse-nonsecure-call" fn(u32, u64, u32), + | ^^^^^^^^^^^^^ 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 `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/params-via-stack.rs:27:5 +error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:20:43 | -LL | f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32) -> u32, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f4(AlignRelevant(1), 2); - | ^^^^^^^^^^^^^^^^^^^^^^^ but its arguments don't fit in the available registers +LL | f4: extern "C-cmse-nonsecure-call" fn(AlignRelevant, u32), + | ^^^^^^^^^^^^^^^^^^ 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 `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers -error[E0798]: arguments for `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/params-via-stack.rs:28:5 +error[E0798]: arguments for `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/params-via-stack.rs:21:43 | -LL | f5: extern "C-cmse-nonsecure-call" fn([u32; 5]) -> u32, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f5([0xAA; 5]); - | ^^^^^^^^^^^^^ but its arguments don't fit in the available registers +LL | f5: extern "C-cmse-nonsecure-call" fn([u32; 5]), + | ^^^^^^^^ 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 `"C-cmse-nonsecure-call"` ABI must pass all their arguments via the 4 32-bit available argument registers error: aborting due to 5 previous errors diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs index 2ea69327392..e6af1d60e77 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs @@ -1,7 +1,6 @@ -//@ build-fail //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm -#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items)] #![no_core] #[lang = "sized"] pub trait Sized {} @@ -23,21 +22,18 @@ pub struct ReprCAlign16(u16); #[no_mangle] pub fn test( - f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64, - f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes, - f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound, - f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16, - f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5], - f6: extern "C-cmse-nonsecure-call" fn() -> u128, //~ WARNING [improper_ctypes_definitions] - f7: extern "C-cmse-nonsecure-call" fn() -> i128, //~ WARNING [improper_ctypes_definitions] + f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798] + f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798] + f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798] + f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798] + f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798] ) { - f1(); //~ ERROR [E0798] - f2(); //~ ERROR [E0798] - f3(); //~ ERROR [E0798] - f4(); //~ ERROR [E0798] - f5(); //~ ERROR [E0798] - f6(); //~ ERROR [E0798] - f7(); //~ ERROR [E0798] +} + +#[allow(improper_ctypes_definitions)] +struct Test { + u128: extern "C-cmse-nonsecure-call" fn() -> u128, //~ ERROR [E0798] + i128: extern "C-cmse-nonsecure-call" fn() -> i128, //~ ERROR [E0798] } #[repr(C)] @@ -52,9 +48,7 @@ pub union ReprRustUnionU64 { #[no_mangle] pub fn test_union( - f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, //~ WARNING [improper_ctypes_definitions] - f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64, + f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, //~ ERROR [E0798] + f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64, //~ ERROR [E0798] ) { - f1(); //~ ERROR [E0798] - f2(); //~ ERROR [E0798] } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr index 99dc7ad4a9f..c8984e3c0d9 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr @@ -1,133 +1,75 @@ -warning: `extern` fn uses type `u128`, which is not FFI-safe - --> $DIR/return-via-stack.rs:31:9 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:35:50 | -LL | f6: extern "C-cmse-nonsecure-call" fn() -> u128, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | u128: extern "C-cmse-nonsecure-call" fn() -> u128, + | ^^^^ this type doesn't fit in the available registers | - = note: 128-bit integers don't currently have a known stable ABI - = note: `#[warn(improper_ctypes_definitions)]` on by default + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -warning: `extern` fn uses type `i128`, which is not FFI-safe - --> $DIR/return-via-stack.rs:32:9 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:36:50 | -LL | f7: extern "C-cmse-nonsecure-call" fn() -> i128, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | i128: extern "C-cmse-nonsecure-call" fn() -> i128, + | ^^^^ this type doesn't fit in the available registers | - = note: 128-bit integers don't currently have a known stable ABI + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -warning: `extern` fn uses type `ReprRustUnionU64`, which is not FFI-safe - --> $DIR/return-via-stack.rs:55:9 - | -LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union - = note: this union has unspecified layout -note: the type is defined here - --> $DIR/return-via-stack.rs:49:1 - | -LL | pub union ReprRustUnionU64 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:34:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:25:48 | LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprCU64, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f1(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:35:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:26:48 | LL | f2: extern "C-cmse-nonsecure-call" fn() -> ReprCBytes, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f2(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:36:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:27:48 | LL | f3: extern "C-cmse-nonsecure-call" fn() -> U64Compound, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f3(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:37:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:28:48 | LL | f4: extern "C-cmse-nonsecure-call" fn() -> ReprCAlign16, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f4(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:38:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:29:48 | LL | f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 5], - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f5(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:39:5 - | -LL | f6: extern "C-cmse-nonsecure-call" fn() -> u128, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f6(); - | ^^^^ but its return value doesn't fit in the available registers - | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers - -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:40:5 - | -LL | f7: extern "C-cmse-nonsecure-call" fn() -> i128, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f7(); - | ^^^^ but its return value doesn't fit in the available registers - | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers - -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:58:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:51:48 | LL | f1: extern "C-cmse-nonsecure-call" fn() -> ReprRustUnionU64, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f1(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error[E0798]: return value of `C-cmse-nonsecure-call` function too large to pass via registers - --> $DIR/return-via-stack.rs:59:5 +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:52:48 | LL | f2: extern "C-cmse-nonsecure-call" fn() -> ReprCUnionU64, - | -- this function uses the `C-cmse-nonsecure-call` ABI -... -LL | f2(); - | ^^^^ but its return value doesn't fit in the available registers + | ^^^^^^^^^^^^^ this type doesn't fit in the available registers | - = note: functions with the `C-cmse-nonsecure-call` ABI must pass their result via the available return registers + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers -error: aborting due to 9 previous errors; 3 warnings emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs index 91aadd4fe1d..9fda55c2a48 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/via-registers.rs @@ -10,10 +10,10 @@ pub trait Copy {} impl Copy for u32 {} #[repr(transparent)] -pub struct ReprTransparentStructU64 { +pub struct ReprTransparentStruct { _marker1: (), _marker2: (), - field: u64, + field: T, _marker3: (), } @@ -33,19 +33,9 @@ pub fn params( f3: extern "C-cmse-nonsecure-call" fn(u64, u64), f4: extern "C-cmse-nonsecure-call" fn(u128), f5: extern "C-cmse-nonsecure-call" fn(f64, f32, f32), - f6: extern "C-cmse-nonsecure-call" fn(ReprTransparentStructU64, U32Compound), + f6: extern "C-cmse-nonsecure-call" fn(ReprTransparentStruct, U32Compound), f7: extern "C-cmse-nonsecure-call" fn([u32; 4]), ) { - f1(); - f2(1, 2, 3, 4); - f3(1, 2); - f4(1); - f5(1.0, 2.0, 3.0); - f6( - ReprTransparentStructU64 { _marker1: (), _marker2: (), field: 1, _marker3: () }, - U32Compound(2, 3), - ); - f7([0xDEADBEEF; 4]); } #[no_mangle] @@ -55,16 +45,9 @@ pub fn returns( f3: extern "C-cmse-nonsecure-call" fn() -> i64, f4: extern "C-cmse-nonsecure-call" fn() -> f64, f5: extern "C-cmse-nonsecure-call" fn() -> [u8; 4], - f6: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStructU64, - f7: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentEnumU64, - f8: extern "C-cmse-nonsecure-call" fn() -> U32Compound, + f6: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStruct, + f7: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentStruct>, + f8: extern "C-cmse-nonsecure-call" fn() -> ReprTransparentEnumU64, + f9: extern "C-cmse-nonsecure-call" fn() -> U32Compound, ) { - f1(); - f2(); - f3(); - f4(); - f5(); - f6(); - f7(); - f8(); }