Closed alistair23 closed 5 years ago
The constraint "=r"
allows the compiler to pick any register. This is true regardless of the architecture. Register selection never looks at the assembly code to make decisions on what register should be picked; rather, the register allocation algorithm considers the surrounding code and the the constraints only.
As thus, closing as invalid, but if you feel I’m wrong or that I overlooked something, complain, and I will reopen.
Looking at the Linux kernel C code you might be right. They get away with using the +r
as they have used register
variables in C.
#define SBI_CALL(which, arg0, arg1, arg2, arg3) ({ \
register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); \
register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); \
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); \
register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); \
register uintptr_t a7 asm ("a7") = (uintptr_t)(which); \
asm volatile ("ecall" \
: "+r" (a0) \
: "r" (a1), "r" (a2), "r" (a3), "r" (a7) \
: "memory"); \
a0; \
})
The following 32-bit RISC-V Rust code
Compiles to this:
Using:
As you can see, the compiled code assumes that the return value of the ecall is saved into a1 (x11). For the RISC-V ABI this is incorrect as the first return value should be saved into a0 see here.
Changing the output line to:
fixes the problem.