Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3025513
Implemented FromStr for CString and TryFrom<CString> for String
YohDeadfall Sep 20, 2024
5fef462
Add 1.82 release notes
Mark-Simulacrum Oct 2, 2024
a0e687f
Remove unnecessary sorts in `rustc_hir_analysis`.
ismailarilik Oct 6, 2024
ae698f8
Add sugar for &pin (const|mut) types
eholk Sep 20, 2024
b490bf5
Fix clippy and rustfmt compilation
eholk Sep 20, 2024
3aabe1e
Add basic pin sugar support to rustfmt
eholk Sep 23, 2024
005a629
re-sync with latest tracking issue changes
Mark-Simulacrum Oct 7, 2024
cae29b2
Import another update
Mark-Simulacrum Oct 12, 2024
276d112
Add stabilized APIs
Mark-Simulacrum Oct 12, 2024
5b2985f
Add explicit link to PR
Mark-Simulacrum Oct 12, 2024
4e438f7
Fix two const-hacks
GKFX Oct 14, 2024
10aa255
improve error messages for `C-cmse-nonsecure-entry` functions
folkertdev Oct 14, 2024
3c31729
Stabilise 'const_make_ascii'
bjoernager Oct 9, 2024
3a00d35
Rollup merge of #130608 - YohDeadfall:cstr-from-into-str, r=workingju…
matthiaskrgr Oct 15, 2024
fb691b4
Rollup merge of #130635 - eholk:pin-reborrow-sugar, r=compiler-errors
matthiaskrgr Oct 15, 2024
731e360
Rollup merge of #130747 - folkertdev:c-cmse-nonsecure-entry-error-mes…
matthiaskrgr Oct 15, 2024
13e07b9
Rollup merge of #131137 - Mark-Simulacrum:relnotes, r=cuviper
matthiaskrgr Oct 15, 2024
b9cb201
Rollup merge of #131328 - ismailarilik:remove-unnecessary-sorts-in-ru…
matthiaskrgr Oct 15, 2024
9716a42
Rollup merge of #131496 - bjoernager:const-make-ascii, r=dtolnay
matthiaskrgr Oct 15, 2024
83252bd
Rollup merge of #131706 - GKFX:fix-const-hacks, r=tgross35
matthiaskrgr Oct 15, 2024
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
Prev Previous commit
Next Next commit
improve error messages for C-cmse-nonsecure-entry functions
  • Loading branch information
folkertdev committed Oct 14, 2024
commit 10aa255541964bceddaac8f49d7a11f1d736e24d
15 changes: 9 additions & 6 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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;
Expand All @@ -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 });
}
}
};
}
_ => (),
}
}

Expand Down Expand Up @@ -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
}
Loading
Loading