Skip to content

Commit 5517689

Browse files
committed
[AArch64] Refactor @plt, @gotpcrel, and @AUTH to use parseDataExpr
Following PR llvm#132569, which added `parseDataExpr` for parsing expressions in data directives (e.g., `.word`), this PR migrates AArch64 `@plt`, `@gotpcrel`, and `@AUTH` from the `parsePrimaryExpr` workaround to `parseDataExpr`. The goal is to align with the GNU assembler model, where relocation specifiers apply to the entire operand rather than individual terms, reducing complexity-especially evident in `@AUTH` parsing. Note: AArch64 ELF lacks an official syntax for data directives (llvm#132570). A prefix notation might be a preferable future direction. In the test elf-reloc-ptrauth.s, many errors are now reported at parse time.
1 parent 36978fa commit 5517689

File tree

6 files changed

+94
-116
lines changed

6 files changed

+94
-116
lines changed

llvm/include/llvm/MC/MCParser/MCAsmLexer.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ class MCAsmLexer {
148148
void setSkipSpace(bool val) { SkipSpace = val; }
149149

150150
bool getAllowAtInIdentifier() { return AllowAtInIdentifier; }
151-
void setAllowAtInIdentifier(bool v) { AllowAtInIdentifier = v; }
151+
bool setAllowAtInIdentifier(bool v) {
152+
return std::exchange(AllowAtInIdentifier, v);
153+
}
152154

153155
void setAllowHashInIdentifier(bool V) { AllowHashInIdentifier = V; }
154156

llvm/lib/MC/MCParser/AsmParser.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
12041204

12051205
Split = std::make_pair(Identifier, VName);
12061206
}
1207-
} else {
1207+
} else if (Lexer.getAllowAtInIdentifier()) {
12081208
Split = Identifier.split('@');
12091209
}
12101210
} else if (MAI.useParensForSpecifier() &&
@@ -1463,8 +1463,7 @@ bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
14631463
// As a special case, we support 'a op b @ modifier' by rewriting the
14641464
// expression to include the modifier. This is inefficient, but in general we
14651465
// expect users to use 'a@modifier op b'.
1466-
if (Ctx.getAsmInfo()->useAtForSpecifier() &&
1467-
parseOptionalToken(AsmToken::At)) {
1466+
if (Lexer.getAllowAtInIdentifier() && parseOptionalToken(AsmToken::At)) {
14681467
if (Lexer.isNot(AsmToken::Identifier))
14691468
return TokError("unexpected symbol modifier following '@'");
14701469

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

+56-52
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
#include "llvm/ADT/APInt.h"
1919
#include "llvm/ADT/ArrayRef.h"
2020
#include "llvm/ADT/STLExtras.h"
21+
#include "llvm/ADT/ScopeExit.h"
2122
#include "llvm/ADT/SmallSet.h"
2223
#include "llvm/ADT/SmallVector.h"
2324
#include "llvm/ADT/StringExtras.h"
2425
#include "llvm/ADT/StringMap.h"
2526
#include "llvm/ADT/StringRef.h"
2627
#include "llvm/ADT/StringSwitch.h"
2728
#include "llvm/ADT/Twine.h"
29+
#include "llvm/MC/MCAsmInfo.h"
2830
#include "llvm/MC/MCContext.h"
2931
#include "llvm/MC/MCExpr.h"
3032
#include "llvm/MC/MCInst.h"
@@ -180,6 +182,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
180182
bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
181183
OperandVector &Operands);
182184

185+
bool parseDataExpr(const MCExpr *&Res) override;
183186
bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc);
184187

185188
bool parseDirectiveArch(SMLoc L);
@@ -335,8 +338,6 @@ class AArch64AsmParser : public MCTargetAsmParser {
335338
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
336339
unsigned Kind) override;
337340

338-
bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
339-
340341
static bool classifySymbolRef(const MCExpr *Expr,
341342
AArch64MCExpr::Specifier &ELFSpec,
342343
MCSymbolRefExpr::VariantKind &DarwinRefKind,
@@ -4478,6 +4479,18 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
44784479
if (HasELFModifier)
44794480
ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
44804481

4482+
if (getContext().getAsmInfo()->hasSubsectionsViaSymbols() &&
4483+
parseOptionalToken(AsmToken::At)) {
4484+
StringRef Spec;
4485+
if (getParser().parseIdentifier(Spec))
4486+
return Error(getLoc(), "expected specifier after '@'");
4487+
if (auto *SRE = dyn_cast<MCSymbolRefExpr>(ImmVal)) {
4488+
auto MaybeSpec = getContext().getAsmInfo()->getSpecifierForName(Spec);
4489+
ImmVal =
4490+
MCSymbolRefExpr::create(&SRE->getSymbol(), *MaybeSpec, getContext());
4491+
}
4492+
}
4493+
44814494
return false;
44824495
}
44834496

@@ -8086,11 +8099,48 @@ bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
80868099
return false;
80878100
}
80888101

8089-
bool AArch64AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
8090-
// Try @AUTH expressions: they're more complex than the usual symbol variants.
8091-
if (!parseAuthExpr(Res, EndLoc))
8102+
bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
8103+
SMLoc EndLoc;
8104+
8105+
if (getParser().parseExpression(Res))
8106+
return true;
8107+
MCAsmParser &Parser = getParser();
8108+
if (!parseOptionalToken(AsmToken::At))
80928109
return false;
8093-
return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
8110+
if (getLexer().getKind() != AsmToken::Identifier)
8111+
return Error(getLoc(), "expected relocation specifier");
8112+
8113+
std::string Identifier = Parser.getTok().getIdentifier().lower();
8114+
SMLoc Loc = getLoc();
8115+
Lex();
8116+
if (Identifier == "auth")
8117+
return parseAuthExpr(Res, EndLoc);
8118+
8119+
auto Spec = MCSymbolRefExpr::VK_PLT;
8120+
if (Identifier == "gotpcrel")
8121+
Spec = MCSymbolRefExpr::VK_GOTPCREL;
8122+
else if (Identifier != "plt")
8123+
return Error(Loc, "invalid relocation specifier");
8124+
if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Res))
8125+
Res = MCSymbolRefExpr::create(&SRE->getSymbol(), Spec, getContext(),
8126+
SRE->getLoc());
8127+
else
8128+
return Error(Loc, "this relocation specifier must follow a symbol");
8129+
8130+
for (;;) {
8131+
std::optional<MCBinaryExpr::Opcode> Opcode;
8132+
if (parseOptionalToken(AsmToken::Plus))
8133+
Opcode = MCBinaryExpr::Add;
8134+
else if (parseOptionalToken(AsmToken::Minus))
8135+
Opcode = MCBinaryExpr::Sub;
8136+
else
8137+
break;
8138+
const MCExpr *Term;
8139+
if (getParser().parsePrimaryExpr(Term, EndLoc, nullptr))
8140+
return true;
8141+
Res = MCBinaryExpr::create(*Opcode, Res, Term, getContext());
8142+
}
8143+
return false;
80948144
}
80958145

80968146
/// parseAuthExpr
@@ -8100,54 +8150,8 @@ bool AArch64AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
81008150
bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
81018151
MCAsmParser &Parser = getParser();
81028152
MCContext &Ctx = getContext();
8103-
81048153
AsmToken Tok = Parser.getTok();
81058154

8106-
// Look for '_sym@AUTH' ...
8107-
if (Tok.is(AsmToken::Identifier) && Tok.getIdentifier().ends_with("@AUTH")) {
8108-
StringRef SymName = Tok.getIdentifier().drop_back(strlen("@AUTH"));
8109-
if (SymName.contains('@'))
8110-
return TokError(
8111-
"combination of @AUTH with other modifiers not supported");
8112-
Res = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(SymName), Ctx);
8113-
8114-
Parser.Lex(); // Eat the identifier.
8115-
} else {
8116-
// ... or look for a more complex symbol reference, such as ...
8117-
SmallVector<AsmToken, 6> Tokens;
8118-
8119-
// ... '"_long sym"@AUTH' ...
8120-
if (Tok.is(AsmToken::String))
8121-
Tokens.resize(2);
8122-
// ... or '(_sym + 5)@AUTH'.
8123-
else if (Tok.is(AsmToken::LParen))
8124-
Tokens.resize(6);
8125-
else
8126-
return true;
8127-
8128-
if (Parser.getLexer().peekTokens(Tokens) != Tokens.size())
8129-
return true;
8130-
8131-
// In either case, the expression ends with '@' 'AUTH'.
8132-
if (Tokens[Tokens.size() - 2].isNot(AsmToken::At) ||
8133-
Tokens[Tokens.size() - 1].isNot(AsmToken::Identifier) ||
8134-
Tokens[Tokens.size() - 1].getIdentifier() != "AUTH")
8135-
return true;
8136-
8137-
if (Tok.is(AsmToken::String)) {
8138-
StringRef SymName;
8139-
if (Parser.parseIdentifier(SymName))
8140-
return true;
8141-
Res = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(SymName), Ctx);
8142-
} else {
8143-
if (Parser.parsePrimaryExpr(Res, EndLoc, nullptr))
8144-
return true;
8145-
}
8146-
8147-
Parser.Lex(); // '@'
8148-
Parser.Lex(); // 'AUTH'
8149-
}
8150-
81518155
// At this point, we encountered "<id>@AUTH". There is no fallback anymore.
81528156
if (parseToken(AsmToken::LParen, "expected '('"))
81538157
return true;

llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ AArch64MCAsmInfoDarwin::AArch64MCAsmInfoDarwin(bool IsILP32) {
6161
UsesELFSectionDirectiveForBSS = true;
6262
SupportsDebugInformation = true;
6363
UseDataRegionDirectives = true;
64+
UseAtForSpecifier = false;
6465

6566
ExceptionsType = ExceptionHandling::DwarfCFI;
6667

@@ -105,6 +106,7 @@ AArch64MCAsmInfoELF::AArch64MCAsmInfoELF(const Triple &T) {
105106
Data64bitsDirective = "\t.xword\t";
106107

107108
UseDataRegionDirectives = false;
109+
UseAtForSpecifier = false;
108110

109111
WeakRefDirective = "\t.weak\t";
110112

llvm/test/MC/AArch64/data-directive-specifier.s

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# RUN: llvm-mc -triple=aarch64 -filetype=obj %s | llvm-readobj -r - | FileCheck %s
2-
# 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:
2+
# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
3+
# 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:
34

45
.globl g
56
g:
@@ -32,13 +33,21 @@ data1:
3233
.word extern@GOTPCREL-5
3334

3435
.ifdef ERR
35-
# ERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
36-
.word extern@plt - und
36+
# ERR: [[#@LINE+1]]:9: error: this relocation specifier must follow a symbol
37+
.quad 3@plt - .
38+
39+
# ERR: [[#@LINE+1]]:9: error: expected ')'
40+
.quad (l@plt - .)
41+
.endif
3742

43+
.ifdef OBJERR
3844
.quad g@plt - .
3945

4046
.word extern@gotpcrel - .
4147

42-
# ERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
48+
# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
49+
.word extern@plt - und
50+
51+
# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
4352
.word extern@gotpcrel - und
4453
.endif

llvm/test/MC/AArch64/elf-reloc-ptrauth.s

+18-56
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: llvm-mc -triple=aarch64 %s --defsym=ASMONLY=1 | FileCheck %s --check-prefix=ASM
1+
// RUN: llvm-mc -triple=aarch64 %s | FileCheck %s --check-prefix=ASM
22

33
// RUN: llvm-mc -triple=aarch64 -filetype=obj %s | \
44
// RUN: llvm-readelf -S -r -x .test - | FileCheck %s --check-prefix=RELOC
@@ -41,8 +41,6 @@
4141
// RELOC-NEXT: 70 00000000 10000000
4242
// ^^^^ discriminator
4343
// ^^ 0 no addr diversity 0 reserved 00 ia key 0000 reserved
44-
// RELOC-NEXT: 80 04000000 00000000
45-
// Folded to constant 4 bytes difference between _g9 and _g8
4644

4745
.section .helper
4846
.local "_g 6"
@@ -63,12 +61,12 @@ _g9:
6361
.quad _g0@AUTH(ia,42)
6462
.quad 0
6563

66-
// ASM: .xword _g1@AUTH(ib,0)
67-
.quad _g1@AUTH(ib,0)
64+
// ASM: .xword (+_g1)@AUTH(ib,0)
65+
.quad +_g1@AUTH(ib,0)
6866
.quad 0
6967

7068
// ASM: .xword _g2@AUTH(da,5,addr)
71-
.quad _g2@AUTH(da,5,addr)
69+
.quad _g2 @ AUTH(da,5,addr)
7270
.quad 0
7371

7472
// ASM: .xword _g3@AUTH(db,65535,addr)
@@ -91,33 +89,20 @@ _g9:
9189
.quad ("_g 7" + 7)@AUTH(ia,16)
9290
.quad 0
9391

94-
// ASM: .xword _g9@AUTH(ia,42)-_g8@AUTH(ia,42)
95-
.quad _g9@AUTH(ia,42) - _g8@AUTH(ia,42)
96-
.quad 0
92+
// RUN: not llvm-mc -triple=aarch64 --defsym=ERR=1 %s 2>&1 | \
93+
// RUN: FileCheck %s --check-prefix=ERR
9794

98-
.ifdef ASMONLY
95+
.ifdef ERR
9996

100-
// ASM: .xword _g10@AUTH(ia,42)+1
10197
.quad _g10@AUTH(ia,42) + 1
10298

103-
// ASM: .xword 1+_g11@AUTH(ia,42)
10499
.quad 1 + _g11@AUTH(ia,42)
105100

106-
// ASM: .xword 1+_g12@AUTH(ia,42)+1
107101
.quad 1 + _g12@AUTH(ia,42) + 1
108102

109-
// ASM: .xword _g13@AUTH(ia,42)+_g14@AUTH(ia,42)
110103
.quad _g13@AUTH(ia,42) + _g14@AUTH(ia,42)
111104

112-
// ASM: .xword _g9@AUTH(ia,42)-_g8
113105
.quad _g9@AUTH(ia,42) - _g8
114-
.quad 0
115-
116-
.endif // ASMONLY
117-
118-
.ifdef ERR
119-
// RUN: not llvm-mc -triple=aarch64 --defsym=ERR=1 %s 2>&1 | \
120-
// RUN: FileCheck %s --check-prefix=ERR
121106

122107
// ERR: :[[#@LINE+1]]:15: error: expected '('
123108
.quad sym@AUTH)ia,42)
@@ -143,51 +128,28 @@ _g9:
143128
// ERR: :[[#@LINE+1]]:21: error: expected ')'
144129
.quad sym@AUTH(ia,42(
145130

146-
// ERR: :[[#@LINE+1]]:7: error: combination of @AUTH with other modifiers not supported
131+
// ERR: :[[#@LINE+1]]:14: error: unexpected token
147132
.quad sym@PLT@AUTH(ia,42)
148133

149-
// ERR: :[[#@LINE+1]]:11: error: invalid variant 'AUTH@GOT'
134+
// ERR: :[[#@LINE+1]]:15: error: expected '('
150135
.quad sym@AUTH@GOT(ia,42)
151136

152-
// ERR: :[[#@LINE+1]]:18: error: invalid variant 'TLSDESC@AUTH'
153-
.quad "long sym"@TLSDESC@AUTH(ia,42)
154-
155-
// ERR: :[[#@LINE+1]]:18: error: invalid variant 'AUTH@PLT'
137+
// ERR: :[[#@LINE+1]]:22: error: expected '('
156138
.quad "long sym"@AUTH@PLT(ia,42)
157139

158-
// ERR: :[[#@LINE+1]]:17: error: invalid variant 'GOT@AUTH'
140+
// ERR: :[[#@LINE+1]]:17: error: invalid relocation specifier
159141
.quad (sym - 5)@GOT@AUTH(ia,42)
160142

161-
// ERR: :[[#@LINE+1]]:17: error: invalid variant 'AUTH@TLSDESC'
162-
.quad (sym + 5)@AUTH@TLSDESC(ia,42)
163-
164-
// ERR: :[[#@LINE+1]]:12: error: invalid variant 'AUTH'
165-
.quad +sym@AUTH(ia,42)
166-
167-
.endif // ERR
168-
169-
.ifdef ERROBJ
170-
// RUN: not llvm-mc -triple=aarch64 -filetype=obj --defsym=ERROBJ=1 %s -o /dev/null 2>&1 | \
171-
// RUN: FileCheck %s --check-prefix=ERROBJ
172-
173-
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
143+
// ERR: :[[#@LINE+1]]:23: error: unexpected token
174144
.quad sym@AUTH(ia,42) + 1
175145

176-
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
177-
.quad 1 + sym@AUTH(ia,42)
178-
179-
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
146+
// ERR: :[[#@LINE+1]]:27: error: unexpected token
180147
.quad 1 + sym@AUTH(ia,42) + 1
181148

182-
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
183-
.quad sym@AUTH(ia,42) + sym@AUTH(ia,42)
184-
185-
// TODO: do we really want to emit an error here? It might not be important
186-
// whether a symbol has an AUTH modifier or not since the compile-time computed
187-
// distance remains the same. Leave it in such state as for now since it
188-
// makes code simpler: subtraction of a non-AUTH symbol and of a constant
189-
// are handled identically.
190-
// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
149+
/// @AUTH applies to the whole operand instead of an individual term.
150+
/// Trailing expression parts are not allowed even if the logical subtraction
151+
/// result might make sense.
152+
// ERR: :[[#@LINE+1]]:23: error: unexpected token
191153
.quad _g9@AUTH(ia,42) - _g8
192154

193-
.endif // ERROBJ
155+
.endif // ERR

0 commit comments

Comments
 (0)