[lld] [llvm] AArch64: Replace @plt/%gotpcrel in data directives with %pltpcrel %gotpcrel (PR #155776)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 28 00:52:16 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
Similar to #<!-- -->132569 for RISC-V, replace the unofficial `@<!-- -->plt` and
`@<!-- -->gotpcrel` relocation specifiers, currently only used by clang
-fexperimental-relative-c++-abi-vtables, with %pltpcrel %gotpcrel. The
syntax is not used in humand-written assembly code, and is not supported
by GNU assembler.
---
Full diff: https://github.com/llvm/llvm-project/pull/155776.diff
7 Files Affected:
- (modified) lld/test/ELF/aarch64-reloc-gotpcrel32.s (+5-5)
- (modified) lld/test/ELF/aarch64-reloc-plt32.s (+3-3)
- (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+24)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp (+20-5)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp (+16-1)
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h (+2)
- (modified) llvm/test/MC/AArch64/data-directive-specifier.s (+37-29)
``````````diff
diff --git a/lld/test/ELF/aarch64-reloc-gotpcrel32.s b/lld/test/ELF/aarch64-reloc-gotpcrel32.s
index 4d007776a86a7..35dfe756f4b24 100644
--- a/lld/test/ELF/aarch64-reloc-gotpcrel32.s
+++ b/lld/test/ELF/aarch64-reloc-gotpcrel32.s
@@ -17,11 +17,11 @@ _start: // PC = 0x303a0
// bar at GOTPCREL-4 = 0x20390 (got entry for `bar`) - 0x303a8 (.) - 4 = 0xe4fffeff
// CHECK: Contents of section .data:
// CHECK-NEXT: {{.*}} f0fffeff f0fffeff e4fffeff
- .word bar at GOTPCREL
- .word bar at GOTPCREL+4
- .word bar at GOTPCREL-4
+ .word %gotpcrel(bar)
+ .word %gotpcrel(bar+4)
+ .word %gotpcrel(bar-4)
// WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
// WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
- .word baz at GOTPCREL+0xffffffff
- .word baz at GOTPCREL-0xffffffff
+ .word %gotpcrel(baz+0xffffffff)
+ .word %gotpcrel(baz-0xffffffff)
diff --git a/lld/test/ELF/aarch64-reloc-plt32.s b/lld/test/ELF/aarch64-reloc-plt32.s
index 8a3b989a909b8..cd442e76fcf3d 100644
--- a/lld/test/ELF/aarch64-reloc-plt32.s
+++ b/lld/test/ELF/aarch64-reloc-plt32.s
@@ -32,6 +32,6 @@
.globl _start
_start:
.data
- .word foo at PLT - . + 2149589079
- .word foo at PLT - . - 2145378212
- .word foo at PLT - .
+ .word %pltpcrel(foo + 2149589079)
+ .word %pltpcrel(foo - 2145378212)
+ .word %pltpcrel(foo)
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 3641e22e6f76a..88ccc043d8b89 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -181,6 +181,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
OperandVector &Operands);
+ bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
bool parseDataExpr(const MCExpr *&Res) override;
bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc);
@@ -8190,8 +8191,31 @@ bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
return false;
}
+bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
+ SMLoc Loc = getLoc();
+ if (getLexer().getKind() != AsmToken::Identifier)
+ return TokError("expected '%' relocation specifier");
+ StringRef Identifier = getParser().getTok().getIdentifier();
+ auto Spec = AArch64::parsePercentSpecifierName(Identifier);
+ if (!Spec)
+ return TokError("invalid relocation specifier");
+
+ getParser().Lex(); // Eat the identifier
+ if (parseToken(AsmToken::LParen, "expected '('"))
+ return true;
+
+ const MCExpr *SubExpr;
+ if (getParser().parseParenExpression(SubExpr, E))
+ return true;
+
+ Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc);
+ return false;
+}
+
bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
SMLoc EndLoc;
+ if (parseOptionalToken(AsmToken::Percent))
+ return parseExprWithSpecifier(Res, EndLoc);
if (getParser().parseExpression(Res))
return true;
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index a388216a95098..5add98dcab931 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -104,6 +104,18 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
break;
}
+ switch (RefKind) {
+ case AArch64::S_GOTPCREL:
+ case AArch64::S_PLT:
+ if (Kind == FK_Data_4)
+ break;
+ reportError(Fixup.getLoc(), AArch64::getSpecifierName(RefKind) +
+ " can only be used in a .word directive");
+ return ELF::R_RISCV_NONE;
+ default:
+ break;
+ }
+
// Extract the relocation type from the fixup kind, after applying STT_TLS as
// needed.
if (mc::isRelocation(Fixup.getKind()))
@@ -117,8 +129,7 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
case FK_Data_2:
return R_CLS(PREL16);
case FK_Data_4: {
- return Target.getSpecifier() == AArch64::S_PLT ? R_CLS(PLT32)
- : R_CLS(PREL32);
+ return R_CLS(PREL32);
}
case FK_Data_8:
if (IsILP32) {
@@ -220,9 +231,13 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
case FK_Data_2:
return R_CLS(ABS16);
case FK_Data_4:
- return (!IsILP32 && Target.getSpecifier() == AArch64::S_GOTPCREL)
- ? ELF::R_AARCH64_GOTPCREL32
- : R_CLS(ABS32);
+ if (!IsILP32) {
+ if (Target.getSpecifier() == AArch64::S_GOTPCREL)
+ return ELF::R_AARCH64_GOTPCREL32;
+ if (Target.getSpecifier() == AArch64::S_PLT)
+ return ELF::R_AARCH64_PLT32;
+ }
+ return R_CLS(ABS32);
case FK_Data_8: {
if (IsILP32) {
reportError(
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
index 2b5cf3484ffc1..2a3addbc0d71e 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
@@ -113,12 +113,22 @@ StringRef AArch64::getSpecifierName(AArch64::Specifier S) {
case AArch64::S_GOT_AUTH: return ":got_auth:";
case AArch64::S_GOT_AUTH_PAGE: return ":got_auth:";
case AArch64::S_GOT_AUTH_LO12: return ":got_auth_lo12:";
+
+ case AArch64::S_GOTPCREL: return "%gotpcrel";
+ case AArch64::S_PLT: return "%pltpcrel";
default:
llvm_unreachable("Invalid relocation specifier");
}
// clang-format on
}
+AArch64::Specifier AArch64::parsePercentSpecifierName(StringRef name) {
+ return StringSwitch<AArch64::Specifier>(name)
+ .Case("pltpcrel", AArch64::S_PLT)
+ .Case("gotpcrel", AArch64::S_GOTPCREL)
+ .Default(0);
+}
+
static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) {
if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm))
@@ -232,8 +242,13 @@ void AArch64MCAsmInfoELF::printSpecifierExpr(
raw_ostream &OS, const MCSpecifierExpr &Expr) const {
if (auto *AE = dyn_cast<AArch64AuthMCExpr>(&Expr))
return AE->print(OS, this);
- OS << AArch64::getSpecifierName(Expr.getSpecifier());
+ auto Str = AArch64::getSpecifierName(Expr.getSpecifier());
+ OS << Str;
+ if (!Str.empty() && Str[0] == '%')
+ OS << '(';
printExpr(OS, *Expr.getSubExpr());
+ if (!Str.empty() && Str[0] == '%')
+ OS << ')';
}
bool AArch64MCAsmInfoELF::evaluateAsRelocatableImpl(
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
index 0dfa61b1dc60e..971ba58497f96 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
@@ -183,6 +183,8 @@ enum {
/// (e.g. ":got:", ":lo12:").
StringRef getSpecifierName(Specifier S);
+Specifier parsePercentSpecifierName(StringRef);
+
inline Specifier getSymbolLoc(Specifier S) {
return static_cast<Specifier>(S & AArch64::S_SymLocBits);
}
diff --git a/llvm/test/MC/AArch64/data-directive-specifier.s b/llvm/test/MC/AArch64/data-directive-specifier.s
index 2cb7eb3a3ca81..8d559442ac763 100644
--- a/llvm/test/MC/AArch64/data-directive-specifier.s
+++ b/llvm/test/MC/AArch64/data-directive-specifier.s
@@ -1,54 +1,62 @@
+# RUN: llvm-mc -triple=aarch64 %s | FileCheck %s --check-prefix=ASM
# RUN: llvm-mc -triple=aarch64 -filetype=obj %s | llvm-readobj -r - | FileCheck %s
-# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
-# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym OBJERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBJERR --implicit-check-not=error:
+
+# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR0=1 2>&1 | FileCheck %s --check-prefix=ERR0 --implicit-check-not=error:
+# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
.globl g
g:
l:
+# ASM: .word %pltpcrel(l)
# CHECK: Section ({{.*}}) .rela.data {
# CHECK-NEXT: 0x0 R_AARCH64_PLT32 l 0x0
-# CHECK-NEXT: 0x4 R_AARCH64_PLT32 l 0x4
-# CHECK-NEXT: 0x8 R_AARCH64_PLT32 extern 0x4
-# CHECK-NEXT: 0xC R_AARCH64_PLT32 g 0x8
-# CHECK-NEXT: 0x10 R_AARCH64_PLT32 g 0x18
+# CHECK-NEXT: 0x4 R_AARCH64_PLT32 extern 0x4
+# CHECK-NEXT: 0x8 R_AARCH64_PLT32 g 0x8
# CHECK-NEXT: }
.data
-.word l at plt - .
-.word l at plt - .data
-
-.word extern at plt - . + 4
-.word g at plt - . + 8
-.word g at plt - .data + 8
+.word %pltpcrel(l)
+.word %pltpcrel(extern + 4), %pltpcrel(g + 8)
+# ASM: .word %gotpcrel(data1)
# CHECK: Section ({{.*}}) .rela.data1 {
# CHECK-NEXT: 0x0 R_AARCH64_GOTPCREL32 data1 0x0
# CHECK-NEXT: 0x4 R_AARCH64_GOTPCREL32 extern 0x4
-# CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 extern 0xFFFFFFFFFFFFFFFB
+# CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 extern 0xFFFFFFFFFFFFFFFB
# CHECK-NEXT: }
.section .data1,"aw"
data1:
-.word data1 at GOTPCREL
-.word extern at gotpcrel+4
-.word extern at GOTPCREL-5
+.word %gotpcrel(data1)
+.word %gotpcrel(extern+4), %gotpcrel(extern-5)
-## Test parse-time errors
-.ifdef ERR
-# ERR: [[#@LINE+1]]:9: error: @ specifier only allowed after a symbol
-.quad 3 at plt - .
+.ifdef ERR0
+# ERR0: [[#@LINE+1]]:8: error: invalid relocation specifier
+.word %xxx(l)
+
+# ERR0: [[#@LINE+1]]:17: error: expected '('
+.word %pltpcrel l
-# ERR: [[#@LINE+1]]:9: error: expected ')'
-.quad (l at plt - .)
+# ERR0: [[#@LINE+2]]:14: error: unknown token in expression
+# ERR0: [[#@LINE+1]]:14: error: invalid operand
+ldr w0, [x1, %pltpcrel(g)]
.endif
-.ifdef OBJERR
-.quad g at plt - .
+.ifdef ERR
+# ERR: [[#@LINE+1]]:8: error: %pltpcrel can only be used in a .word directive
+.quad %pltpcrel(g)
+
+# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
+.word %pltpcrel(g-.)
+
+# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
+.word %pltpcrel(extern - und)
-.word extern at gotpcrel - .
+# ERR: [[#@LINE+1]]:8: error: %gotpcrel can only be used in a .word directive
+.quad %gotpcrel(g)
-# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
-.word extern at plt - und
+# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
+.word %gotpcrel(extern - .)
-# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
-.word extern at gotpcrel - und
+# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
+.word %gotpcrel(extern - und)
.endif
``````````
</details>
https://github.com/llvm/llvm-project/pull/155776
More information about the llvm-commits
mailing list