Rollup merge of #127766 - folkertdev:c-cmse-nonsecure-entry, r=jackh726

add `extern "C-cmse-nonsecure-entry" fn`

tracking issue #75835

in https://github.com/rust-lang/rust/issues/75835#issuecomment-1183517255 it was decided that using an abi, rather than an attribute, was the right way to go for this feature.

This PR adds that ABI and removes the `#[cmse_nonsecure_entry]` attribute. All relevant tests have been updated, some are now obsolete and have been removed.

Error 0775 is no longer generated. It contains the list of targets that support the CMSE feature, and maybe we want to still use this? right now a generic "this abi is not supported on this platform" error is returned when this abi is used on an unsupported platform. On the other hand, users of this abi are likely to be experienced rust users, so maybe the generic error is good enough.
This commit is contained in:
Michael Goulet 2024-09-21 15:18:55 -04:00 committed by GitHub
commit 2a9525bb90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 185 additions and 182 deletions

View File

@ -61,6 +61,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
Conv::CCmseNonSecureCall => { Conv::CCmseNonSecureCall => {
sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented"); sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented");
} }
Conv::CCmseNonSecureEntry => {
sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented");
}
Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => { Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => {
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");

View File

@ -422,6 +422,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
if let Conv::RiscvInterrupt { kind } = self.conv { if let Conv::RiscvInterrupt { kind } = self.conv {
func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str())); func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str()));
} }
if let Conv::CCmseNonSecureEntry = self.conv {
func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"))
}
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs }); attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });
let mut i = 0; let mut i = 0;
@ -659,9 +662,11 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
impl From<Conv> for llvm::CallConv { impl From<Conv> for llvm::CallConv {
fn from(conv: Conv) -> Self { fn from(conv: Conv) -> Self {
match conv { match conv {
Conv::C | Conv::Rust | Conv::CCmseNonSecureCall | Conv::RiscvInterrupt { .. } => { Conv::C
llvm::CCallConv | Conv::Rust
} | Conv::CCmseNonSecureCall
| Conv::CCmseNonSecureEntry
| Conv::RiscvInterrupt { .. } => llvm::CCallConv,
Conv::Cold => llvm::ColdCallConv, Conv::Cold => llvm::ColdCallConv,
Conv::PreserveMost => llvm::PreserveMost, Conv::PreserveMost => llvm::PreserveMost,
Conv::PreserveAll => llvm::PreserveAll, Conv::PreserveAll => llvm::PreserveAll,

View File

@ -483,9 +483,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx); let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]); attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
} }
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
}
if let Some(align) = codegen_fn_attrs.alignment { if let Some(align) = codegen_fn_attrs.alignment {
llvm::set_alignment(llfn, align); llvm::set_alignment(llfn, align);
} }

View File

@ -195,24 +195,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
} }
} }
} }
sym::cmse_nonsecure_entry => {
if let Some(fn_sig) = fn_sig()
&& !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
{
struct_span_code_err!(
tcx.dcx(),
attr.span,
E0776,
"`#[cmse_nonsecure_entry]` requires C ABI"
)
.emit();
}
if !tcx.sess.target.llvm_target.contains("thumbv8m") {
struct_span_code_err!(tcx.dcx(), attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
.emit();
}
codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::track_caller => { sym::track_caller => {
let is_closure = tcx.is_closure_like(did.to_def_id()); let is_closure = tcx.is_closure_like(did.to_def_id());

View File

@ -1,13 +1,14 @@
#### Note: this error code is no longer emitted by the compiler.
`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M
extension. extension.
Erroneous code example: Erroneous code example:
```compile_fail,E0775 ```ignore (no longer emitted)
#![feature(cmse_nonsecure_entry)] #![feature(cmse_nonsecure_entry)]
#[cmse_nonsecure_entry] pub extern "C-cmse-nonsecure-entry" fn entry_function() {}
pub extern "C" fn entry_function() {}
``` ```
To fix this error, compile your code for a Rust target that supports the To fix this error, compile your code for a Rust target that supports the

View File

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
`#[cmse_nonsecure_entry]` functions require a C ABI `#[cmse_nonsecure_entry]` functions require a C ABI
Erroneous code example: Erroneous code example:
```compile_fail,E0776 ```ignore (no longer emitted)
#![feature(cmse_nonsecure_entry)] #![feature(cmse_nonsecure_entry)]
#[no_mangle] #[no_mangle]

View File

@ -681,4 +681,5 @@ E0800: 0800,
// E0723, // unstable feature in `const` context // E0723, // unstable feature in `const` context
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
// E0744, // merged into E0728 // E0744, // merged into E0728
// E0776, // Removed; cmse_nonsecure_entry is now `C-cmse-nonsecure-entry`
// E0796, // unused error code. We use `static_mut_refs` lint instead. // E0796, // unused error code. We use `static_mut_refs` lint instead.

View File

@ -551,10 +551,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
EncodeCrossCrate::No, experimental!(register_tool), EncodeCrossCrate::No, experimental!(register_tool),
), ),
gated!(
cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing,
EncodeCrossCrate::No, experimental!(cmse_nonsecure_entry)
),
// RFC 2632 // RFC 2632
gated!( gated!(
const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl, const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,

View File

@ -395,7 +395,7 @@ declare_features! (
(unstable, closure_lifetime_binder, "1.64.0", Some(97362)), (unstable, closure_lifetime_binder, "1.64.0", Some(97362)),
/// Allows `#[track_caller]` on closures and coroutines. /// Allows `#[track_caller]` on closures and coroutines.
(unstable, closure_track_caller, "1.57.0", Some(87417)), (unstable, closure_track_caller, "1.57.0", Some(87417)),
/// Allows to use the `#[cmse_nonsecure_entry]` attribute. /// Allows `extern "C-cmse-nonsecure-entry" fn()`.
(unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)), (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
/// Allows `async {}` expressions in const contexts. /// Allows `async {}` expressions in const contexts.
(unstable, const_async_blocks, "1.53.0", Some(85368)), (unstable, const_async_blocks, "1.53.0", Some(85368)),

View File

@ -120,9 +120,7 @@ bitflags::bitflags! {
/// #[ffi_const]: applies clang's `const` attribute to a foreign function /// #[ffi_const]: applies clang's `const` attribute to a foreign function
/// declaration. /// declaration.
const FFI_CONST = 1 << 12; const FFI_CONST = 1 << 12;
/// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a // (Bit 13 was used for `#[cmse_nonsecure_entry]`, but is now unused.)
/// function as an entry function from Non-Secure code.
const CMSE_NONSECURE_ENTRY = 1 << 13;
// (Bit 14 was used for `#[coverage(off)]`, but is now unused.) // (Bit 14 was used for `#[coverage(off)]`, but is now unused.)
/// `#[used(linker)]`: /// `#[used(linker)]`:
/// indicates that neither LLVM nor the linker will eliminate this function. /// indicates that neither LLVM nor the linker will eliminate this function.

View File

@ -1191,6 +1191,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
| RiscvInterruptM | RiscvInterruptM
| RiscvInterruptS | RiscvInterruptS
| CCmseNonSecureCall | CCmseNonSecureCall
| CCmseNonSecureEntry
| Unadjusted => false, | Unadjusted => false,
Rust | RustCall | RustCold | RustIntrinsic => { Rust | RustCall | RustCold | RustIntrinsic => {
tcx.sess.panic_strategy() == PanicStrategy::Unwind tcx.sess.panic_strategy() == PanicStrategy::Unwind

View File

@ -188,9 +188,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| [sym::rustc_must_implement_one_of, ..] | [sym::rustc_must_implement_one_of, ..]
| [sym::rustc_deny_explicit_impl, ..] | [sym::rustc_deny_explicit_impl, ..]
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target), | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
[sym::cmse_nonsecure_entry, ..] => {
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
}
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
[sym::must_use, ..] => self.check_must_use(hir_id, attr, target), [sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
@ -563,27 +560,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
} }
} }
/// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
fn check_cmse_nonsecure_entry(
&self,
hir_id: HirId,
attr: &Attribute,
span: Span,
target: Target,
) {
match target {
Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
attr_span: attr.span,
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
}
}
}
/// Debugging aid for `object_lifetime_default` query. /// Debugging aid for `object_lifetime_default` query.
fn check_object_lifetime_default(&self, hir_id: HirId) { fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx; let tcx = self.tcx;

View File

@ -470,6 +470,7 @@ impl RustcInternal for Abi {
Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt, Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt,
Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt, Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt,
Abi::CCmseNonSecureCall => rustc_target::spec::abi::Abi::CCmseNonSecureCall, Abi::CCmseNonSecureCall => rustc_target::spec::abi::Abi::CCmseNonSecureCall,
Abi::CCmseNonSecureEntry => rustc_target::spec::abi::Abi::CCmseNonSecureEntry,
Abi::System { unwind } => rustc_target::spec::abi::Abi::System { unwind }, Abi::System { unwind } => rustc_target::spec::abi::Abi::System { unwind },
Abi::RustIntrinsic => rustc_target::spec::abi::Abi::RustIntrinsic, Abi::RustIntrinsic => rustc_target::spec::abi::Abi::RustIntrinsic,
Abi::RustCall => rustc_target::spec::abi::Abi::RustCall, Abi::RustCall => rustc_target::spec::abi::Abi::RustCall,

View File

@ -105,6 +105,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
Conv::PreserveAll => CallConvention::PreserveAll, Conv::PreserveAll => CallConvention::PreserveAll,
Conv::ArmAapcs => CallConvention::ArmAapcs, Conv::ArmAapcs => CallConvention::ArmAapcs,
Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall, Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
Conv::Msp430Intr => CallConvention::Msp430Intr, Conv::Msp430Intr => CallConvention::Msp430Intr,
Conv::PtxKernel => CallConvention::PtxKernel, Conv::PtxKernel => CallConvention::PtxKernel,
Conv::X86Fastcall => CallConvention::X86Fastcall, Conv::X86Fastcall => CallConvention::X86Fastcall,

View File

@ -910,6 +910,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi {
abi::Abi::AvrInterrupt => Abi::AvrInterrupt, abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
abi::Abi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry,
abi::Abi::System { unwind } => Abi::System { unwind }, abi::Abi::System { unwind } => Abi::System { unwind },
abi::Abi::RustIntrinsic => Abi::RustIntrinsic, abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
abi::Abi::RustCall => Abi::RustCall, abi::Abi::RustCall => Abi::RustCall,

View File

@ -779,6 +779,7 @@ pub enum Conv {
// Target-specific calling conventions. // Target-specific calling conventions.
ArmAapcs, ArmAapcs,
CCmseNonSecureCall, CCmseNonSecureCall,
CCmseNonSecureEntry,
Msp430Intr, Msp430Intr,
@ -972,6 +973,7 @@ impl FromStr for Conv {
"RustCold" => Ok(Conv::Rust), "RustCold" => Ok(Conv::Rust),
"ArmAapcs" => Ok(Conv::ArmAapcs), "ArmAapcs" => Ok(Conv::ArmAapcs),
"CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall), "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall),
"CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry),
"Msp430Intr" => Ok(Conv::Msp430Intr), "Msp430Intr" => Ok(Conv::Msp430Intr),
"PtxKernel" => Ok(Conv::PtxKernel), "PtxKernel" => Ok(Conv::PtxKernel),
"X86Fastcall" => Ok(Conv::X86Fastcall), "X86Fastcall" => Ok(Conv::X86Fastcall),

View File

@ -103,6 +103,7 @@ impl ToJson for crate::abi::call::Conv {
Self::PreserveAll => "PreserveAll", Self::PreserveAll => "PreserveAll",
Self::ArmAapcs => "ArmAapcs", Self::ArmAapcs => "ArmAapcs",
Self::CCmseNonSecureCall => "CCmseNonSecureCall", Self::CCmseNonSecureCall => "CCmseNonSecureCall",
Self::CCmseNonSecureEntry => "CCmseNonSecureEntry",
Self::Msp430Intr => "Msp430Intr", Self::Msp430Intr => "Msp430Intr",
Self::PtxKernel => "PtxKernel", Self::PtxKernel => "PtxKernel",
Self::X86Fastcall => "X86Fastcall", Self::X86Fastcall => "X86Fastcall",

View File

@ -48,6 +48,7 @@ pub enum Abi {
AvrInterrupt, AvrInterrupt,
AvrNonBlockingInterrupt, AvrNonBlockingInterrupt,
CCmseNonSecureCall, CCmseNonSecureCall,
CCmseNonSecureEntry,
System { System {
unwind: bool, unwind: bool,
}, },
@ -124,6 +125,7 @@ const AbiDatas: &[AbiData] = &[
AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" }, AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" }, AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" }, AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
AbiData { abi: Abi::CCmseNonSecureEntry, name: "C-cmse-nonsecure-entry" },
AbiData { abi: Abi::System { unwind: false }, name: "system" }, AbiData { abi: Abi::System { unwind: false }, name: "system" },
AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" }, AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" }, AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
@ -244,6 +246,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
feature: sym::abi_c_cmse_nonsecure_call, feature: sym::abi_c_cmse_nonsecure_call,
explain: "C-cmse-nonsecure-call ABI is experimental and subject to change", explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
}), }),
"C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable {
feature: sym::cmse_nonsecure_entry,
explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change",
}),
_ => Err(AbiDisabled::Unrecognized), _ => Err(AbiDisabled::Unrecognized),
} }
} }
@ -286,15 +292,16 @@ impl Abi {
AvrInterrupt => 23, AvrInterrupt => 23,
AvrNonBlockingInterrupt => 24, AvrNonBlockingInterrupt => 24,
CCmseNonSecureCall => 25, CCmseNonSecureCall => 25,
CCmseNonSecureEntry => 26,
// Cross-platform ABIs // Cross-platform ABIs
System { unwind: false } => 26, System { unwind: false } => 27,
System { unwind: true } => 27, System { unwind: true } => 28,
RustIntrinsic => 28, RustIntrinsic => 29,
RustCall => 29, RustCall => 30,
Unadjusted => 30, Unadjusted => 31,
RustCold => 31, RustCold => 32,
RiscvInterruptM => 32, RiscvInterruptM => 33,
RiscvInterruptS => 33, RiscvInterruptS => 34,
}; };
debug_assert!( debug_assert!(
AbiDatas AbiDatas

View File

@ -2724,7 +2724,10 @@ impl Target {
} }
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
Aapcs { .. } => "arm" == self.arch, Aapcs { .. } => "arm" == self.arch,
CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), CCmseNonSecureCall | CCmseNonSecureEntry => {
["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
.contains(&&self.llvm_target[..])
}
Win64 { .. } | SysV64 { .. } => self.arch == "x86_64", Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
PtxKernel => self.arch == "nvptx64", PtxKernel => self.arch == "nvptx64",
Msp430Interrupt => self.arch == "msp430", Msp430Interrupt => self.arch == "msp430",

View File

@ -312,6 +312,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv {
SysV64 { .. } => Conv::X86_64SysV, SysV64 { .. } => Conv::X86_64SysV,
Aapcs { .. } => Conv::ArmAapcs, Aapcs { .. } => Conv::ArmAapcs,
CCmseNonSecureCall => Conv::CCmseNonSecureCall, CCmseNonSecureCall => Conv::CCmseNonSecureCall,
CCmseNonSecureEntry => Conv::CCmseNonSecureEntry,
PtxKernel => Conv::PtxKernel, PtxKernel => Conv::PtxKernel,
Msp430Interrupt => Conv::Msp430Intr, Msp430Interrupt => Conv::Msp430Intr,
X86Interrupt => Conv::X86Intr, X86Interrupt => Conv::X86Intr,

View File

@ -433,6 +433,7 @@ pub enum CallConvention {
// Target-specific calling conventions. // Target-specific calling conventions.
ArmAapcs, ArmAapcs,
CCmseNonSecureCall, CCmseNonSecureCall,
CCmseNonSecureEntry,
Msp430Intr, Msp430Intr,

View File

@ -1062,6 +1062,7 @@ pub enum Abi {
AvrInterrupt, AvrInterrupt,
AvrNonBlockingInterrupt, AvrNonBlockingInterrupt,
CCmseNonSecureCall, CCmseNonSecureCall,
CCmseNonSecureEntry,
System { unwind: bool }, System { unwind: bool },
RustIntrinsic, RustIntrinsic,
RustCall, RustCall,

View File

@ -15,10 +15,10 @@ LLVM, the Rust compiler and the linker are providing
TrustZone-M feature. TrustZone-M feature.
One of the things provided, with this unstable feature, is the One of the things provided, with this unstable feature, is the
`cmse_nonsecure_entry` attribute. This attribute marks a Secure function as an `C-cmse-nonsecure-entry` ABI. This ABI marks a Secure function as an
entry function (see [section entry function (see [section
5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details). 5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
With this attribute, the compiler will do the following: With this ABI, the compiler will do the following:
* add a special symbol on the function which is the `__acle_se_` prefix and the * add a special symbol on the function which is the `__acle_se_` prefix and the
standard function name standard function name
* constrain the number of parameters to avoid using the Non-Secure stack * constrain the number of parameters to avoid using the Non-Secure stack
@ -38,11 +38,11 @@ gateway veneer.
<!-- NOTE(ignore) this example is specific to thumbv8m targets --> <!-- NOTE(ignore) this example is specific to thumbv8m targets -->
``` rust,ignore ``` rust,ignore
#![no_std]
#![feature(cmse_nonsecure_entry)] #![feature(cmse_nonsecure_entry)]
#[no_mangle] #[no_mangle]
#[cmse_nonsecure_entry] pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
pub extern "C" fn entry_function(input: u32) -> u32 {
input + 6 input + 6
} }
``` ```

View File

@ -377,6 +377,7 @@ pub enum FnAbi {
AvrNonBlockingInterrupt, AvrNonBlockingInterrupt,
C, C,
CCmseNonsecureCall, CCmseNonsecureCall,
CCmseNonsecureEntry,
CDecl, CDecl,
CDeclUnwind, CDeclUnwind,
CUnwind, CUnwind,
@ -434,6 +435,7 @@ impl FnAbi {
s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt, s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt, s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall, s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry,
s if *s == sym::C_dash_unwind => FnAbi::CUnwind, s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
s if *s == sym::C => FnAbi::C, s if *s == sym::C => FnAbi::C,
s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind, s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
@ -477,6 +479,7 @@ impl FnAbi {
FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt", FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
FnAbi::C => "C", FnAbi::C => "C",
FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call", FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry",
FnAbi::CDecl => "C-decl", FnAbi::CDecl => "C-decl",
FnAbi::CDeclUnwind => "cdecl-unwind", FnAbi::CDeclUnwind => "cdecl-unwind",
FnAbi::CUnwind => "C-unwind", FnAbi::CUnwind => "C-unwind",

View File

@ -32,6 +32,7 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
"riscv-interrupt-m", "riscv-interrupt-m",
"riscv-interrupt-s", "riscv-interrupt-s",
"C-cmse-nonsecure-call", "C-cmse-nonsecure-call",
"C-cmse-nonsecure-entry",
"wasm", "wasm",
"system", "system",
"system-unwind", "system-unwind",

View File

@ -94,6 +94,7 @@ define_symbols! {
avr_dash_interrupt = "avr-interrupt", avr_dash_interrupt = "avr-interrupt",
avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt", avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt",
C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call", C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call",
C_dash_cmse_dash_nonsecure_dash_entry = "C-cmse-nonsecure-entry",
C_dash_unwind = "C-unwind", C_dash_unwind = "C-unwind",
cdecl_dash_unwind = "cdecl-unwind", cdecl_dash_unwind = "cdecl-unwind",
fastcall_dash_unwind = "fastcall-unwind", fastcall_dash_unwind = "fastcall-unwind",

View File

@ -467,7 +467,6 @@ ui/closures/issue-87814-2.rs
ui/closures/issue-90871.rs ui/closures/issue-90871.rs
ui/closures/issue-97607.rs ui/closures/issue-97607.rs
ui/closures/issue-99565.rs ui/closures/issue-99565.rs
ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
ui/codegen/auxiliary/issue-97708-aux.rs ui/codegen/auxiliary/issue-97708-aux.rs
ui/codegen/issue-101585-128bit-repeat.rs ui/codegen/issue-101585-128bit-repeat.rs
ui/codegen/issue-16602-1.rs ui/codegen/issue-16602-1.rs

26
tests/assembly/cmse.rs Normal file
View File

@ -0,0 +1,26 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
//@ needs-llvm-components: arm
#![crate_type = "lib"]
#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
// CHECK-LABEL: __acle_se_entry_point
// CHECK: bxns
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 {
0
}
// CHECK-LABEL: call_nonsecure
// CHECK: blxns
#[no_mangle]
pub fn call_nonsecure(
f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64,
) -> u64 {
unsafe { f(0, 1, 2, 3) }
}

View File

@ -1,13 +1,7 @@
// This checks that the attribute validation ICE in issue #105594 doesn't // This checks that the attribute validation ICE in issue #105594 doesn't
// recur. // recur.
//
//@ ignore-thumbv8m.base-none-eabi
#![feature(cmse_nonsecure_entry)]
fn main() {} fn main() {}
#[track_caller] //~ ERROR attribute should be applied to a function #[track_caller] //~ ERROR attribute should be applied to a function
static _A: () = (); static _A: () = ();
#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function
static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets

View File

@ -1,26 +1,11 @@
error[E0739]: attribute should be applied to a function definition error[E0739]: attribute should be applied to a function definition
--> $DIR/issue-105594-invalid-attr-validation.rs:9:1 --> $DIR/issue-105594-invalid-attr-validation.rs:6:1
| |
LL | #[track_caller] LL | #[track_caller]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
LL | static _A: () = (); LL | static _A: () = ();
| ------------------- not a function definition | ------------------- not a function definition
error: attribute should be applied to a function definition error: aborting due to 1 previous error
--> $DIR/issue-105594-invalid-attr-validation.rs:12:1
|
LL | #[cmse_nonsecure_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | static _B: () = ();
| ------------------- not a function definition
error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension For more information about this error, try `rustc --explain E0739`.
--> $DIR/issue-105594-invalid-attr-validation.rs:12:1
|
LL | #[cmse_nonsecure_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0739, E0775.
For more information about an error, try `rustc --explain E0739`.

View File

@ -0,0 +1,20 @@
//@ build-pass
//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
//@ needs-llvm-components: arm
#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items, intrinsics)]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
impl Copy for u32 {}
#[no_mangle]
pub extern "C-cmse-nonsecure-entry" fn test(
f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32,
a: u32,
b: u32,
c: u32,
) -> u32 {
f(a, b, c, 42)
}

View File

@ -1,10 +1,9 @@
// gate-test-cmse_nonsecure_entry // gate-test-cmse_nonsecure_entry
#[no_mangle] #[no_mangle]
#[cmse_nonsecure_entry] pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
//~^ ERROR [E0775] //~^ ERROR [E0570]
//~| ERROR [E0658] //~| ERROR [E0658]
pub extern "C" fn entry_function(input: u32) -> u32 {
input + 6 input + 6
} }

View File

@ -1,20 +1,20 @@
error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature error[E0658]: C-cmse-nonsecure-entry ABI is experimental and subject to change
--> $DIR/gate_test.rs:4:1 --> $DIR/gate_test.rs:4:12
| |
LL | #[cmse_nonsecure_entry] LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information = note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information
= help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
--> $DIR/gate_test.rs:4:1 --> $DIR/gate_test.rs:4:1
| |
LL | #[cmse_nonsecure_entry] LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
Some errors have detailed explanations: E0658, E0775. Some errors have detailed explanations: E0570, E0658.
For more information about an error, try `rustc --explain E0658`. For more information about an error, try `rustc --explain E0570`.

View File

@ -1,9 +0,0 @@
// Regression test for the ICE described in #83475.
#![crate_type="lib"]
#![feature(cmse_nonsecure_entry)]
#[cmse_nonsecure_entry]
//~^ ERROR: attribute should be applied to a function definition
struct XEmpty2;
//~^ NOTE: not a function definition

View File

@ -1,11 +0,0 @@
error: attribute should be applied to a function definition
--> $DIR/issue-83475.rs:6:1
|
LL | #[cmse_nonsecure_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | struct XEmpty2;
| --------------- not a function definition
error: aborting due to 1 previous error

View File

@ -3,14 +3,14 @@
//@ needs-llvm-components: arm //@ needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)] #![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core] #![no_core]
#[lang="sized"] #![crate_type = "lib"]
trait Sized { } #[lang = "sized"]
#[lang="copy"] trait Sized {}
trait Copy { } #[lang = "copy"]
trait Copy {}
impl Copy for u32 {} impl Copy for u32 {}
#[no_mangle] #[no_mangle]
#[cmse_nonsecure_entry] pub extern "C-cmse-nonsecure-entry" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
d d
} }

View File

@ -3,14 +3,19 @@
//@ needs-llvm-components: arm //@ needs-llvm-components: arm
#![feature(cmse_nonsecure_entry, no_core, lang_items)] #![feature(cmse_nonsecure_entry, no_core, lang_items)]
#![no_core] #![no_core]
#[lang="sized"] #[lang = "sized"]
trait Sized { } trait Sized {}
#[lang="copy"] #[lang = "copy"]
trait Copy { } trait Copy {}
impl Copy for u32 {} impl Copy for u32 {}
#[no_mangle] #[no_mangle]
#[cmse_nonsecure_entry] pub extern "C-cmse-nonsecure-entry" fn entry_function(
pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 { _: u32,
_: u32,
_: u32,
_: u32,
e: u32,
) -> u32 {
e e
} }

View File

@ -0,0 +1,9 @@
error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
--> $DIR/trustzone-only.rs:20: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`.

View File

@ -1,10 +1,25 @@
//@ ignore-thumbv8m.main-none-eabi //@ revisions: x86 aarch64 thumb7
#![feature(cmse_nonsecure_entry)] //
//@[x86] compile-flags: --target x86_64-unknown-linux-gnu
//@[x86] needs-llvm-components: x86
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
//@[aarch64] needs-llvm-components: aarch64
//@[thumb7] compile-flags: --target thumbv7em-none-eabi
//@[thumb7] needs-llvm-components: arm
#![feature(no_core, lang_items, rustc_attrs, cmse_nonsecure_entry)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for u32 {}
#[no_mangle] #[no_mangle]
#[cmse_nonsecure_entry] //~ ERROR [E0775] pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
pub extern "C" fn entry_function(input: u32) -> u32 { //~^ ERROR [E0570]
input + 6 input
} }
fn main() {} fn main() {}

View File

@ -1,9 +0,0 @@
error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
--> $DIR/trustzone-only.rs:5:1
|
LL | #[cmse_nonsecure_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0775`.

View File

@ -0,0 +1,9 @@
error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
--> $DIR/trustzone-only.rs:20: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`.

View File

@ -0,0 +1,9 @@
error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
--> $DIR/trustzone-only.rs:20: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`.

View File

@ -1,16 +0,0 @@
//@ 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 {}
#[no_mangle]
#[cmse_nonsecure_entry]
//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776]
pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
d
}

View File

@ -1,9 +0,0 @@
error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI
--> $DIR/wrong-abi.rs:12:1
|
LL | #[cmse_nonsecure_entry]
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0776`.

View File

@ -1,5 +1,6 @@
C C
C-cmse-nonsecure-call C-cmse-nonsecure-call
C-cmse-nonsecure-entry
C-unwind C-unwind
Rust Rust
aapcs aapcs