Skip to content

Commit 38ae44f

Browse files
lenarycmuellner
authored andcommitted
Codify Save/Restore Frame Layout
These layouts need to be compatible between what the compiler expects when emitting CFI information, and what the library actually implements, so we write a bit more detail about how these should work to ensure that compatibility. Fixes #35 Signed-off-by: Sam Elliott <[email protected]>
1 parent a802a11 commit 38ae44f

File tree

1 file changed

+37
-3
lines changed

1 file changed

+37
-3
lines changed

src/toolchain-conventions.adoc

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,12 @@ have the following signatures:
193193
- `void` `+__riscv_restore_<N>(void)+`
194194
- `void` `+__riscv_restore_tailcall_<N>+` `(void * tail /* passed in t1 */)` (LLVM/compiler-rt only)
195195

196-
`<N>` is a value between 0 and 12 and corresponds to the number of
197-
registers between `s0` and `s11` that are saved/restored. The return
198-
address register `ra` is always included in the registers saved and restored.
196+
`<N>` is a value between 0 and 12 and corresponds to the number of registers
197+
between `s0` and `s11` that are saved/restored. When using the `ILP32E` ABI,
198+
`<N>` can be at most 2, as `s3` to `s12` are temporary registers in this ABI.
199+
200+
The return address register `ra` is always included in the registers saved and
201+
restored.
199202

200203
The `+__riscv_save_<N>+` functions are called from the prologue, using `t0` as
201204
the link register to avoid clobbering `ra`. They allocate stack space for the
@@ -216,6 +219,37 @@ As of November 2021 the additional tail-call entry points are only
216219
implemented in compiler-rt, and calls will only be generated by LLVM
217220
when the option `-mllvm -save-restore-tailcall` is specified.
218221

222+
=== Save Restore Routine Stack Frame Layouts
223+
224+
While the implementation of the save restore routines are in the library, it is
225+
the compiler's responsibility to emit the unwind information (CFI) for the
226+
registers that are saved and restored by these routines, so the compilers and
227+
the libraries must agree on the stack layouts used by these routines.
228+
229+
As the stack pointer must be correctly aligned at all times, the save restore
230+
routines are expected to allocate more stack than they require to spill all
231+
registers in many cases. Additional Callee-saved registers, beyond those
232+
requested, may be saved and restored by these routines, in line with the
233+
existing practice of saving and restoring registers in batches to match the
234+
stack alignment (which saves on code size).
235+
236+
For the `LP64`, `LP64F`, `LP64D`, and `LP64Q` ABIs, the save restore routines
237+
use `roundup(N+1, 2) * 8` bytes of stack space (where `roundup(val, multiple)`
238+
rounds `value` up to a multiple of `multiple`).
239+
240+
For the `ILP32`, `ILP32F`, and `ILP32D` ABIs, the save restore routines use
241+
`roundup(N+1, 4) * 4` bytes of stack space.
242+
243+
For the `ILP32E` ABI, the save restore routines use `(N+1) * 4` bytes of stack
244+
space (which reflects the lower stack alignment used by this ABI).
245+
246+
In all the save restore routines, across all ABIs, `ra` is stored adjacent to
247+
the incoming stack pointer (highest address), then the Callee-Saved registers in
248+
register order from `s0` to `s11`. This follows the [Frame Pointer
249+
Convention](https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#frame-pointer-convention),
250+
whether or not a frame pointer is actually being used, and contradicts with the
251+
order used by Zcmp push/pop instructions.
252+
219253
== Conventions for vendor extensions
220254

221255
Support for custom instruction set extensions are an important part of RISC-V,

0 commit comments

Comments
 (0)