Repository: rust
Issue: Tracking Issue for the #[cmse_nonsecure_entry] attribute
Labels: A-attributes,A-codegen,O-Arm,T-lang,T-compiler,B-unstable,C-tracking-issue,F-cmse_nonsecure_entry,S-tracking-design-concerns

This is a tracking issue for the PR #75810. It was deemed in that PR that a RFC was not necessary because the changes were small.
The feature gate for the issue is `#![feature(cmse_nonsecure_entry)]`.

## Description

The `cmse_nonsecure_entry` attribute is a target-dependent attribute available for `thumbv8m` targets. It directly maps to the attribute of the same name in LLVM.

It is to be used under the [TrustZone-M technology for Armv8-M architecture](https://developer.arm.com/documentation/100690/latest/).

It will modify code generation of Secure entry functions:
* add a special symbol on the function which is the `__acle_se_` prefix and the
  standard function name
* constrain the number of parameters to avoid using the Non-Secure stack
* before returning from the function, clear registers that might contain Secure
  information
* use the `BXNS` instruction to return

See [section 5.4 of ARMv8-M Security Extensions: Requirements on Development Tools - Engineering Specification](https://developer.arm.com/documentation/ecm0359818/latest/) for more details.

## Example 

Having a Secure entry function named `entry_function`:
```rust
#![feature(cmse_nonsecure_entry)]

#[no_mangle]
#[cmse_nonsecure_entry]
pub extern "C" fn entry_function(in: u32) -> u32 {
    in + 6
}
```

With those commands:

```text
$ rustc --emit obj --crate-type lib --target thumbv8m.main-none-eabi function.rs
$ arm-none-eabi-objdump -D function.o
```

it will emit the following assembly:

```text
00000000 <entry_function>:
   0:   b580            push    {r7, lr}
   2:   466f            mov     r7, sp
   4:   b082            sub     sp, #8
   6:   9001            str     r0, [sp, #4]
   8:   1d81            adds    r1, r0, #6
   a:   460a            mov     r2, r1
   c:   4281            cmp     r1, r0
   e:   9200            str     r2, [sp, #0]
  10:   d30b            bcc.n   2a <entry_function+0x2a>
  12:   e7ff            b.n     14 <entry_function+0x14>
  14:   9800            ldr     r0, [sp, #0]
  16:   b002            add     sp, #8
  18:   e8bd 4080       ldmia.w sp!, {r7, lr}
  1c:   4671            mov     r1, lr
  1e:   4672            mov     r2, lr
  20:   4673            mov     r3, lr
  22:   46f4            mov     ip, lr
  24:   f38e 8800       msr     CPSR_f, lr
  28:   4774            bxns    lr
  2a:   f240 0000       movw    r0, #0
  2e:   f2c0 0000       movt    r0, #0
  32:   f240 0200       movw    r2, #0
  36:   f2c0 0200       movt    r2, #0
  3a:   211c            movs    r1, #28
  3c:   f7ff fffe       bl      0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E>
  40:   defe            udf     #254    ; 0xfe
```

You can see from `1c` to `24` the clearing of the registers and the `BXNS` instruction used on `28`.

## Steps

* [X] Initial implementation: #75810
* [ ] ABI compliance should be checked by rustc instead of LLVM: https://github.com/rust-lang/rust/issues/81347