[llvm] [Xtensa] Fix code generation for TLS variables. (PR #202822)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 11:54:03 PDT 2026
https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/202822
>From 32afb2d1dc1bab6010d7af37ab8a1affab98a5c4 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 10 Jun 2026 03:03:04 +0300
Subject: [PATCH 1/2] [Xtensa] Fix code generation for TLS variables.
---
.../Xtensa/AsmParser/XtensaAsmParser.cpp | 6 +--
.../Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp | 4 ++
.../MCTargetDesc/XtensaTargetStreamer.cpp | 5 +-
llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp | 7 ---
llvm/test/CodeGen/Xtensa/tls.ll | 30 +++++++++++
llvm/test/MC/Xtensa/tls.s | 50 +++++++++++++++++++
6 files changed, 89 insertions(+), 13 deletions(-)
create mode 100644 llvm/test/CodeGen/Xtensa/tls.ll
create mode 100644 llvm/test/MC/Xtensa/tls.s
diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index dc33295c16f28..16eb24f59260b 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -676,12 +676,8 @@ ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {
return ParseStatus::Failure;
break;
case AsmToken::Identifier: {
- StringRef Identifier;
- if (getParser().parseIdentifier(Identifier))
+ if (getParser().parseExpression(Res))
return ParseStatus::Failure;
-
- MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
- Res = MCSymbolRefExpr::create(Sym, getContext());
break;
}
case AsmToken::Percent:
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp
index ec4477ad80fe2..de15486337343 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCAsmInfo.cpp
@@ -18,6 +18,8 @@
using namespace llvm;
+const MCAsmInfo::AtSpecifier atSpecifiers[] = {{Xtensa::S_TPOFF, "TPOFF"}};
+
XtensaMCAsmInfo::XtensaMCAsmInfo(const Triple &TT,
const MCTargetOptions &Options)
: MCAsmInfoELF(Options) {
@@ -32,6 +34,8 @@ XtensaMCAsmInfo::XtensaMCAsmInfo(const Triple &TT,
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
AlignmentIsInBytes = false;
+
+ initializeAtSpecifiers(atSpecifiers);
}
void XtensaMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
index 0ea70cff4d404..ba266057d3a5e 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "XtensaTargetStreamer.h"
+#include "MCTargetDesc/XtensaMCAsmInfo.h"
#include "XtensaInstPrinter.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAssembler.h"
@@ -61,7 +62,9 @@ void XtensaTargetAsmStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
LiteralStr << CE->getValue() << "\n";
} else if (auto SRE = dyn_cast<MCSymbolRefExpr>(Value)) {
const MCSymbol &Sym = SRE->getSymbol();
- LiteralStr << Sym.getName() << "\n";
+ Xtensa::Specifier Spec = (Xtensa::Specifier)SRE->getSpecifier();
+ StringRef Modifier = (Spec == Xtensa::S_TPOFF) ? "@TPOFF" : "";
+ LiteralStr << Sym.getName() << Modifier << "\n";
} else {
llvm_unreachable("unexpected constant pool entry type");
}
diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
index c6e432fb9918c..710084289a3e0 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
@@ -97,13 +97,6 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
auto Spec = getModifierSpecifier(XtensaCPV->getModifier());
- if (XtensaCPV->getModifier() != XtensaCP::no_modifier) {
- std::string SymName(MCSym->getName());
- StringRef Modifier = XtensaCPV->getModifierText();
- SymName += Modifier;
- MCSym = OutContext.getOrCreateSymbol(SymName);
- }
-
const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, Spec, OutContext);
TS->emitLiteral(LblSym, Expr, false);
}
diff --git a/llvm/test/CodeGen/Xtensa/tls.ll b/llvm/test/CodeGen/Xtensa/tls.ll
new file mode 100644
index 0000000000000..0d59b8b2f7df0
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/tls.ll
@@ -0,0 +1,30 @@
+; RUN: llc -mtriple=xtensa -function-sections --mcpu=esp32 --filetype=obj < %s \
+; RUN: | llvm-objdump -r -s --triple=xtensa --mcpu=esp32 - | FileCheck -check-prefix=XTENSA-CHECK-OBJ %s
+; RUN: llc -mtriple=xtensa -function-sections --mcpu=esp32 --filetype=asm < %s | FileCheck -check-prefix=XTENSA-CHECK-ASM %s
+
+; XTENSA-CHECK-OBJ-LABEL: RELOCATION RECORDS FOR [.literal.get_tls]:
+; XTENSA-CHECK-OBJ: OFFSET TYPE VALUE
+; XTENSA-CHECK-OBJ-NEXT: 00000000 R_XTENSA_TLS_TPOFF tls_var
+
+; XTENSA-CHECK-ASM-LABEL: .literal_position
+; XTENSA-CHECK-ASM: .literal .LCPI0_0, tls_var at TPOFF
+; XTENSA-CHECK-ASM-LABEL: get_tls:
+; XTENSA-CHECK-ASM: .cfi_startproc
+; XTENSA-CHECK-ASM-NEXT: # %bb.0:
+; XTENSA-CHECK-ASM-NEXT: entry a1, 32
+; XTENSA-CHECK-ASM-NEXT: .cfi_def_cfa_offset 32
+; XTENSA-CHECK-ASM-NEXT: l32r a8, .LCPI0_0
+; XTENSA-CHECK-ASM-NEXT: rur a9, threadptr
+; XTENSA-CHECK-ASM-NEXT: add a8, a9, a8
+; XTENSA-CHECK-ASM-NEXT: l32i a2, a8, 0
+; XTENSA-CHECK-ASM-NEXT: retw.n
+
+
+ at tls_var = dso_local thread_local local_unnamed_addr global i32 42, align 4
+
+define dso_local i32 @get_tls() {
+entry:
+ %v = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tls_var)
+ %res = load i32, ptr %v, align 4
+ ret i32 %res
+}
diff --git a/llvm/test/MC/Xtensa/tls.s b/llvm/test/MC/Xtensa/tls.s
new file mode 100644
index 0000000000000..9ca2599c15491
--- /dev/null
+++ b/llvm/test/MC/Xtensa/tls.s
@@ -0,0 +1,50 @@
+# RUN: llvm-mc -triple=xtensa --mcpu=esp32 --filetype=obj < %s \
+# RUN: | llvm-objdump -r -s --triple=xtensa --mcpu=esp32 - | FileCheck -check-prefix=XTENSA-CHECK-OBJ %s
+# RUN: llvm-mc -triple=xtensa --mcpu=esp32 --filetype=asm < %s | FileCheck -check-prefix=XTENSA-CHECK-ASM %s
+
+# XTENSA-CHECK-OBJ-LABEL: RELOCATION RECORDS FOR [.literal]:
+# XTENSA-CHECK-OBJ: OFFSET TYPE VALUE
+# XTENSA-CHECK-OBJ-NEXT: 00000000 R_XTENSA_TLS_TPOFF tls_var
+# XTENSA-CHECK-OBJ-LABEL: RELOCATION RECORDS FOR [.literal.get_tls]:
+# XTENSA-CHECK-OBJ: OFFSET TYPE VALUE
+# XTENSA-CHECK-OBJ-NEXT: 00000000 R_XTENSA_TLS_TPOFF tls_var
+
+# XTENSA-CHECK-ASM-LABEL: .literal_position
+# XTENSA-CHECK-ASM: .literal .LCPI0_0, tls_var at TPOFF
+# XTENSA-CHECK-ASM-LABEL: get_tls:
+# XTENSA-CHECK-ASM-NEXT: entry a1, 32
+# XTENSA-CHECK-ASM-NEXT: or a7, a1, a1
+# XTENSA-CHECK-ASM-NEXT: l32r a8, .LCPI0_0
+# XTENSA-CHECK-ASM-NEXT: rur a9, threadptr
+# XTENSA-CHECK-ASM-NEXT: add a8, a9, a8
+# XTENSA-CHECK-ASM-NEXT: l32i a2, a8, 0
+# XTENSA-CHECK-ASM-NEXT: .literal .Ltmp0, tls_var at TPOFF
+# XTENSA-CHECK-ASM-NEXT: l32r a3, .Ltmp0
+# XTENSA-CHECK-ASM-NEXT: retw.n
+
+ .literal_position
+ .literal .LCPI0_0, tls_var at TPOFF
+ .text
+ .section .text.get_tls,"ax", at progbits
+ .global get_tls # -- Begin function get_tls
+ .p2align 2
+ .type get_tls, at function
+get_tls:
+ entry a1, 32
+ or a7, a1, a1
+ l32r a8, .LCPI0_0
+ rur a9, threadptr
+ add a8, a9, a8
+ l32i a2, a8, 0
+ movi a3, tls_var at TPOFF
+ retw.n
+.Lfunc_end0:
+ .size get_tls, .Lfunc_end0-get_tls
+ # -- End function
+ .type tls_var, at object # @tls_var
+ .section .tdata,"awT", at progbits
+ .global tls_var
+ .p2align 2, 0x0
+tls_var:
+ .long 42 # 0x2a
+ .size tls_var, 4
>From 71329af5b8cae59ee354635ac0bae0fc1a067308 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 10 Jun 2026 21:49:51 +0300
Subject: [PATCH 2/2] [Xtensa] Minor fix in XtensaTargetAsmStreamer.
---
.../Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
index ba266057d3a5e..6283d0f38211e 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaTargetStreamer.cpp
@@ -62,9 +62,12 @@ void XtensaTargetAsmStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
LiteralStr << CE->getValue() << "\n";
} else if (auto SRE = dyn_cast<MCSymbolRefExpr>(Value)) {
const MCSymbol &Sym = SRE->getSymbol();
- Xtensa::Specifier Spec = (Xtensa::Specifier)SRE->getSpecifier();
- StringRef Modifier = (Spec == Xtensa::S_TPOFF) ? "@TPOFF" : "";
- LiteralStr << Sym.getName() << Modifier << "\n";
+ Xtensa::Specifier Spec =
+ static_cast<Xtensa::Specifier>(SRE->getSpecifier());
+ LiteralStr << Sym.getName();
+ if (Spec == Xtensa::S_TPOFF)
+ LiteralStr << "@TPOFF";
+ LiteralStr << '\n';
} else {
llvm_unreachable("unexpected constant pool entry type");
}
More information about the llvm-commits
mailing list