Index: lld/ELF/Arch/SPARCV9.cpp =================================================================== --- lld/ELF/Arch/SPARCV9.cpp +++ lld/ELF/Arch/SPARCV9.cpp @@ -30,6 +30,8 @@ uint64_t pltEntryAddr) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, const Relocation &, + uint64_t val) const override; }; } // namespace @@ -43,6 +45,8 @@ pltEntrySize = 32; pltHeaderSize = 4 * pltEntrySize; + tlsGotRel = R_SPARC_TLS_TPOFF64; + defaultCommonPageSize = 8192; defaultMaxPageSize = 0x100000; defaultImageBase = 0x100000; @@ -88,6 +92,11 @@ case R_SPARC_TLS_LE_HIX22: case R_SPARC_TLS_LE_LOX10: return R_TPREL; + case R_SPARC_TLS_IE_HI22: + case R_SPARC_TLS_IE_LO10: + case R_SPARC_TLS_IE_LDX: + case R_SPARC_TLS_IE_ADD: + return R_GOT_OFF; default: error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + ") against symbol " + toString(s)); @@ -120,6 +129,7 @@ checkUInt(loc, val, 22, rel); write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); break; + case R_SPARC_TLS_IE_HI22: case R_SPARC_GOT22: case R_SPARC_PC22: case R_SPARC_LM22: @@ -146,6 +156,7 @@ // T-simm10 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); break; + case R_SPARC_TLS_IE_LO10: case R_SPARC_LO10: // T-simm13 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff)); @@ -185,11 +196,36 @@ // T-simm13 write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00); break; + case R_SPARC_TLS_IE_LDX: + case R_SPARC_TLS_IE_ADD: + break; default: llvm_unreachable("unknown relocation"); } } +void SPARCV9::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, + uint64_t val) const { + switch (rel.type) { + case R_SPARC_TLS_IE_ADD: + return; + case R_SPARC_TLS_IE_LDX: + // call ldx [%r1 + %r2], %r3 -> nop + write32(loc, 0x01000000); + return; + case R_SPARC_TLS_IE_HI22: + relocateNoSym(loc, R_SPARC_TLS_LE_HIX22, val); + return; + case R_SPARC_TLS_IE_LO10: + // or %r1, %tie_lo10(sym), %r2 -> xor %r1, %tle_lox10(sym), %r2 + write32be(loc, (read32be(loc) & ~0x01f80000) | 0x180000); + relocateNoSym(loc, R_SPARC_TLS_LE_LOX10, val); + return; + default: + llvm_unreachable("unsupported relocation for TLS IE to LE relaxation"); + } +} + void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/, uint64_t pltEntryAddr) const { const uint8_t pltData[] = { Index: lld/test/ELF/sparcv9-tls-ie.s =================================================================== --- /dev/null +++ lld/test/ELF/sparcv9-tls-ie.s @@ -0,0 +1,33 @@ +# REQUIRES: sparc +# RUN: llvm-mc -filetype=obj -triple=sparcv9 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: ld.lld -shared %t.o -o %t.so +# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s +# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=RELAX %s + +# CHECK: sethi 0, %o0 +# CHECK-NEXT: or %o0, 8, %o0 +# CHECK-NEXT: ldx [%l7+%o0], %o0 +# CHECK-NEXT: add %g7, %o0, %o0 + +# IE -> LE Relaxation + +# RELAX: sethi 1, %o0 +# RELAX-NEXT: xor %o0, -2, %o0 +# RELAX-NEXT: nop +# RELAX-NEXT: add %g7, %o0, %o0 +sethi %tie_hi22(a), %o0 +or %o0, %tie_lo10(a), %o0 +ldx [%l7 + %o0], %o0, %tie_ldx(a) +add %g7, %o0, %o0, %tie_add(a) + +.section .tbss +.globl a +a: +.zero 1024+2 +b: + +# RELOC: .rela.dyn { +# RELOC-NEXT: R_SPARC_TLS_TPOFF64 a 0x0 +# RELOC-NEXT: }