This is an archive of the discontinued LLVM Phabricator instance.

[BOLT][RISCV] Implement R_RISCV_ADD32/SUB32
ClosedPublic

Authored by jobnoorman on Mar 21 2023, 11:36 AM.

Details

Summary

Thispatch implements the R_RISCV_ADD32 and R_RISCV_SUB32 relocations for
RISC-V.

Diff Detail

Event Timeline

jobnoorman created this revision.Mar 21 2023, 11:36 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 21 2023, 11:36 AM
jobnoorman requested review of this revision.Mar 21 2023, 11:36 AM
jobnoorman edited the summary of this revision. (Show Details)

Add tests.

Note that the reloc-jt.s test is a real-world use case for label subtraction
on RISC-V (jump tables). However, I haven't found a way to implement this test
without having to hardcode the label difference. I have tried to minimize the
fragility of this test by hardcoding the section addresses but ideas to improve
this test would be appreciated.

rafauler added inline comments.Jun 20 2023, 5:34 PM
bolt/lib/Rewrite/RewriteInstance.cpp
2989

Aren't these data-to-code relocs? (BOLT doesn't need to update data-to-data relocs).

bolt/test/RISCV/reloc-jt.s
14–15

I'm not sure I get that. Aren't the two relocs supposed to point to the same symbol (.LJTI0_0)?

evandro removed a subscriber: evandro.Jun 20 2023, 5:42 PM
jobnoorman added inline comments.Jun 21 2023, 1:18 AM
bolt/lib/Rewrite/RewriteInstance.cpp
2989

Aren't these data-to-code relocs?

The relevant relocations in the reloc-jt.s test case look like this:

Relocation section '.rela.data' at offset 0x2068 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000002000  000300000023 R_RISCV_ADD32     000000000000100e .LBB0_1 + 0
000000002000  000200000027 R_RISCV_SUB32     0000000000002000 .LJTI0_0 + 0

.LJTI0_0 is a label in .data so the R_RISCV_SUB32 is a data-to-data relocation.

BOLT doesn't need to update data-to-data relocs

iiuc, BOLT usually doesn't need to update data-to-data relocs because the .data section is not relocated, correct?

In this case, however, the data-to-data reloc gets composed (see D146546) with a data-to-code reloc (R_RISCV_ADD32) so BOLT needs to process it to ensure the linker can properly update the value.

The condition here might be a bit coarse-grained, though, as all data-to-data relocs on RISC-V will now be processed even though it might not always be necessary. I suppose this doesn't really matter as the linker will just overwrite data contents with its original value. Or am I missing something here?

bolt/test/RISCV/reloc-jt.s
14–15

Aren't the two relocs supposed to point to the same symbol (.LJTI0_0)?

No, they aren't, but this is something that also used to confuse me :)

Creating a 32-bit PC-relative address on RISC-V works as follows:

  1. auipc ("add upper immediate to PC") with a R_RISCV_PCREL_HI20 reloc pointing to the target symbol (.LJTI0_0 in this case). The result only has the upper 20-bits filled, the lower 12 are set to 0.
  2. addi (or another instruction with a 12-bit immediate, like lw) with a R_RISCV_PCREL_LO12_I pointing to the corresponding auipc (.LBB0_0 in this case) to fill in the lower 12-bits.

The psABI has a good explanation for why it works this way (an important reason is that the auipc and addi are not necessarily consecutive).

rafauler added inline comments.Jun 21 2023, 1:40 PM
bolt/lib/Rewrite/RewriteInstance.cpp
2989

I see, it makes sense. You're correct in your assessment and it should be harmless. it does increase the chance that BOLT might incorrectly update some value that didn't even need updating in the first place, although that would be a hidden bug in BOLT that would need to be solved anyway.

bolt/test/RISCV/reloc-jt.s
14–15

Thanks for explaining

rafauler accepted this revision.Jun 21 2023, 2:51 PM
This revision is now accepted and ready to land.Jun 21 2023, 2:51 PM
This revision was automatically updated to reflect the committed changes.