riscv-non-isa/riscv-asm-manual

`.option (no)?relax` and label differences

MaskRay opened this issue · 1 comments

GNU assembler emits a pair of R_RISCV_ADD32 and R_RISCV_SUB32 for 32-bit label differences. This assembler construct is useful for metadata and the desired behavior should be documented somewhere.

.option push
.option norelax
.section .text,"ax",@progbits
lo:
  ret
hi:
.option pop

.data
.long hi - lo

Currently both GNU assembler and LLVM integrated assembler emit R_RISCV_ADD32 R_RISCV_SUB32 regardless of the relax/norelax state. I think it will be useful to have a way to emit a constant in the norelax case to make relocatable object files smaller. This will help clang -g:

.section        .debug_info,"",@progbits
...
.word   .Lfunc_end0-.Lfunc_begin0

If 32-bit label differences always lead to R_RISCV_ADD32 R_RISCV_SUB32, it will be cumbersome to get rid of the relocations in -mno-relax mode. An object file producer can do some hard work emitting a constant but this isn't feasible for an assembly file producer.

The documentation may specify:

  • the symbols must be STB_LOCAL. Currently the assemblers don't report an error even if this output may not make sense as linked output.
  • the behavior when the labels are not in a SHF_EXECINSTR section.

@compnerd

I have a much better understanding of label differences now and think this is probably out of the scope of an assembler manual. https://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation#label-differences-related-to-text-section-symbols

When my https://reviews.llvm.org/D155357 ([RISCV] Allow delayed decision for ADD/SUB relocations) lands, .long hi - lo in the case will generate no relocation.

GNU assembler conservatively generates relocations because lo and hi are in a text section (TC_FORCE_RELOCATION_SUB_SAME in gas/write.c:fix_segment returns true).