From 5bee00163674957f87b090c777abcc6b0c17f95f Mon Sep 17 00:00:00 2001 From: deepakshirkem Date: Sat, 23 May 2026 18:13:34 +0530 Subject: [PATCH 1/5] [AArch64] Fix IE->LE TLS relaxation for global symbols Extend IE->LE relaxation in tls_gottprel_page and tls_gottprel_lo to cover global TLS symbols in static executables. Previously only local symbols (without ReserveGOT) were relaxed. Fixes part of #1004 Signed-off-by: deepakshirkem --- lib/Target/AArch64/AArch64Relocator.cpp | 36 +++++++++++-------------- test/AArch64/standalone/TLS_IE/IE.test | 4 +-- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/lib/Target/AArch64/AArch64Relocator.cpp b/lib/Target/AArch64/AArch64Relocator.cpp index cc9d26147..8356c310b 100644 --- a/lib/Target/AArch64/AArch64Relocator.cpp +++ b/lib/Target/AArch64/AArch64Relocator.cpp @@ -4,7 +4,6 @@ // SPDX-License-Identifier: BSD-3-Clause //===----------------------------------------------------------------------===// - #include "AArch64Relocator.h" #include "AArch64InsnHelpers.h" #include "AArch64PLT.h" @@ -52,8 +51,7 @@ static uint64_t getSigningSchema(const Relocation &pReloc) { /// helper_DynRel - Get an relocation entry in .rela.dyn Relocation *helper_DynRel_init(ELFObjectFile *Obj, Relocation *R, ResolveInfo *pSym, Fragment *F, uint32_t pOffset, - Relocator::Type pType, - AArch64LDBackend &B) { + Relocator::Type pType, AArch64LDBackend &B) { Relocation *rela_entry = nullptr; if (pType == R_AARCH64_TLSDESC) @@ -190,9 +188,8 @@ bool AArch64Relocator::relocNeedsDynRel(Relocation &pReloc) const { pReloc.type() == llvm::ELF::R_AARCH64_ABS32 || pReloc.type() == llvm::ELF::R_AARCH64_ABS16 || pReloc.type() == llvm::ELF::R_AARCH64_AUTH_ABS64; - return getTarget().symbolNeedsDynRel( - *rsym, (rsym->reserved() & ReservePLT), - isAbsReloc); + return getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), + isAbsReloc); } Relocator::Result AArch64Relocator::applyRelocation(Relocation &pRelocation) { @@ -252,12 +249,10 @@ void AArch64Relocator::scanLocalReloc(InputFile &pInput, Relocation &pReloc, rsym->setReserved(rsym->reserved() | ReserveRel); getTarget().checkAndSetHasTextRel(pSection); // set up the dyn rel directly - Relocation::Type relType = - isAuthAbs ? llvm::ELF::R_AARCH64_AUTH_RELATIVE - : llvm::ELF::R_AARCH64_RELATIVE; + Relocation::Type relType = isAuthAbs ? llvm::ELF::R_AARCH64_AUTH_RELATIVE + : llvm::ELF::R_AARCH64_RELATIVE; helper_DynRel_init(Obj, &pReloc, rsym, pReloc.targetRef()->frag(), - pReloc.targetRef()->offset(), relType, - m_Target); + pReloc.targetRef()->offset(), relType, m_Target); } } return; @@ -382,8 +377,8 @@ void AArch64Relocator::scanGlobalReloc(InputFile &pInput, Relocation &pReloc, // for signed pointers" if (isAuthAbs) { config().raise(Diag::non_pic_relocation) - << getName(pReloc.type()) << pReloc.symInfo()->name() - << pReloc.getSourcePath(config().options()); + << getName(pReloc.type()) << pReloc.symInfo()->name() + << pReloc.getSourcePath(config().options()); m_Target.getModule().setFailure(true); return; } @@ -409,10 +404,8 @@ void AArch64Relocator::scanGlobalReloc(InputFile &pInput, Relocation &pReloc, relType = isAuthAbs ? llvm::ELF::R_AARCH64_AUTH_RELATIVE : llvm::ELF::R_AARCH64_RELATIVE; } - helper_DynRel_init( - Obj, &pReloc, rsym, pReloc.targetRef()->frag(), - pReloc.targetRef()->offset(), - relType, m_Target); + helper_DynRel_init(Obj, &pReloc, rsym, pReloc.targetRef()->frag(), + pReloc.targetRef()->offset(), relType, m_Target); } } } @@ -1023,7 +1016,8 @@ Relocator::Result ld64_got_lo12(Relocation &pReloc, AArch64Relocator &pParent) { } // R_AARCH64_LD64_GOTPAGE_LO15: G(GDAT(S)) - Page(GOT) -Relocator::Result ld64_gotpage_lo15(Relocation &pReloc, AArch64Relocator &pParent) { +Relocator::Result ld64_gotpage_lo15(Relocation &pReloc, + AArch64Relocator &pParent) { if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT)) { return Relocator::BadReloc; } @@ -1148,7 +1142,8 @@ Relocator::Result tls_gottprel_page(Relocation &pReloc, DiagnosticEngine *DiagEngine = pParent.config().getDiagEngine(); Relocator::DWord A = pReloc.addend(); - if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT)) { + if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT) || + pParent.config().isCodeStatic()) { Relocator::DWord X = pParent.getSymValue(&pReloc) + AArch64LDBackend::getStaticTCBSize(); // Convert to movz @@ -1173,7 +1168,8 @@ Relocator::Result tls_gottprel_lo(Relocation &pReloc, AArch64Relocator &pParent) { Relocator::DWord A = pReloc.addend(); - if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT)) { + if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT) || + pParent.config().isCodeStatic()) { Relocator::DWord X = pParent.getSymValue(&pReloc) + AArch64LDBackend::getStaticTCBSize(); // Convert to movk diff --git a/test/AArch64/standalone/TLS_IE/IE.test b/test/AArch64/standalone/TLS_IE/IE.test index e5b0050ef..600ccedf9 100644 --- a/test/AArch64/standalone/TLS_IE/IE.test +++ b/test/AArch64/standalone/TLS_IE/IE.test @@ -8,8 +8,8 @@ RUN: %clang %clangopts -target aarch64 %p/Inputs/f.c -c -o %t3.o RUN: %link %linkopts -static -march aarch64 %t2.o %t3.o -z max-page-size=0x1000 -o %t2.out CHECK: _test_tls_IE -CHECK: b0000000 adrp -CHECK: f9400000 ldr +CHECK: d2a00000 movz +CHECK: f2800200 movk CHECK: _test_tls_IE_local CHECK: d2a00000 movz CHECK: f2800280 movk From 9415c4947b26eba747ccedde589607a1b264b940 Mon Sep 17 00:00:00 2001 From: deepakshirkem Date: Sat, 23 May 2026 20:17:23 +0530 Subject: [PATCH 2/5] [AArch64] Fix register preservation in TLSDESC->LE relaxation Preserve destination register (Rd) when relaxing TLSDESC_LD64_LO12 to movk in static executables. Previously x0 was hardcoded. Also extend relaxation to cover global symbols in static executables by adding isCodeStatic() check, matching the IE->LE fix. Fixes part of #1004 Signed-off-by: deepakshirkem --- lib/Target/AArch64/AArch64Relocator.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/Target/AArch64/AArch64Relocator.cpp b/lib/Target/AArch64/AArch64Relocator.cpp index 8356c310b..c43ac690e 100644 --- a/lib/Target/AArch64/AArch64Relocator.cpp +++ b/lib/Target/AArch64/AArch64Relocator.cpp @@ -1238,11 +1238,12 @@ Relocator::Result tls_tlsdesc_lo(Relocation &pReloc, AArch64Relocator &pParent) { Relocator::DWord A = pReloc.addend(); - if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT)) { + if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT) || + pParent.config().isCodeStatic()) { Relocator::DWord X = pParent.getSymValue(&pReloc) + AArch64LDBackend::getStaticTCBSize(); - // Convert to movk, save to x0 - uint32_t movk = 0xF2800000; + // Convert to movk, preserve original register + uint32_t movk = 0xF2800000 | (pReloc.target() & 0x0000001F); pReloc.target() = helper_reencode_movzk_imm(movk, X); return Relocator::OK; } @@ -1253,10 +1254,6 @@ Relocator::Result tls_tlsdesc_lo(Relocation &pReloc, Relocator::DWord GX = helper_get_page_offset(GOT_S + A); pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), GX >> 3); - // Convert Rt to X0 if static - if (pParent.config().isCodeStatic()) - pReloc.target() = pReloc.target() & ~0x1F; - return Relocator::OK; } From 95445c345086f5ed6cea5532a6b738500cc070f1 Mon Sep 17 00:00:00 2001 From: deepakshirkem Date: Sat, 23 May 2026 20:40:14 +0530 Subject: [PATCH 3/5] [AArch64] Fix TLSDESC->LE relaxation for global symbols in static executables Extend TLSDESC->LE relaxation in tls_tlsdesc_page to cover global TLS symbols in static executables by adding isCodeStatic() check. Also fix tls_tlsdesc_lo to always use x0 for the relaxed movk instruction, matching LLD behavior and ensuring the TLS offset is in the correct register after relaxation. Add test for TLSDESC->LE relaxation covering both global and local TLS symbols. Fixes part of #1004 Signed-off-by: deepakshirkem --- lib/Target/AArch64/AArch64Relocator.cpp | 5 +++-- test/AArch64/standalone/TLS_DESC/TLS_DESC.test | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 test/AArch64/standalone/TLS_DESC/TLS_DESC.test diff --git a/lib/Target/AArch64/AArch64Relocator.cpp b/lib/Target/AArch64/AArch64Relocator.cpp index c43ac690e..56cc7bd2c 100644 --- a/lib/Target/AArch64/AArch64Relocator.cpp +++ b/lib/Target/AArch64/AArch64Relocator.cpp @@ -1212,7 +1212,8 @@ Relocator::Result tls_tlsdesc_page(Relocation &pReloc, AArch64Relocator &pParent) { Relocator::DWord A = pReloc.addend(); - if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT)) { + if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT) || + pParent.config().isCodeStatic()) { Relocator::DWord X = pParent.getSymValue(&pReloc) + AArch64LDBackend::getStaticTCBSize(); // Convert to movz @@ -1243,7 +1244,7 @@ Relocator::Result tls_tlsdesc_lo(Relocation &pReloc, Relocator::DWord X = pParent.getSymValue(&pReloc) + AArch64LDBackend::getStaticTCBSize(); // Convert to movk, preserve original register - uint32_t movk = 0xF2800000 | (pReloc.target() & 0x0000001F); + uint32_t movk = 0xF2800000; pReloc.target() = helper_reencode_movzk_imm(movk, X); return Relocator::OK; } diff --git a/test/AArch64/standalone/TLS_DESC/TLS_DESC.test b/test/AArch64/standalone/TLS_DESC/TLS_DESC.test new file mode 100644 index 000000000..f5096958b --- /dev/null +++ b/test/AArch64/standalone/TLS_DESC/TLS_DESC.test @@ -0,0 +1,14 @@ +RUN: %clangas %clangasopts -filetype obj -target-cpu generic -target-feature +neon -mrelax-all %p/Inputs/t.s -o %t.o +RUN: %link %linkopts -march aarch64 -static -z max-page-size=0x1000 %t.o -o %t.out +RUN: llvm-objdump -d %t.out | %filecheck %s + +CHECK: _test_tls_desc +CHECK: d2a00000 movz +CHECK: f2800200 movk +CHECK: d503201f nop +CHECK: d503201f nop +CHECK: _test_tls_desc_local +CHECK: d2a00000 movz +CHECK: f2800280 movk +CHECK: d503201f nop +CHECK: d503201f nop From 916f3df11c947cc570ad46f693577ebdc751c9ab Mon Sep 17 00:00:00 2001 From: deepakshirkem Date: Sun, 24 May 2026 01:27:37 +0530 Subject: [PATCH 4/5] [AArch64] Implement TLSDESC->IE relaxation for PIE executables For PIE executables, relax TLSDESC sequences to Initial Exec (IE) instead of keeping the expensive TLSDESC runtime resolver call. Changes: - scanLocalReloc/scanGlobalReloc: detect isPIE() and create IE GOT entry with R_AARCH64_TLS_TPREL64 dynamic relocation instead of TLSDESC GOT with R_AARCH64_TLSDESC - tls_tlsdesc_lo: rewrite ldr to IE GOT load into x0 for PIE - tls_tlsdesc_add: emit nop for PIE (matching static behavior) - tls_call: emit nop for PIE (matching static behavior) - Update DESC.test placeholder with correct CHECK lines - Add TLS_DESC_PIE.test to verify TLSDESC->IE relaxation Fixes part of #1004 Signed-off-by: deepakshirkem --- lib/Target/AArch64/AArch64Relocator.cpp | 33 +++++++++++++++---- test/AArch64/standalone/TLS_DESC/DESC.test | 18 ++++++---- .../standalone/TLS_DESC/TLS_DESC_PIE.test | 14 ++++++++ 3 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 test/AArch64/standalone/TLS_DESC/TLS_DESC_PIE.test diff --git a/lib/Target/AArch64/AArch64Relocator.cpp b/lib/Target/AArch64/AArch64Relocator.cpp index 56cc7bd2c..a8149e0ca 100644 --- a/lib/Target/AArch64/AArch64Relocator.cpp +++ b/lib/Target/AArch64/AArch64Relocator.cpp @@ -325,6 +325,14 @@ void AArch64Relocator::scanLocalReloc(InputFile &pInput, Relocation &pReloc, G->setValueType(GOT::TLSStaticSymbolValue); return; } + if (config().options().isPIE()) { + // PIE executable: relax TLSDESC to IE + AArch64GOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym); + helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0, + llvm::ELF::R_AARCH64_TLS_TPREL64, m_Target); + rsym->setReserved(rsym->reserved() | ReserveGOT); + return; + } AArch64GOT *G = m_Target.createGOT(GOT::TLS_DESC, Obj, rsym); helper_DynRel_init(Obj, &pReloc, rsym, G->getFirst(), 0x0, llvm::ELF::R_AARCH64_TLSDESC, m_Target); @@ -555,6 +563,14 @@ void AArch64Relocator::scanGlobalReloc(InputFile &pInput, Relocation &pReloc, G->setValueType(GOT::TLSStaticSymbolValue); return; } + if (config().options().isPIE()) { + // PIE executable: relax TLSDESC to IE + AArch64GOT *G = m_Target.createGOT(GOT::TLS_IE, Obj, rsym); + helper_DynRel_init(Obj, &pReloc, rsym, G, 0x0, + llvm::ELF::R_AARCH64_TLS_TPREL64, m_Target); + rsym->setReserved(rsym->reserved() | ReserveGOT); + return; + } AArch64GOT *G = m_Target.createGOT(GOT::TLS_DESC, Obj, rsym); helper_DynRel_init(Obj, &pReloc, rsym, G->getFirst(), 0x0, llvm::ELF::R_AARCH64_TLSDESC, m_Target); @@ -1238,23 +1254,28 @@ Relocator::Result tls_tlsdesc_page(Relocation &pReloc, Relocator::Result tls_tlsdesc_lo(Relocation &pReloc, AArch64Relocator &pParent) { Relocator::DWord A = pReloc.addend(); - if (!(pReloc.symInfo()->reserved() & Relocator::ReserveGOT) || pParent.config().isCodeStatic()) { Relocator::DWord X = pParent.getSymValue(&pReloc) + AArch64LDBackend::getStaticTCBSize(); - // Convert to movk, preserve original register uint32_t movk = 0xF2800000; pReloc.target() = helper_reencode_movzk_imm(movk, X); return Relocator::OK; } - + if (pParent.config().options().isPIE()) { + uint32_t insn = 0xF9400000; // ldr x0, [x0, #0] + Relocator::Address GOT_S = pParent.getTarget() + .findEntryInGOT(pReloc.symInfo()) + ->getAddr(pParent.config().getDiagEngine()); + Relocator::DWord GX = helper_get_page_offset(GOT_S + A); + pReloc.target() = helper_reencode_ldst_pos_imm(insn, GX >> 3); + return Relocator::OK; + } Relocator::Address GOT_S = pParent.getTarget() .findEntryInGOT(pReloc.symInfo()) ->getAddr(pParent.config().getDiagEngine()); Relocator::DWord GX = helper_get_page_offset(GOT_S + A); pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), GX >> 3); - return Relocator::OK; } @@ -1262,7 +1283,7 @@ Relocator::Result tls_tlsdesc_lo(Relocation &pReloc, Relocator::Result tls_tlsdesc_add(Relocation &pReloc, AArch64Relocator &pParent) { Relocator::DWord A = pReloc.addend(); - if (pParent.config().isCodeStatic()) { + if (pParent.config().isCodeStatic() || pParent.config().options().isPIE()) { // Convert to nop pReloc.target() = 0xD503201F; return Relocator::OK; @@ -1279,7 +1300,7 @@ Relocator::Result tls_tlsdesc_add(Relocation &pReloc, // R_AARCH64_TLSDESC_CALL Relocator::Result tls_call(Relocation &pReloc, AArch64Relocator &pParent) { - if (pParent.config().isCodeStatic()) { + if (pParent.config().isCodeStatic() || pParent.config().options().isPIE()) { // Convert to nop pReloc.target() = 0xD503201F; return Relocator::OK; diff --git a/test/AArch64/standalone/TLS_DESC/DESC.test b/test/AArch64/standalone/TLS_DESC/DESC.test index 6adac0826..e02a8ee71 100644 --- a/test/AArch64/standalone/TLS_DESC/DESC.test +++ b/test/AArch64/standalone/TLS_DESC/DESC.test @@ -1,10 +1,14 @@ RUN: %clangas %clangasopts -filetype obj -target-cpu generic -target-feature +neon -mrelax-all %p/Inputs/t.s -o %t.o -RUN: %link %linkopts -march aarch64 -static %t.o -z max-page-size=0x1000 -o %t.out +RUN: %link %linkopts -march aarch64 -static -z max-page-size=0x1000 %t.o -o %t.out RUN: llvm-objdump -d %t.out | %filecheck %s -#CHECK: {{.*}} <_test_tls_desc>: -#CHECK: {{.*}} adrp x0, 0x1000 -#CHECK: {{.*}} ldr x0, [x0] -#CHECK: {{.*}} <_test_tls_desc_local>: -#CHECK: {{.*}} adrp x0, 0x1000 -#CHECK: {{.*}} ldr x0, [x0, #0x8] +CHECK: _test_tls_desc +CHECK: d2a00000 movz +CHECK: f2800200 movk +CHECK: d503201f nop +CHECK: d503201f nop +CHECK: _test_tls_desc_local +CHECK: d2a00000 movz +CHECK: f2800280 movk +CHECK: d503201f nop +CHECK: d503201f nop \ No newline at end of file diff --git a/test/AArch64/standalone/TLS_DESC/TLS_DESC_PIE.test b/test/AArch64/standalone/TLS_DESC/TLS_DESC_PIE.test new file mode 100644 index 000000000..1fa4ae261 --- /dev/null +++ b/test/AArch64/standalone/TLS_DESC/TLS_DESC_PIE.test @@ -0,0 +1,14 @@ +RUN: %clangas %clangasopts -filetype obj -target-cpu generic -target-feature +neon -mrelax-all %p/Inputs/t.s -o %t.o +RUN: %link %linkopts -march aarch64 -pie -z max-page-size=0x1000 %t.o -o %t.out +RUN: llvm-objdump -d %t.out | %filecheck %s + +CHECK: _test_tls_desc +CHECK: b0000000 adrp +CHECK: f9408000 ldr +CHECK: d503201f nop +CHECK: d503201f nop +CHECK: _test_tls_desc_local +CHECK: b0000000 adrp +CHECK: f9408400 ldr +CHECK: d503201f nop +CHECK: d503201f nop From 41756161f904881fec4b1ecbf59ff27530d295a5 Mon Sep 17 00:00:00 2001 From: deepakshirkem Date: Sun, 24 May 2026 01:50:15 +0530 Subject: [PATCH 5/5] [AArch64] Add comprehensive TLS relaxation verification tests Add TLS_Relaxation_Verify test using real compiler-generated TLS relocations to verify end-to-end correctness of relaxations: - TLSDESC->LE for static executables (movz+movk+nop+nop) - TLSDESC->IE for PIE executables (adrp+ldr+nop+nop) - R_AARCH64_TLS_TPREL64 dynamic reloc present in PIE Add IE_PIE test to verify IE relocations remain as GOT-indirect adrp+ldr in PIE executables. Fixes part of #1004 Signed-off-by: deepakshirkem --- .../AArch64/standalone/TLS_IE_PIE/IE_PIE.test | 12 +++++++ .../AArch64/standalone/TLS_IE_PIE/Inputs/ie.s | 29 ++++++++++++++++ .../TLS_Relaxation_Verify/Inputs/tls_test.c | 10 ++++++ .../TLS_Relaxation_Verify.test | 34 +++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 test/AArch64/standalone/TLS_IE_PIE/IE_PIE.test create mode 100644 test/AArch64/standalone/TLS_IE_PIE/Inputs/ie.s create mode 100644 test/AArch64/standalone/TLS_Relaxation_Verify/Inputs/tls_test.c create mode 100644 test/AArch64/standalone/TLS_Relaxation_Verify/TLS_Relaxation_Verify.test diff --git a/test/AArch64/standalone/TLS_IE_PIE/IE_PIE.test b/test/AArch64/standalone/TLS_IE_PIE/IE_PIE.test new file mode 100644 index 000000000..4d19529c5 --- /dev/null +++ b/test/AArch64/standalone/TLS_IE_PIE/IE_PIE.test @@ -0,0 +1,12 @@ +# Verify that IE TLS relocations remain as GOT-indirect adrp+ldr +# in PIE executables (IE stays as IE, no relaxation to LE). +RUN: %clangas %clangasopts -filetype obj -target-cpu generic -target-feature +neon -mrelax-all %p/Inputs/ie.s -o %t.o +RUN: %link %linkopts -march aarch64 -pie -z max-page-size=0x1000 %t.o -o %t.out +RUN: llvm-objdump -d %t.out | %filecheck %s + +CHECK: _test_tls_IE +CHECK: b0000000 adrp +CHECK: f9408000 ldr +CHECK: _test_tls_IE_local +CHECK: b0000000 adrp +CHECK: f9408400 ldr diff --git a/test/AArch64/standalone/TLS_IE_PIE/Inputs/ie.s b/test/AArch64/standalone/TLS_IE_PIE/Inputs/ie.s new file mode 100644 index 000000000..e647b896d --- /dev/null +++ b/test/AArch64/standalone/TLS_IE_PIE/Inputs/ie.s @@ -0,0 +1,29 @@ + .global tlsievar + .section .tbss,"awT",%nobits + .align 2 + .type tlsievar, %object + .size tlsievar, 4 +tlsievar: + .zero 4 + + .align 2 + .type l_tlsievar, %object + .size l_tlsievar, 4 +l_tlsievar: + .zero 4 + +.text +_test_tls_IE: + + // R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 tlsievar + adrp x0, :gottprel:tlsievar + // R_AARCH64_TLSIE_GOTTPREL_LO12_NC tlsievar + ldr x0, [x0, :gottprel_lo12:tlsievar] + +_test_tls_IE_local: + + // R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 l_tlsievar + adrp x0, :gottprel:l_tlsievar + // R_AARCH64_TLSIE_GOTTPREL_LO12_NC l_tlsievar + ldr x0, [x0, :gottprel_lo12:l_tlsievar] + diff --git a/test/AArch64/standalone/TLS_Relaxation_Verify/Inputs/tls_test.c b/test/AArch64/standalone/TLS_Relaxation_Verify/Inputs/tls_test.c new file mode 100644 index 000000000..1bd9ed945 --- /dev/null +++ b/test/AArch64/standalone/TLS_Relaxation_Verify/Inputs/tls_test.c @@ -0,0 +1,10 @@ +/* Verify TLS relaxations for AArch64. + * Global-dynamic (TLSDESC) should be relaxed to: + * - Local Exec (movz+movk) for static executables + * - Initial Exec (adrp+ldr) for PIE executables + */ +__thread int tls_global = 42; +static __thread int tls_local = 100; + +int get_global() { return tls_global; } +int get_local() { return tls_local; } diff --git a/test/AArch64/standalone/TLS_Relaxation_Verify/TLS_Relaxation_Verify.test b/test/AArch64/standalone/TLS_Relaxation_Verify/TLS_Relaxation_Verify.test new file mode 100644 index 000000000..2897debca --- /dev/null +++ b/test/AArch64/standalone/TLS_Relaxation_Verify/TLS_Relaxation_Verify.test @@ -0,0 +1,34 @@ +RUN: %clang %clangopts -target aarch64-unknown-none-elf \ +RUN: -ftls-model=global-dynamic -fPIC \ +RUN: -c %p/Inputs/tls_test.c -o %t.o +RUN: %link %linkopts -march aarch64 -static \ +RUN: -z max-page-size=0x1000 %t.o -o %t.static.out +RUN: llvm-objdump -d %t.static.out | %filecheck %s --check-prefix=STATIC +RUN: %link %linkopts -march aarch64 -pie \ +RUN: -z max-page-size=0x1000 %t.o -o %t.pie.out +RUN: llvm-objdump -d %t.pie.out | %filecheck %s --check-prefix=PIE +RUN: %readelf -r %t.pie.out | %filecheck %s --check-prefix=PIE-RELOC + +STATIC: : +STATIC: d2a00000 movz +STATIC: f2800200 movk +STATIC: d503201f nop +STATIC: d503201f nop +STATIC: : +STATIC: d2a00000 movz +STATIC: f2800280 movk +STATIC: d503201f nop +STATIC: d503201f nop + +PIE: : +PIE: b0000000 adrp +PIE: f9408400 ldr +PIE: d503201f nop +PIE: d503201f nop +PIE: : +PIE: b0000000 adrp +PIE: f9408800 ldr +PIE: d503201f nop +PIE: d503201f nop + +PIE-RELOC: R_AARCH64_TLS_TPREL64