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

Stack frame layout for __riscv_{save,restore}_N #35

Open
dramforever opened this issue Apr 18, 2023 · 1 comment
Open

Stack frame layout for __riscv_{save,restore}_N #35

dramforever opened this issue Apr 18, 2023 · 1 comment

Comments

@dramforever
Copy link

Currently it (at least seems to me that) the stack frame layout used for __riscv_{save,restore}_N functions is the same for both GCC and LLVM:

And it's compatible with the frame pointer convention defined over at psABI at https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#frame-pointer-convention.

Is perhaps worthwhile to standardize the layout in which ra and s registers are saved on the stack somewhat? Like for example, how many bytes of stack are used for each N and the order for them. It would allow for frame pointers to be used with -msave-restore, and would allow for calculating the precise stack usage when using these routines.

Observation: For now, LLVM can use __riscv_save_N with addi s0, sp, ... for -msave-restore -fno-omit-frame-pointers, but GCC (as of 12.2.0) doesn't seem to know how to do that and emits longhand sequences for the saves and restores instead (See https://godbolt.org/z/6YYhxxzxx).

@lenary
Copy link

lenary commented Jun 17, 2024

This has come up again in llvm/llvm-project#95390 and llvm/llvm-project#95398 - which relate to versions of save/restore for the ilp32e/lp64e ABIs - and @jrtc27 wanted me to push for specifying/documenting/standardising the behaviour of these routines in this repository.

Given the situation where the CFI information for functions using save/restore is emitted by/inside those functions, not the save/restore procedure, I agree that we need to write down what the layout is, and follow it.

The implementations currently push multiple registers at the same time, to maintain stack pointer alignment for their respective ABIs. (It's worth ignoring architectures for these implementations, you need to follow your ABI's register convention).

At the moment the layouts in LLVM's compiler-rt are:

  • ilp32,ilp32f, and ilp32d push GP-registers four at a time, in register order with ra at the highest address.
  • lp64,lp64f, and lp64d push GP-registers two at a time, in register order with ra at the highest address.

In llvm/llvm-project#95398 I have proposed the following for the ilp32e/lp64e ABIs (which are used by RVE, but also by RVI when making code that is compatible with RVE code):

  • ilp32e, and lp64e pushes GP-registers one at a time, in register order with ra at the highest address.

I think making the register order, as much as possible, match the frame pointer convention, is sensible. I don't think these orders need to match the Zcmp push/pop instructions because if you have those, you would use them directly rather than calling out to these routines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants