As a reminder, RISC-V calling conventions can be reviewed at https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#procedure-calling-convention. You may also find my "golden model" useful https://github.com/lowRISC/riscv-calling-conv-model.
After lots of back and forth, I'm ended up implementing a custom calling convention function. I've found TableGen-based calling convention definitions to lack flexibility and require substantial boilerplate when you reach their limitations (see e.g. MipsCCState). I'm open to alternative suggestions of course. An additional advantage of CC_RISCV is that it can be trivially parametrised by XLEN and FLEN, meaning the same code paths can be used to support the 10 RISC-V calling conventions we need to support (-mabi=ilp32e, -mabi=ilp32, -mabi=ilp32f, -mabil=ilp32d, rv32i* varargs, rv32e* varargs, -mabi=lp64, -mabi=lp64f, -mabi=lp64d, rv64 varargs).
This patch adds support for:
- Passing large scalars according to the RV32I calling convention
- Byval arguments
- Passing values on the stack when the argument registers are exhausted
It also documents the ABI lowering that a language frontend is expected to perform.
A follow-up patch adds support for varargs.
Although I've kept it as a separate patch at https://github.com/lowrisc/riscv-llvm, I've included changes to CallingConvLower.h here in order to make review easier. We add PendingArgFlags CCState, as a companion to PendingLocs.
The PendingLocs vector is used by a number of backends to handle arguments that are split during legalisation. However CCValAssign doesn't keep track of the original argument alignment. Therefore, add a PendingArgFlags vector which can be used to keep track of the ISD::ArgFlagsTy for every value added to PendingLocs.
CCing @kparzysz. As another backend owner who has also ended up implementing custom calling convention functions I thought you may also have input.