Hi Dong,
Firstly, I think the RVE ABI is under-documented. I see that you've
started to clarify some aspects in
<
https://github.com/riscv/riscv-elf-psabi-doc/issues/77>, and I'd
encourage you to continue in that direction. I'm slightly confused as
the status of the current RV32E ABI given the stated plans to unveil a
set of new "embedded" ABIs. One of the motivations for upstreaming and
thus standardising the RV32E ABI implemented in GCC was that it was a
counterpart to the ilp32/ilp32f/ilp32d/lp64/lp64f/lp64d "Linux ABIs"
and thus orthogonal to whatever the is going to be proposed for the
new "embedded" ABIs
<
https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/CAFyWVaZsAWt8j4D%2B9ZvUJwNRMOiabwxeb45uRCAMvFwAaUFiwA%40mail.gmail.com>.
But the linked issue indicates there's no plan to support PLT.
As for implementing it, I'd separate the tasks somewhat. I've written
some notes here, which should get you started though I warn you that
it's unlikely I successfully enumerate every piece of code you may
need to change. You'll want to support both -march=rv32i -mabi=lp32e
and -march=rv32e -mabi=ilp32e.
* MC layer (assembler) support for -march-rv32e. Ensure that using
registers other than x0-x15 in assembly results in an error.
* RV32E calling convention support:
* LLVM-side support: Look specifically at CC_RISCV in
RISCVISelLowering.cpp as well as the callee-saved register sets in
RISCVCallingConv.td. Stack alignment is different for RV32E, so you'd
want to grep 'stackalign' in RISCVFrameLowering.cpp. I imagine you'll
want to modify RISCVRegisterInfo::getCalleeSavedRegs too, but if not
supporting -march=rv32i -mabi=ilp32e, it might not be necessary to
modify the calee-saved register set logic.
* Clang-side support: Due to the design of LLVM and its IR,
target-specific code is needed to do some amount of ABI lowering in
the frontend. For the integer RISC-V ABIs, this is basically limited
to counting the number of GPRs that are used used so that parameters
can be marked as signext/zeroext as appropriate if they are passed in
registers (they are anyext if passed on the stack). Look at NumArgGPRs
in RISCVABIInfo in lib/CodeGen/TargetInfo.cpp.
* RV32E codegen support: Need to ensure that when targeting
-march=rv32e that x16-x31 will never be selected.
In order to provide the MC layer and codegen support, we want to avoid
duplicating every instruction and instruction pattern in
RISCVInstrInfo.td with an RV32E instruction variant that uses a new
'EGPR' register class. I should think you'd be able to mark x16-x31 as
reserved in RISCVRegisterInfo if the target is rv32e. You'll want to
add a little extra logic in the AsmParser and Disassembler to reject
out-of-range registers for RV32E. I'd recommend looking at how the ARM
backend (lib/Target/ARM) handles the "+d16" target feature which
disables the top 16 double precision registers. Grep for FeatureD16
and HasD16.
Best,
Alex