diff options
author | 2024-01-28 15:52:19 -0800 | |
---|---|---|
committer | 2024-08-11 20:36:41 -0700 | |
commit | f0953f2695185e259f7de6611f3cf1282a5a1a47 (patch) | |
tree | 97093b0388f7373cab6d7722ff4e3246add6deea | |
parent | riscv: Emit large int or float in constant pool (diff) | |
download | pypy-f0953f2695185e259f7de6611f3cf1282a5a1a47.tar.gz pypy-f0953f2695185e259f7de6611f3cf1282a5a1a47.tar.bz2 pypy-f0953f2695185e259f7de6611f3cf1282a5a1a47.zip |
riscv: Support large frame slot offsets
This commit adds support for large frame slot offsets. Before this
commit, the code generator assumes the frame slot offsets is always
addressable with signed 12-bit immediate. But, it turns out 12-bit is
not enough. `lib_python_tests.py` `test_tarfile` triggers the assertion
in the code generator.
This commit fixes the problem by emitting `load_imm + ADD` when the
immediate is too large for `ADDI`.
Test: pypy2.7 testrunner/lib_python_tests.py -v -k test_tarfile
-rw-r--r-- | rpython/jit/backend/riscv/assembler.py | 26 | ||||
-rw-r--r-- | rpython/jit/backend/riscv/codebuilder.py | 20 |
2 files changed, 40 insertions, 6 deletions
diff --git a/rpython/jit/backend/riscv/assembler.py b/rpython/jit/backend/riscv/assembler.py index 5f6029bba2..3aa4828805 100644 --- a/rpython/jit/backend/riscv/assembler.py +++ b/rpython/jit/backend/riscv/assembler.py @@ -1671,9 +1671,11 @@ class AssemblerRISCV(OpAssembler): def _mov_stack_to_loc(self, prev_loc, loc): offset = prev_loc.value if loc.is_core_reg(): - self.mc.load_int(loc.value, r.jfp.value, offset) + self.mc.load_int_from_base_plus_offset(loc.value, r.jfp.value, + offset) elif loc.is_fp_reg(): - self.mc.load_float(loc.value, r.jfp.value, offset) + self.mc.load_float_from_base_plus_offset(loc.value, r.jfp.value, + offset, tmp=r.x31.value) else: assert 0, 'unsupported case' @@ -1681,7 +1683,15 @@ class AssemblerRISCV(OpAssembler): if loc.is_core_reg(): self.mc.MV(loc.value, prev_loc.value) elif loc.is_stack(): - self.mc.store_int(prev_loc.value, r.jfp.value, loc.value) + # Use `r.shadow_old` as `scratch_reg`. We can't use `r.x31` + # because `prev_loc` can be `r.x31` (see also. + # `regalloc_prepare_move`). We can't use `r.ra` because `r.ra` is + # allocated for the callee function address in `callbuiler.py` + # and its lifetime overlaps with `remap_frame_layout`. + scratch_reg = r.shadow_old + self.mc.store_int_to_base_plus_offset(prev_loc.value, r.jfp.value, + loc.value, + tmp=scratch_reg.value) else: assert 0, 'unsupported case' @@ -1692,7 +1702,9 @@ class AssemblerRISCV(OpAssembler): assert XLEN == 8 and FLEN == 8 self.mc.FMV_X_D(loc.value, prev_loc.value) elif loc.is_stack(): - self.mc.store_float(prev_loc.value, r.jfp.value, loc.value) + self.mc.store_float_to_base_plus_offset(prev_loc.value, + r.jfp.value, loc.value, + tmp=r.x31.value) else: assert 0, 'unsupported case' @@ -1701,7 +1713,8 @@ class AssemblerRISCV(OpAssembler): self.mc.load_float_imm(loc.value, prev_loc.value) elif loc.is_stack(): self.mc.load_float_imm(r.f31.value, prev_loc.value) - self.mc.store_float(r.f31.value, r.jfp.value, loc.value) + self.mc.store_float_to_base_plus_offset(r.f31.value, r.jfp.value, + loc.value, tmp=r.x31.value) else: assert 0, 'unsupported case' @@ -1713,7 +1726,8 @@ class AssemblerRISCV(OpAssembler): elif loc.is_stack(): # Move a value from JITFRAME stack to raw stack. scratch_reg = r.x31 - self.mc.load_int(scratch_reg.value, r.jfp.value, loc.value) + self.mc.load_int_from_base_plus_offset(scratch_reg.value, + r.jfp.value, loc.value) self.mc.store_int(scratch_reg.value, r.sp.value, sp_offset) elif loc.is_fp_reg(): self.mc.store_float(loc.value, r.sp.value, sp_offset) diff --git a/rpython/jit/backend/riscv/codebuilder.py b/rpython/jit/backend/riscv/codebuilder.py index 8e05b9640f..c5654e2a14 100644 --- a/rpython/jit/backend/riscv/codebuilder.py +++ b/rpython/jit/backend/riscv/codebuilder.py @@ -172,6 +172,26 @@ class AbstractRISCVBuilder(object): def store_float(self, rs2, rs1, imm): self.FSD(rs2, rs1, imm) + # Load an FLEN-bit float from rs1+imm (imm can be a large constant) + def load_float_from_base_plus_offset(self, rd, rs1, imm, tmp): + assert tmp != rs1 + if check_imm_arg(imm): + self.load_float(rd, rs1, imm) + else: + self.load_int_imm(tmp, imm) + self.ADD(tmp, tmp, rs1) + self.load_float(rd, tmp, 0) + + # Store an FLEN-bit float to rs1+imm (imm can be a large constant) + def store_float_to_base_plus_offset(self, rs2, rs1, imm, tmp): + assert tmp != rs1 + if check_imm_arg(imm): + self.store_float(rs2, rs1, imm) + else: + self.load_int_imm(tmp, imm) + self.ADD(tmp, tmp, rs1) + self.store_float(rs2, tmp, 0) + # Load a rffi.INT from imm(rs1) def load_rffi_int(self, rd, rs1, imm): # Note: On RV64 (LP64), rffi.INT is 32-bit signed integer. |