Fix riscv64 li pseudo-instruction to properly initialize registers with small immediates#21
Conversation
Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com>
Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com>
li pseudo-instruction to properly initialize registers with small immediates
|
@copilot testしたら失敗してたわ。確認して。 |
Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com>
Fixed in commit 1fc7ea9. The test failure was due to an incorrect expectation in the test I added. For |
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a critical bug in the RISC-V 64 li (load immediate) pseudo-instruction that was generating incorrect code when loading small immediate values (those fitting in 12 bits) into registers. The bug caused the instruction to add the immediate to the register's uninitialized value instead of properly initializing the register.
- Fixed the
liimplementation to use the zero register (x0) as source when the upper 20 bits are zero - Added comprehensive test coverage for various immediate value scenarios
- Ensures proper register initialization for small immediates including zero
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/riscv64/builder.rs | Fixed li pseudo-instruction logic to use zero register for proper initialization when upper bits are zero |
| src/riscv64/tests.rs | Added comprehensive test suite covering zero, small positive/negative, large, and boundary value immediates |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Problem
The
li(load immediate) pseudo-instruction was generating incorrect code when loading small immediate values (those that fit in 12 bits, including 0) into registers. Instead of initializing the destination register to the immediate value, it was adding the immediate to the register's current uninitialized value.For example:
This was incorrectly generating:
When it should generate:
Root Cause
The
liinstruction implementation uses a two-part strategy:lui rd, upper(whenupper != 0)addi rd, rd, lowerThe bug occurred when
upper == 0(i.e., the immediate fits in 12 bits). In this case, step 1 was skipped, leavingrduninitialized. The code then executedaddi rd, rd, lower, which incorrectly usedrdas both source and destination.Solution
Modified the
lifunction to usex0(the hardwired zero register) as the source register whenupper == 0:Testing
Added comprehensive test
test_li_pseudo_instructionthat verifies correct behavior for:li(x1, 0)→addi x1, x0, 0✅li(x2, 100)→addi x2, x0, 100✅li(x3, -50)→addi x3, x0, -50✅li(x4, 0x12345678)→lui x4, 0x12345; addi x4, x4, 0x678✅All tests pass (81/81).
Fixes issue where
lipseudo-instruction with immediate value of 0 (and other small values) was generating incorrect instructions.Fixes #20
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.