case R_PPC64_GOT_TLSLD16_LO:
writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13, 0
break;
- case R_PPC64_TLSLD:
- write32(loc, NOP);
- write32(loc + 4, 0x38631000); // addi r3, r3, 4096
+ case R_PPC64_GOT_TLSLD_PCREL34:
+ // Relax from paddi r3, 0, x1@got@tlsld@pcrel, 1 to
+ // paddi r3, r13, 0x1000, 0
+ writePrefixedInstruction(loc, 0x06000000386d1000);
+ break;
+ case R_PPC64_TLSLD: {
+ // PC Relative Relaxation:
+ // Relax from bl __tls_get_addr@notoc(x@tlsld)
+ // to
+ // nop
+ // TOC Relaxation:
+ // Relax from bl __tls_get_addr(x@tlsld)
+ // nop
+ // to
+ // nop
+ // addi r3, r3, 4096
+ const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
+ if (locAsInt % 4 == 0) {
+ write32(loc, NOP);
+ write32(loc + 4, 0x38631000); // addi r3, r3, 4096
+ } else if (locAsInt % 4 == 1) {
+ write32(loc - 1, NOP);
+ } else {
+ errorOrWarn("R_PPC64_TLSLD has unexpected byte alignment");
+ }
break;
+ }
case R_PPC64_DTPREL16:
case R_PPC64_DTPREL16_HA:
case R_PPC64_DTPREL16_HI:
case R_PPC64_DTPREL16_DS:
case R_PPC64_DTPREL16_LO:
case R_PPC64_DTPREL16_LO_DS:
+ case R_PPC64_DTPREL34:
relocate(loc, rel, val);
break;
default:
case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TLSLD16_LO:
return R_TLSLD_GOT;
+ case R_PPC64_GOT_TLSLD_PCREL34:
+ return R_TLSLD_PC;
case R_PPC64_GOT_TPREL16_HA:
case R_PPC64_GOT_TPREL16_LO_DS:
case R_PPC64_GOT_TPREL16_DS:
case R_PPC64_DTPREL16_LO:
case R_PPC64_DTPREL16_LO_DS:
case R_PPC64_DTPREL64:
+ case R_PPC64_DTPREL34:
return R_DTPREL;
case R_PPC64_TLSGD:
return R_TLSDESC_CALL;
case R_PPC64_DTPREL64:
write64(loc, val - dynamicThreadPointerOffset);
break;
+ case R_PPC64_DTPREL34:
+ // The Dynamic Thread Vector actually points 0x8000 bytes past the start
+ // of the TLS block. Therefore, in the case of R_PPC64_DTPREL34 we first
+ // need to subtract that value then fallthrough to the general case.
+ val -= dynamicThreadPointerOffset;
+ LLVM_FALLTHROUGH;
case R_PPC64_PCREL34:
case R_PPC64_GOT_PCREL34:
case R_PPC64_GOT_TLSGD_PCREL34:
+ case R_PPC64_GOT_TLSLD_PCREL34:
case R_PPC64_GOT_TPREL_PCREL34:
case R_PPC64_TPREL34: {
const uint64_t si0Mask = 0x00000003ffff0000;
--- /dev/null
+# REQUIRES: ppc
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/asm -o %t.o
+# RUN: ld.lld -T %t/lds --shared -soname=t-ld %t.o -o %t-ld.so
+# RUN: ld.lld -T %t/lds %t.o -o %t-ldtole
+
+# RUN: llvm-readelf -r %t-ld.so | FileCheck %s --check-prefix=LD-RELOC
+# RUN: llvm-readelf -s %t-ld.so | FileCheck %s --check-prefix=LD-SYM
+# RUN: llvm-readelf -x .got %t-ld.so | FileCheck %s --check-prefix=LD-GOT
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-ld.so | FileCheck %s --check-prefix=LD
+
+# RUN: llvm-readelf -r %t-ldtole | FileCheck %s --check-prefix=LDTOLE-RELOC
+# RUN: llvm-readelf -s %t-ldtole | FileCheck %s --check-prefix=LDTOLE-SYM
+# RUN: llvm-readelf -x .got %t-ldtole 2>&1 | FileCheck %s --check-prefix=LDTOLE-GOT
+# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-ldtole | FileCheck %s --check-prefix=LDTOLE
+
+## This test checks the Local Dynamic PC Relative TLS implementation for lld.
+## LD - Local Dynamic with no relaxation possible
+## LDTOLE - Local Dynamic relaxed to Local Exec
+
+# LD-RELOC: Relocation section '.rela.dyn' at offset 0x10080 contains 1 entries:
+# LD-RELOC: 0000000001004168 0000000000000044 R_PPC64_DTPMOD64 0
+
+# LD-SYM: Symbol table '.symtab' contains 11 entries:
+# LD-SYM: 5: 0000000000000000 0 TLS LOCAL DEFAULT 13 x
+# LD-SYM-NEXT: 6: 0000000000000004 0 TLS LOCAL DEFAULT 13 y
+
+# LD-GOT: section '.got':
+# LD-GOT-NEXT: 0x01004160 60c10001 00000000 00000000 00000000
+# LD-GOT-NEXT: 0x01004170 00000000 00000000
+
+# LDTOLE-RELOC: There are no relocations in this file.
+
+# LDTOLE-SYM: Symbol table '.symtab' contains 9 entries:
+# LDTOLE-SYM: 5: 0000000000000000 0 TLS LOCAL DEFAULT 6 x
+# LDTOLE-SYM-NEXT: 6: 0000000000000004 0 TLS LOCAL DEFAULT 6 y
+
+# LDTOLE-GOT: section '.got':
+# LDTOLE-GOT-NEXT: 0x01004020 20c00001 00000000
+
+//--- lds
+SECTIONS {
+ .text_addr 0x1001000 : { *(.text_addr) }
+ .text_val 0x1002000 : { *(.text_val) }
+ .text_twoval 0x1003000 : { *(.text_twoval) }
+ .text_incrval 0x1004000 : { *(.text_incrval) }
+}
+
+//--- asm
+# LD-LABEL: <LDAddr>:
+# LD: paddi 3, 0, 12644, 1
+# LD-NEXT: bl 0x1001020
+# LD-NEXT: paddi 3, 3, -32768, 0
+# LD-NEXT: blr
+# LDTOLE-LABEL: <LDAddr>:
+# LDTOLE: paddi 3, 13, 4096, 0
+# LDTOLE-NEXT: nop
+# LDTOLE-NEXT: paddi 3, 3, -32768, 0
+# LDTOLE-NEXT: blr
+.section .text_addr, "ax", %progbits
+LDAddr:
+ ## TODO: Adding a reference to .TOC. since LLD doesn't gracefully handle the
+ ## case where we define a .got section but have no references to the toc base
+ ## yet.
+ addis 2, 12, .TOC.-LDAddr@ha
+ paddi 3, 0, x@got@tlsld@pcrel, 1
+ bl __tls_get_addr@notoc(x@tlsld)
+ paddi 3, 3, x@dtprel, 0
+ blr
+
+# LD-LABEL: <LDVal>:
+# LD: paddi 3, 0, 8552, 1
+# LD-NEXT: bl 0x1001020
+# LD-NEXT: paddi 3, 3, -32768, 0
+# LD-NEXT: lwz 3, 0(3)
+# LD-NEXT: blr
+# LDTOLE-LABEL: <LDVal>:
+# LDTOLE: paddi 3, 13, 4096, 0
+# LDTOLE-NEXT: nop
+# LDTOLE-NEXT: paddi 3, 3, -32768, 0
+# LDTOLE-NEXT: lwz 3, 0(3)
+# LDTOLE-NEXT: blr
+.section .text_val, "ax", %progbits
+LDVal:
+ paddi 3, 0, x@got@tlsld@pcrel, 1
+ bl __tls_get_addr@notoc(x@tlsld)
+ paddi 3, 3, x@dtprel, 0
+ lwz 3, 0(3)
+ blr
+
+# LD-LABEL: <LDTwoVal>:
+# LD: paddi 3, 0, 4456, 1
+# LD-NEXT: bl 0x1001020
+# LD-NEXT: paddi 3, 3, -32768, 0
+# LD-NEXT: lwz 2, 0(3)
+# LD-NEXT: paddi 3, 3, -32764, 0
+# LD-NEXT: lwz 3, 0(3)
+# LD-NEXT: blr
+# LDTOLE-LABEL: <LDTwoVal>:
+# LDTOLE: paddi 3, 13, 4096, 0
+# LDTOLE-NEXT: nop
+# LDTOLE-NEXT: paddi 3, 3, -32768, 0
+# LDTOLE-NEXT: lwz 2, 0(3)
+# LDTOLE-NEXT: paddi 3, 3, -32764, 0
+# LDTOLE-NEXT: lwz 3, 0(3)
+# LDTOLE-NEXT: blr
+.section .text_twoval, "ax", %progbits
+LDTwoVal:
+ paddi 3, 0, x@got@tlsld@pcrel, 1
+ bl __tls_get_addr@notoc(x@tlsld)
+ paddi 3, 3, x@dtprel, 0
+ lwz 2, 0(3)
+ paddi 3, 3, y@dtprel, 0
+ lwz 3, 0(3)
+ blr
+
+# LD-LABEL: <LDIncrementVal>:
+# LD: paddi 3, 0, 360, 1
+# LD-NEXT: bl 0x1001020
+# LD-NEXT: paddi 9, 3, -32764, 0
+# LD-NEXT: lwz 4, 0(9)
+# LD-NEXT: stw 5, 0(9)
+# LD-NEXT: blr
+# LDTOLE-LABEL: <LDIncrementVal>:
+# LDTOLE: paddi 3, 13, 4096, 0
+# LDTOLE-NEXT: nop
+# LDTOLE-NEXT: paddi 9, 3, -32764, 0
+# LDTOLE-NEXT: lwz 4, 0(9)
+# LDTOLE-NEXT: stw 5, 0(9)
+# LDTOLE-NEXT: blr
+.section .text_incrval, "ax", %progbits
+LDIncrementVal:
+ paddi 3, 0, y@got@tlsld@pcrel, 1
+ bl __tls_get_addr@notoc(y@tlsld)
+ paddi 9, 3, y@dtprel, 0
+ lwz 4, 0(9)
+ stw 5, 0(9)
+ blr
+
+.section .tbss,"awT",@nobits
+x:
+ .long 0
+y:
+ .long 0