Skip to content
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

Prestacked annotation proposal #53

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
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
68 changes: 67 additions & 1 deletion riscv-c-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ The compiler won't generate the prologue/epilogue for those functions with
`naked` attributes. This attribute is usually used when you want to write a
function with an inline assembly body.

This attribute is incompatible with the `interrupt` attribute.
This attribute is incompatible with the `interrupt` and `prestacked` attribute.

NOTE: Be aware that compilers might have further restrictions on naked
functions. Please consult your compiler's manual for more information.
Expand All @@ -204,6 +204,72 @@ function declares more than one mode or an undefined mode.

This attribute is incompatible with the `naked` attribute.

### `__attribute__((prestacked("<reglist>"))`

The prestacked attribute instructs the compiler which registers can be
used without saving/restoring them. It enables efficient use of
custom interrupt controllers that stack some of the architectural registers.
Without the need for compiler builds with a custom attributes.

It shall not imply `interrupt` attribute.
If used together with `interrupt` attribute, `prestacked` annotation overrides
its register preservation functionality.

To support auxiliary purposes, annotated functions should be callable by regular code.

> **_NOTE:_** If `x1` (aka `ra`) is included in the list, then a special return
mechanism must be used (e.g. `mret` from `interrupt` attribute)

`<reglist>` is a string literal, listing all registers available for use
in a given function, with a following syntax rules:

- no whitespaces
- raw register names rather than ABI mnemonics
- register range cover all registers between and including specified ("x4-x6"
is equivalent to "x4,x5,x6")
- register range must span at least 3 consecutive registers
- registers/ranges are separated by comma
- annotated callee saved registers have to be properly handled as a temporary ones by caller
- CSRs taking part in calling conventions are also subject to this mechanism
- registers must be sorted (integer, floating point, vector, custom, then by
lowest numbered)
- CSRs must be put after the architectural regfiles, those don’t have to be sorted
- argument registers that are passed but not included in the list, can be assumed
to be unmodified after return from an annotated function

> **_NOTE:_** Strict syntax rules allow better portability across compilers and ABIs.

This attribute is incompatible with the `naked` attribute.

#### usage examples

ilp32f, caller saved:\
`__attribute__((prestacked("x5-x7,x10-x17,x28-x31,f0-f7,f10-f17,f28-f31,fcsr")))`

standard risc-v irq, ilp32e, caller saved and `ra`:\
`__attribute__((interrupt, prestacked("x1,x5-x7,x10-x15")))`

preemptible CLIC irq with simplified range (e.g. shadow register file):\
`__attribute__((interrupt("CLIC-preemptible"), prestacked("x8-x15")))`

custom irq controller, F + P extensions (`ra`,`a0`,`a1` pushed on stack, shadow registers
where bit 2 of register operand is set):\
`__attribute__((prestacked("x4-x7,x10,x11,x12-x15,x20-x23,x28-x31,fcsr,vxsat")))`

optimization for `noreturn` functions (ilp32f):\
`__attribute__((noreturn, prestacked("x1,x5-x31,f0-f31,fcsr")))`

> **_NOTE:_** Compilers are intentionally preserving full prologues, of `noreturn` functions, to
allow backtracing and throwing exceptions. Which leads to stack and codespace
bloating. Prestacked annotation can be abused to get rid of the prologue stacking
without the risk of underflowing the stack as would happen with `naked` attribute.

pure assembly function (FP compute kernel) using only subset of caller saved
registers (`a0` argument not modified):\
`__attribute__((prestacked("x5,x11-x15,f10-f13,v0,v1,v8-v31,fcsr,vl,vtype,vstart")))`

> **_NOTE:_** This use case is necessary for efficient IPRA compilations. Beneficial even without IPRA.

### `__attribute__((target("<ATTR-STRING>")))`

The `target` attribute is used to enable a set of features or extensions for a
Expand Down