[PATCH] D100835: [WIP][LLD][RISCV] Linker Relaxation

Chih-Mao Chen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 20 02:54:43 PDT 2021


PkmX created this revision.
PkmX added reviewers: ruiu, MaskRay, jrtc27.
Herald added subscribers: vkmr, frasercrmck, dang, evandro, luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, the_o, brucehoult, MartinMosbeck, rogfer01, atanasyan, mgrang, edward-jones, zzheng, shiva0217, kito-cheng, niosHD, sabuasal, simoncook, johnrusso, rbar, asb, arichardson, sdardis, emaste.
PkmX requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This patch fully implements linker relaxation for RISC-V including relaxation for `R_RISCV_CALL`, `R_RISCV_HI20/LO12`, `R_RISCV_PCREL_HI20/LO12` and handling for `R_RISCV_ALIGN`. Just for reference/link, there were some previous efforts/discussion to implementation linker relaxation in D77694 <https://reviews.llvm.org/D77694> and D79105 <https://reviews.llvm.org/D79105>.

As linker relaxation is highly specific to RISC-V at the moment, most of the work are done in the `Target::finalizeContents()` function and isolated from generic code. For now I'm avoiding trying to come up with a common relaxation framework for multiple targets as their needs may be greatly different.

The relaxation process is split into several passes:

- For each executable input section, search its relocation vector for `R_RISCV_RELAX` and determine how to relax the previous relocation.
- If the relocation is `R_RISCV_CALL` (auipc+jalr pair), try to relax to jal or c.jal if the jump target is in range. This assumes that the PC-relative offset can only become smaller during the relaxation process.
- If the relocation is `R_RISCV_HI20/LO12` (absolute addressing) and the target symbol can be addressed from `__global_pointer$` (defaulted to `.sdata+0x800`), delete the `lui` and rewrite the lo part to use `gp` as source register.
- If the relocation is `R_RISCV_PCREL_HI20/LO12`, this requires two-pass to relax as `PCREL_LO12` links to its `PCREL_HI20` for address calculation and they may appear in arbitrary order in an input section. To preserve the look up from `PCREL_LO12` the first pass relaxes/deletes`PCREL_LO12` and the second pass handles `PCREL_HI20`. The implementation is simpler than that in bfd because lld doesn't allow addends in `PCREL_LO12` (https://github.com/riscv/riscv-elf-psabi-doc/issues/184), and so both parts can be relaxed independently.
- The range of bytes are deleted after processing relaxation for a whole input section. This requires adjusting section content, symbol addresses/sizes and relocation offsets, which is handled in `InputSectionBase::deleteRanges`. Compared to other approaches we use a algorithm that is not quadratic by sorting symbols, relocations and bytes to be deleted by offset.
- After relaxation, handle alignment as symbols addresses are now fixed modulo section alignment. This is always enabled regardless of the `--relax` option as this is required for correctness.

There are still some issues to solve:

- `--emit-relocs` will be broken on relaxed section as currently it just copies the corresponding `.rela` section verbatim from input. It needs to be fixed to build relocation entries from the section's relocation vector.
- The patch adds two additional `RelExpr` (`R_RISCV_GPREL` and `R_RELAX_HINT`) which unfortunately makes it unable to fit into a 64-bit mask, so it is now changed back to sequential checking. I think it should be somehow split into target-independent (`R_ABS`, `R_PC`, ...) exprs and target-dependent (`R_RISCV_...`, `R_MIPS_...`) exprs which can overlap in numeric range, but it is probably out of the scope of this patch.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100835

Files:
  lld/ELF/Arch/RISCV.cpp
  lld/ELF/Config.h
  lld/ELF/Driver.cpp
  lld/ELF/InputSection.cpp
  lld/ELF/InputSection.h
  lld/ELF/Options.td
  lld/ELF/Relocations.cpp
  lld/ELF/Relocations.h
  lld/ELF/Target.h
  lld/ELF/Writer.cpp
  lld/test/ELF/riscv-gp.s
  lld/test/ELF/riscv-relax-align-rvc.s
  lld/test/ELF/riscv-relax-align.s
  lld/test/ELF/riscv-relax-call.s
  lld/test/ELF/riscv-relax-hi20-lo12.s
  lld/test/ELF/riscv-relax-pcrel.s
  lld/test/ELF/riscv-relax-syms.s
  lld/test/ELF/riscv-reloc-align.s

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D100835.338775.patch
Type: text/x-patch
Size: 36747 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210420/f1170e36/attachment-0001.bin>


More information about the llvm-commits mailing list