Skip to content

Commit 93fbb97

Browse files
jrtc27veselypeta
authored andcommitted
[RISCV][MC] Backport support for parsing modifiers in data directives
This backports the core of fe6fb91 to support parsing `.foo %bar(expr)` in RISC-V assembly, which will be used as the syntax for code capabilities. Note that upstream has since switched to "specifier" rather than "modifier" for the terminology here, but I have kept RISC-V consistent with our older version in using "modifier". The MC header's comment does however use "specifier" as it's target-independent. Upstream commit message: [RISCV] Replace @plt/@gotpcrel in data directives with %pltpcrel %gotpcrel clang -fexperimental-relative-c++-abi-vtables might generate `@plt` and `@gotpcrel` specifiers in data directives. The syntax is not used in humand-written assembly code, and is not supported by GNU assembler. Note: the `@plt` in `.word foo@plt` is different from the legacy `call func@plt` (where `@plt` is simply ignored). The `@plt` syntax was selected was simply due to a quirk of AsmParser: the syntax was supported by all targets until I updated it to be an opt-in feature in a067175 RISC-V favors the `%specifier(expr)` syntax following MIPS and Sparc, and we should follow this convention. This PR adds support for `.word %pltpcrel(foo+offset)` and `.word %gotpcrel(foo)`, and drops `@plt` and `@gotpcrel`. * MCValue::SymA can no longer have a SymbolVariant. Add an assert similar to that of AArch64ELFObjectWriter.cpp before https://reviews.llvm.org/D81446 (see my analysis at https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers if intrigued) * `jump foo@plt, x31` now has a different diagnostic. Pull Request: llvm/llvm-project#132569
2 parents 8ef2267 + f64dc41 commit 93fbb97

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,12 @@ class MCTargetAsmParser : public MCAsmParserExtension {
412412
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
413413
return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
414414
}
415+
// Parse an expression in a data directive, possibly with a relocation
416+
// specifier.
417+
virtual bool parseDataExpr(const MCExpr *&Res) {
418+
SMLoc EndLoc;
419+
return getParser().parseExpression(Res, EndLoc);
420+
}
415421

416422
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc,
417423
SMLoc &EndLoc) = 0;

llvm/lib/MC/MCParser/AsmParser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3203,7 +3203,7 @@ bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
32033203
auto parseOp = [&]() -> bool {
32043204
const MCExpr *Value;
32053205
SMLoc ExprLoc = getLexer().getLoc();
3206-
if (checkForValidSection() || parseExpression(Value))
3206+
if (checkForValidSection() || getTargetParser().parseDataExpr(Value))
32073207
return true;
32083208
// Special case constant expressions to match code generator.
32093209
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
@@ -5881,7 +5881,7 @@ bool AsmParser::parseDirectiveCheriCap(SMLoc DirectiveLoc) {
58815881
if (!getTargetParser().isCheri())
58825882
return Error(DirectiveLoc, "'.chericap' requires CHERI");
58835883

5884-
if (parseExpression(Expr))
5884+
if (getTargetParser().parseDataExpr(Expr))
58855885
return true;
58865886

58875887
int64_t Value;

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ class RISCVAsmParser : public MCTargetAsmParser {
248248
ParseStatus parseZcmpSpimm(OperandVector &Operands);
249249

250250
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
251+
bool parseExprWithModifier(const MCExpr *&Res, SMLoc &E);
252+
bool parseDataExpr(const MCExpr *&Res) override;
251253

252254
bool parseDirectiveOption();
253255
bool parseDirectiveAttribute();
@@ -2236,7 +2238,14 @@ ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
22362238

22372239
if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
22382240
return ParseStatus::Failure;
2241+
const MCExpr *Expr = nullptr;
2242+
bool Failed = parseExprWithModifier(Expr, E);
2243+
if (!Failed)
2244+
Operands.push_back(RISCVOperand::createImm(Expr, S, E, isRV64()));
2245+
return Failed;
2246+
}
22392247

2248+
bool RISCVAsmParser::parseExprWithModifier(const MCExpr *&Res, SMLoc &E) {
22402249
if (getLexer().getKind() != AsmToken::Identifier)
22412250
return Error(getLoc(), "expected valid identifier for operand modifier");
22422251
StringRef Identifier = getParser().getTok().getIdentifier();
@@ -2246,15 +2255,21 @@ ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
22462255

22472256
getParser().Lex(); // Eat the identifier
22482257
if (parseToken(AsmToken::LParen, "expected '('"))
2249-
return ParseStatus::Failure;
2258+
return true;
22502259

22512260
const MCExpr *SubExpr;
22522261
if (getParser().parseParenExpression(SubExpr, E))
2253-
return ParseStatus::Failure;
2262+
return true;
22542263

2255-
const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
2256-
Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
2257-
return ParseStatus::Success;
2264+
Res = RISCVMCExpr::create(SubExpr, VK, getContext());
2265+
return false;
2266+
}
2267+
2268+
bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
2269+
SMLoc E;
2270+
if (parseOptionalToken(AsmToken::Percent))
2271+
return parseExprWithModifier(Res, E);
2272+
return getParser().parseExpression(Res);
22582273
}
22592274

22602275
ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {

0 commit comments

Comments
 (0)