[llvm] 8e20a6d - [AArch64] Support TLS variables in debug info (#146572)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 20:20:48 PDT 2026


Author: Shivam Gupta
Date: 2026-03-31T08:50:43+05:30
New Revision: 8e20a6dc866c54683f801d1ca041c6b3ba302485

URL: https://github.com/llvm/llvm-project/commit/8e20a6dc866c54683f801d1ca041c6b3ba302485
DIFF: https://github.com/llvm/llvm-project/commit/8e20a6dc866c54683f801d1ca041c6b3ba302485.diff

LOG: [AArch64] Support TLS variables in debug info (#146572)

This adds an implementation of getDebugThreadLocalSymbol for AArch64 by
using AArch::S_DTPREL.

Fixes #83466

Added: 
    

Modified: 
    llvm/docs/ReleaseNotes.md
    llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
    llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
    llvm/test/DebugInfo/AArch64/tls-at-location.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index fbf47b9789b09..9462510fc8d9e 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -128,6 +128,11 @@ Changes to the AArch64 Backend
 
 * The `sysp`, `mrrs`, and `msrr` instructions are now accepted without
   requiring the `+d128` feature gating.
+* Added a new internal option `-aarch64-emit-debug-tls-location` to allow the
+  emission of `DW_AT_location` for thread-local variables. This is currently
+  disabled by default to maintain compatibility with Binutils and LLVM older
+  toolchains that do not define the `R_AARCH64_TLS_DTPREL64` static relocation
+  type for TLS offsets.
 
 Changes to the AMDGPU Backend
 -----------------------------

diff  --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
index 886f41975e199..9debe57634ff3 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
@@ -22,15 +22,17 @@
 using namespace llvm;
 using namespace dwarf;
 
+static cl::opt<bool> EmitAArch64DebugTLSLocation(
+    "aarch64-emit-debug-tls-location",
+    cl::desc("Emit the TLS DWARF location with DTPREL relocation for AArch64"),
+    cl::Hidden);
+
 void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
                                              const TargetMachine &TM) {
   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
   PLTPCRelativeSpecifier = AArch64::S_PLT;
   SupportIndirectSymViaGOTPCRel = true;
-
-  // AARCH64 ELF ABI does not define static relocation type for TLS offset
-  // within a module.  Do not generate AT_location for TLS variables.
-  SupportDebugThreadLocalLocation = false;
+  SupportDebugThreadLocalLocation = EmitAArch64DebugTLSLocation;
 
   // Make sure the implicitly created empty .text section has the
   // SHF_AARCH64_PURECODE flag set if the "+execute-only" target feature is
@@ -187,3 +189,8 @@ MCSection *AArch64_ELFTargetObjectFile::SelectSectionForGlobal(
 
   return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
 }
+
+const MCExpr *AArch64_ELFTargetObjectFile::getDebugThreadLocalSymbol(
+    const MCSymbol *Sym) const {
+  return MCSpecifierExpr::create(Sym, AArch64::S_DTPREL, getContext());
+}

diff  --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
index 6b3381452c70b..78c0c22da8d1b 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
@@ -40,6 +40,9 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
 
   MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
                                     const TargetMachine &TM) const override;
+
+  /// Describe a TLS variable address within debug info.
+  const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override;
 };
 
 /// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.

diff  --git a/llvm/test/DebugInfo/AArch64/tls-at-location.ll b/llvm/test/DebugInfo/AArch64/tls-at-location.ll
index 20a0afb789771..97c69996945b1 100644
--- a/llvm/test/DebugInfo/AArch64/tls-at-location.ll
+++ b/llvm/test/DebugInfo/AArch64/tls-at-location.ll
@@ -1,8 +1,33 @@
-; RUN: llc -filetype=obj -mtriple=aarch64--linux-gnu -o - %s | llvm-dwarfdump -v - | FileCheck %s
-;
-; CHECK: .debug_info contents:
-; CHECK: DW_TAG_variable
-; CHECK-NOT: DW_AT_location
+; RUN: llc -O0 -mtriple=aarch64 --aarch64-emit-debug-tls-location -filetype=obj < %s \
+; RUN:     | llvm-dwarfdump - | FileCheck %s --check-prefix=TLS
+
+; RUN: llc -O0 -mtriple=aarch64 --aarch64-emit-debug-tls-location=false -filetype=obj < %s \
+; RUN:     | llvm-dwarfdump - | FileCheck %s --check-prefix=NO-TLS
+
+; RUN: llc -O0 -mtriple=aarch64 -filetype=obj < %s \
+; RUN:     | llvm-dwarfdump - | FileCheck %s --check-prefix=NO-TLS
+
+; RUN: llc -O0 -mtriple=aarch64 --aarch64-emit-debug-tls-location -filetype=obj < %s -o %t
+; RUN: llvm-objdump -r %t | FileCheck %s --check-prefix=OBJDUMP
+; RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=RELOC
+
+; TLS: .debug_info contents:
+; TLS:  DW_TAG_variable
+; TLS-NEXT:   DW_AT_name      ("var")
+; TLS-NEXT:   DW_AT_type      (0x{{.*}} "int")
+; TLS-NEXT:   DW_AT_external  (true)
+; TLS-NEXT:   DW_AT_decl_file ("{{.*}}tls-at-location.c")
+; TLS-NEXT:   DW_AT_decl_line (1)
+; TLS-NEXT:   DW_AT_location  (DW_OP_const8u 0x0, DW_OP_GNU_push_tls_address)
+
+; NO-TLS: .debug_info contents:
+; NO-TLS: DW_TAG_variable
+; NO-TLS-NEXT:  DW_AT_name	("var")
+; NO-TLS-NOT:   DW_AT_location
+
+; OBJDUMP: R_AARCH64_TLS_DTPREL64   var
+
+; RELOC: R_AARCH64_TLS_DTPREL64 {{0+}} var + 0
 
 @var = thread_local global i32 0, align 4, !dbg !0
 


        


More information about the llvm-commits mailing list