[PPC64] Add TLS global dynamic to local exec relaxation

This patch adds the target call back relaxTlsGdToLe to support TLS relaxation
from global dynamic to local exec model.

The relaxation performs the following transformation:
addis r3, r2, x@got@tlsgd@ha --> nop
addi r3, r3, x@got@tlsgd@l   --> addis r3, r13, x@tprel@ha
bl __tls_get_addr(x@tlsgd)   --> nop
nop                          --> addi r3, r3, x@tprel@l

Differential Revision: https://reviews.llvm.org/D48082

llvm-svn: 335730
This commit is contained in:
Zaara Syeda 2018-06-27 13:27:29 +00:00
parent f681413e67
commit 1cdd816c12
2 changed files with 120 additions and 0 deletions

View File

@ -54,6 +54,7 @@ public:
RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,
RelExpr Expr) const override;
void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
};
} // namespace
@ -159,6 +160,42 @@ uint32_t PPC64::calcEFlags() const {
return 2;
}
void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
// Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement.
// The general dynamic code sequence for a global `x` will look like:
// Instruction Relocation Symbol
// addis r3, r2, x@got@tlsgd@ha R_PPC64_GOT_TLSGD16_HA x
// addi r3, r3, x@got@tlsgd@l R_PPC64_GOT_TLSGD16_LO x
// bl __tls_get_addr(x@tlsgd) R_PPC64_TLSGD x
// R_PPC64_REL24 __tls_get_addr
// nop None None
// Relaxing to local exec entails converting:
// addis r3, r2, x@got@tlsgd@ha into nop
// addi r3, r3, x@got@tlsgd@l into addis r3, r13, x@tprel@ha
// bl __tls_get_addr(x@tlsgd) into nop
// nop into addi r3, r3, x@tprel@l
uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U;
switch (Type) {
case R_PPC64_GOT_TLSGD16_HA:
write32(Loc - EndianOffset, 0x60000000); // nop
break;
case R_PPC64_GOT_TLSGD16_LO:
write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13
relocateOne(Loc, R_PPC64_TPREL16_HA, Val);
break;
case R_PPC64_TLSGD:
write32(Loc, 0x60000000); // nop
write32(Loc + 4, 0x38630000); // addi r3, r3
relocateOne(Loc + 4 + EndianOffset, R_PPC64_TPREL16_LO, Val);
break;
default:
llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
}
}
RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const {
switch (Type) {

View File

@ -0,0 +1,83 @@
// REQUIRES: ppc
// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: ld.lld %t.o -o %t
// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: ld.lld %t.o -o %t
// RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s
// RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s
.text
.abiversion 2
.globl _start # -- Begin function _start
.p2align 4
.type _start,@function
_start: # @_start
.Lfunc_begin0:
.Lfunc_gep0:
addis 2, 12, .TOC.-.Lfunc_gep0@ha
addi 2, 2, .TOC.-.Lfunc_gep0@l
.Lfunc_lep0:
.localentry _start, .Lfunc_lep0-.Lfunc_gep0
# %bb.0: # %entry
mflr 0
std 31, -8(1)
std 0, 16(1)
stdu 1, -64(1)
mr 31, 1
std 30, 48(31) # 8-byte Folded Spill
li 3, 0
stw 3, 44(31)
addis 3, 2, a@got@tlsgd@ha
addi 3, 3, a@got@tlsgd@l
bl __tls_get_addr(a@tlsgd)
nop
lwz 30, 0(3)
extsw 3, 30
ld 30, 48(31) # 8-byte Folded Reload
addi 1, 1, 64
ld 0, 16(1)
ld 31, -8(1)
mtlr 0
blr
.long 0
.quad 0
.Lfunc_end0:
.size _start, .Lfunc_end0-.Lfunc_begin0
.globl __tls_get_addr
.type __tls_get_addr,@function
__tls_get_addr:
# -- End function
.type a,@object # @a
.section .tdata,"awT",@progbits
.globl a
.p2align 2
a:
.long 55 # 0x37
.size a, 4
// Verify that the input has general-dynamic tls relocation types
// InputRelocs: Relocation section '.rela.text'
// InputRelocs: R_PPC64_GOT_TLSGD16_HA {{0+}} a + 0
// InputRelocs: R_PPC64_GOT_TLSGD16_LO {{0+}} a + 0
// InputRelocs: R_PPC64_TLSGD {{0+}} a + 0
// Verify that the general-dynamic sequence is relaxed to local exec.
// #ha(a@tprel) --> (0 - 0x7000 + 0x8000) >> 16 = 0
// #lo(a@tprel)) --> (0 - 0x7000) & 0xFFFF = -0x7000 = -28672
// Dis: _start:
// Dis: nop
// Dis: addis 3, 13, 0
// Dis: nop
// Dis: addi 3, 3, -28672
// Verify that no general-dynamic relocations exist for the dynamic linker.
// OutputRelocs-NOT: R_PPC64_DTPMOD64
// OutputRelocs-NOT: R_PPC64_DTPREL64