As previously discussed in #308, relaxing traditional TLSGD is impossible in the current psABI because of the lack of the connection between la.tls.gd and call __tls_get_addr.
In my understanding, TLSDESC is a theoretically perfect alternative solution. However, it requires dynamic loader support, and its implementation in GLIBC (https://patchwork.sourceware.org/project/glibc/list/?series=24625) is still too far from productization. If TLSDESC is not translated to IE/LE, for example when we are linking shared objects, it would crash immediately when we get there. Even if GLIBC support is checked-in one day, people who are using old-versioned GLIBC are still not available to this excellent feature. And that's one reason why LLVM still prefer not to turn TLSDESC on by default (llvm/llvm-project#166540).
So, I would like to bring up the discussion again. This kind of relaxation (traditional GD -> LE/IE) seems more robust:
- It is a compiler/linker-only work, does not depend on any specific GLIBC version (once
__tls_get_addr is supported).
- Even if the relaxation does not happen, the program still runs well.
Currently I can think of two possible solutions:
Proposal 1 (from #308)
We can add a new relocation type called R_RISCV_TLS_CALL_LINK which contains the label of R_RISCV_TLS_GD_HI20, and append it to the call __tls_get_addr:
label:
auipc a0,0 # R_RISCV_TLS_GD_HI20 (symbol), R_RISCV_RELAX
addi a0,a0,0 # R_RISCV_PCREL_LO12_I (label), R_RISCV_RELAX
call __tls_get_addr@plt # R_RISCV_TLS_CALL_LINK(label), R_RISCV_CALL_PLT(__tls_get_addr), R_RISCV_RELAX
This idea is more like the idea of TLSDESC. It's more flexible for insn scheduling, allows intervening instructions, while may need more work on the psABI/compiler/assembler/linker I guess.
Proposal 2
We only do this translation when the three relocations (or insns) are strictly adjacent by address, which means by checking the offset strictly matches this:
+0x0: auipc a0, 0x0
+0x0: R_RISCV_TLS_GD_HI20
+0x0: R_RISCV_RELAX
+0x4: mv a0, a0
+0x4: R_RISCV_PCREL_LO12_I
+0x4: R_RISCV_RELAX
+0x8: auipc ra, 0x0
+0x8: R_RISCV_CALL_PLT __tls_get_addr
+0x8: R_RISCV_RELAX
+0xc: jalr ra
The idea comes from x86-64 psABI (http://man6.org/lib/pdfjs/web/viewer.html?file=/blog/PdfFile/x86-64-psABI-1.0.pdf, chapter 10.3.3), looks like they already forces tlsgd and the call to be together in psABI (chapter 10.3.1).
And we can add an option in the compiler which forces the combination of la.tls.gd and call __tls_get_addr to allow more relaxation chances in the linker.
The advantage is that it's more straightforward, the linker support is more trivial, and no major changes to the psABI (just add the GD->IE/LE translation rule).
The drawback is that it may be a little bit tricky, and may lose some flexibility in instruction scheduling.
May I ask does this motivation make sense? Which solution is more preferable, or more proposals?
As previously discussed in #308, relaxing traditional TLSGD is impossible in the current psABI because of the lack of the connection between
la.tls.gdandcall __tls_get_addr.In my understanding, TLSDESC is a theoretically perfect alternative solution. However, it requires dynamic loader support, and its implementation in GLIBC (https://patchwork.sourceware.org/project/glibc/list/?series=24625) is still too far from productization. If TLSDESC is not translated to IE/LE, for example when we are linking shared objects, it would crash immediately when we get there. Even if GLIBC support is checked-in one day, people who are using old-versioned GLIBC are still not available to this excellent feature. And that's one reason why LLVM still prefer not to turn TLSDESC on by default (llvm/llvm-project#166540).
So, I would like to bring up the discussion again. This kind of relaxation (traditional GD -> LE/IE) seems more robust:
__tls_get_addris supported).Currently I can think of two possible solutions:
Proposal 1 (from #308)
Proposal 2
May I ask does this motivation make sense? Which solution is more preferable, or more proposals?