commit 78ec17447c5bd31bf94df1dcce31dd4975eda7f8
parent 5b6da982b55a6146cf7742d6254c6016fa8d2122
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 10 Jun 2026 18:07:35 -0700
fix(rv64): include arg reg a7/fa7 in the -O1 regalloc caller-saved/arg masks
The rv64 NativeAllocClassInfo masks (src/arch/riscv/native.c rv_classes)
dropped the 8th argument register (a7/fa7) and carried a spurious bit-18
(s2/fs2): arg_mask=0x0001fc00 covers only a0-a6, and caller_saved_mask
=0xf00400e0|0x0001fc00 sets bit 18 instead of bit 17. The -O1 register
allocator therefore never learned that a7 is caller-saved, so a parameter
delivered in a7 that is live across a call was left in a7 and never
evacuated to a callee-saved register; the call clobbered it, yielding a
garbage pointer and a SIGSEGV.
This broke the rv64 -O1 self-host: find_and_open_include (9 params; SrcLoc
takes two arg regs, so `resolved` lands in a7) crashes on every #include,
so stage2 SEGV'd compiling the first stage3 file (abi.c). Even
`#include "empty.h"` crashes the -O1-built kit. Pre-existing since the
original rv64 NativeTarget port (6eaf127a); latent because an 8th integer
arg live across a call is rare and -O0 has no register allocator.
Fix both INT and FP classes: arg_mask=0x0003fc00 (a0-a7/fa0-fa7) and
caller_saved_mask=0xf00000e0|0x0003fc00 (FP: 0xf00000ff|0x0003fc00),
matching the existing comments. Confirmed by disasm (a7 now homed to a
callee-saved reg), minimal int+fp 8-arg-live-across-call tests, and abi.c
/#include compiling cleanly with the -O1 rv64 kit.
Diffstat:
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/arch/riscv/native.c b/src/arch/riscv/native.c
@@ -480,10 +480,10 @@ static const NativeAllocClassInfo rv_classes[] = {
.phys = rv_int_phys,
.nphys = sizeof rv_int_phys / sizeof rv_int_phys[0],
/* t0-t6 (5-7,28-31) + a0-a7 (10-17) */
- .caller_saved_mask = 0xf00400e0u | 0x0001fc00u,
+ .caller_saved_mask = 0xf00000e0u | 0x0003fc00u,
/* s0-s11 (8,9,18-27) */
.callee_saved_mask = 0x0ffc0300u,
- .arg_mask = 0x0001fc00u,
+ .arg_mask = 0x0003fc00u,
.ret_mask = 0x00000c00u,
/* zero,ra,sp,gp,tp,t0,t1,t2,s0 (bits 0-8) + t3 (bit 28). t4/t5 are the
* driver scratch pool (reserved-from-alloc but listed in scratch[]). */
@@ -496,10 +496,10 @@ static const NativeAllocClassInfo rv_classes[] = {
.phys = rv_fp_phys,
.nphys = sizeof rv_fp_phys / sizeof rv_fp_phys[0],
/* ft0-ft7 (0-7), fa0-fa7 (10-17), ft8-ft11 (28-31) */
- .caller_saved_mask = 0xf00400ffu | 0x0001fc00u,
+ .caller_saved_mask = 0xf00000ffu | 0x0003fc00u,
/* fs0-fs11 (8,9,18-27) */
.callee_saved_mask = 0x0ffc0300u,
- .arg_mask = 0x0001fc00u,
+ .arg_mask = 0x0003fc00u,
.ret_mask = 0x00000c00u,
.reserved_mask = 0x0000000fu /* ft0-ft3 */},
};