[llvm] [SPARC] Parse relocation specifiers in expressions (PR #208933)
Kirill A. Korinsky via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 31 10:08:13 PDT 2026
https://github.com/catap updated https://github.com/llvm/llvm-project/pull/208933
>From 2e81c8da841963e07ebaeb1b8e232c8c4f1fb64c Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill at korins.ky>
Date: Fri, 31 Jul 2026 12:29:58 +0200
Subject: [PATCH] [SPARC] Parse data relocation specifiers
SPARC code generation emits relocation specifiers such as
%r_disp32(...) in data directives, but the integrated assembler only
recognizes them while parsing instruction operands. Consequently, LLVM
cannot reassemble its own PIC exception table output.
Parse leading specifiers through the target data expression hook.
Preserve diagnostics for malformed specifiers, and test assembly
printing and R_SPARC_DISP32 relocation emission on sparc and sparcv9.
---
.../Target/Sparc/AsmParser/SparcAsmParser.cpp | 16 +++++++++++++++-
.../MC/Sparc/Relocations/relocation-specifier.s | 9 +++++++++
llvm/test/MC/Sparc/sparc-asm-errors.s | 5 +++++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index c6be2489e66ac..861b00b9a705c 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -82,6 +82,7 @@ class SparcAsmParser : public MCTargetAsmParser {
bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
ParseStatus parseDirective(AsmToken DirectiveID) override;
+ bool parseDataExpr(const MCExpr *&Res) override;
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
@@ -1756,8 +1757,10 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
}
Parser.Lex(); // Eat the identifier.
- if (Parser.getTok().getKind() != AsmToken::LParen)
+ if (Parser.getTok().getKind() != AsmToken::LParen) {
+ Error(getLoc(), "expected '('");
return false;
+ }
Parser.Lex(); // Eat the LParen token.
const MCExpr *subExpr;
@@ -1768,6 +1771,17 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
return true;
}
+bool SparcAsmParser::parseDataExpr(const MCExpr *&Res) {
+ SMLoc EndLoc;
+ if (!parseOptionalToken(AsmToken::Percent))
+ return Parser.parseExpression(Res);
+ if (matchSparcAsmModifiers(Res, EndLoc))
+ return false;
+ if (!Parser.hasPendingError())
+ return Error(getLoc(), "invalid relocation specifier");
+ return true;
+}
+
bool SparcAsmParser::isPossibleExpression(const AsmToken &Token) {
switch (Token.getKind()) {
case AsmToken::LParen:
diff --git a/llvm/test/MC/Sparc/Relocations/relocation-specifier.s b/llvm/test/MC/Sparc/Relocations/relocation-specifier.s
index 8a996c99e55ac..d929dadc795a0 100644
--- a/llvm/test/MC/Sparc/Relocations/relocation-specifier.s
+++ b/llvm/test/MC/Sparc/Relocations/relocation-specifier.s
@@ -3,9 +3,11 @@
# RUN: llvm-mc %s -triple=sparc -filetype=obj -o %t
# RUN: llvm-objdump -dr %t | FileCheck %s --check-prefix=OBJDUMP
+# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC
# RUN: llvm-readelf -s - < %t | FileCheck %s --check-prefix=READELF --implicit-check-not=TLS
# RUN: llvm-mc %s --defsym V9=1 -triple=sparcv9 -filetype=obj -o %t
# RUN: llvm-objdump -dr %t | FileCheck %s --check-prefixes=OBJDUMP,OBJDUMP-V9
+# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC
# RUN: llvm-readelf -s - < %t | FileCheck %s --check-prefixes=READELF,READELF-V9 --implicit-check-not=TLS
# READELF: TLS LOCAL DEFAULT [[#]] s_tle_hix22
@@ -217,3 +219,10 @@ s_tle_hix22:
s_tldo_hix22:
.word 0
.size Local, 4
+
+# ASM: .word %r_disp32(sym)
+# RELOC: Section ({{.*}}) .rela.data {
+# RELOC-NEXT: 0x0 R_SPARC_DISP32 sym 0x0
+# RELOC-NEXT: }
+ .data
+ .word %r_disp32(sym)
diff --git a/llvm/test/MC/Sparc/sparc-asm-errors.s b/llvm/test/MC/Sparc/sparc-asm-errors.s
index 655fd15e3962f..2e7a2fa6ce3d4 100644
--- a/llvm/test/MC/Sparc/sparc-asm-errors.s
+++ b/llvm/test/MC/Sparc/sparc-asm-errors.s
@@ -20,3 +20,8 @@
sll %g1, 32, %g2
! V9: immediate shift value out of range
slx %g1, 64, %g2
+
+ ! CHECK: :[[#@LINE+1]]:25: error: expected '('
+ .word %r_disp32 foo
+ ! CHECK: :[[#@LINE+1]]:16: error: invalid relocation specifier
+ .word %tgd_add(foo)
More information about the llvm-commits
mailing list