summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Mips/AsmParser
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2025-03-02 11:27:15 -0800
committerFangrui Song <i@maskray.me>2025-03-02 11:27:15 -0800
commit18e09da2552d99a641b8257e22b4067730cdb2bc (patch)
tree41041980bf8c815d8e22d491da79d557584b7559 /llvm/lib/Target/Mips/AsmParser
parent6d847b1aada50d59c3e29f2e7eff779c0ee8182c (diff)
[Mips] Rework relocation expression parsing
A relocation expression might be used in an immediate operand or a memory offset. https://reviews.llvm.org/D23110 , which intended to generalize chained relocation operators (%hi(%neg(%gp_rel(x)))), inappropriated introduced intrusive changes to the generic code. This patch drops the intrusive changes and significantly simplifies the code. The new style is similar to pre-D23110 but much cleaner. Some weird expressions allowed by gas are not supported for simplicity, e.g. "%lo foo", "(%lo(foo))", "%lo(foo)+1". "(%lo(foo))", while previously parsed, is not used in practice. "%lo(foo)+1" and "%lo(2*4)+foo" were previously parsed but would lead to an error anyway as the expression is not relocatable (`evaluateSymbolicAdd` does not fold the Add when RefKind are different).
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser')
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp140
1 files changed, 65 insertions, 75 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index bed1ef882ffe..d9843ee6fc51 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -205,6 +205,7 @@ class MipsAsmParser : public MCTargetAsmParser {
ParseStatus parseJumpTarget(OperandVector &Operands);
ParseStatus parseInvNum(OperandVector &Operands);
ParseStatus parseRegisterList(OperandVector &Operands);
+ const MCExpr *parseRelocExpr();
bool searchSymbolAlias(OperandVector &Operands);
@@ -353,8 +354,6 @@ class MipsAsmParser : public MCTargetAsmParser {
bool reportParseError(const Twine &ErrorMsg);
bool reportParseError(SMLoc Loc, const Twine &ErrorMsg);
- bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
-
bool parseSetMips0Directive();
bool parseSetArchDirective();
bool parseSetFeature(uint64_t Feature);
@@ -741,64 +740,6 @@ public:
bool isLittle() const { return IsLittleEndian; }
- const MCExpr *createTargetUnaryExpr(const MCExpr *E,
- AsmToken::TokenKind OperatorToken,
- MCContext &Ctx) override {
- switch(OperatorToken) {
- default:
- llvm_unreachable("Unknown token");
- return nullptr;
- case AsmToken::PercentCall16:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
- case AsmToken::PercentCall_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
- case AsmToken::PercentCall_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
- case AsmToken::PercentDtprel_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
- case AsmToken::PercentDtprel_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
- case AsmToken::PercentGot:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
- case AsmToken::PercentGot_Disp:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
- case AsmToken::PercentGot_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
- case AsmToken::PercentGot_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
- case AsmToken::PercentGot_Ofst:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
- case AsmToken::PercentGot_Page:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
- case AsmToken::PercentGottprel:
- return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
- case AsmToken::PercentGp_Rel:
- return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
- case AsmToken::PercentHi:
- return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
- case AsmToken::PercentHigher:
- return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
- case AsmToken::PercentHighest:
- return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
- case AsmToken::PercentLo:
- return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
- case AsmToken::PercentNeg:
- return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
- case AsmToken::PercentPcrel_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
- case AsmToken::PercentPcrel_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
- case AsmToken::PercentTlsgd:
- return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
- case AsmToken::PercentTlsldm:
- return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
- case AsmToken::PercentTprel_Hi:
- return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
- case AsmToken::PercentTprel_Lo:
- return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
- }
- }
-
bool areEqualRegs(const MCParsedAsmOperand &Op1,
const MCParsedAsmOperand &Op2) const override;
};
@@ -6415,6 +6356,64 @@ MCRegister MipsAsmParser::getReg(int RC, int RegNo) {
return getContext().getRegisterInfo()->getRegClass(RC).getRegister(RegNo);
}
+// Parse an expression with optional relocation operator prefixes (e.g. %lo).
+// Some weird expressions allowed by gas are not supported for simplicity,
+// e.g. "%lo foo", "(%lo(foo))", "%lo(foo)+1".
+const MCExpr *MipsAsmParser::parseRelocExpr() {
+ auto getOp = [](StringRef Op) {
+ return StringSwitch<MipsMCExpr::MipsExprKind>(Op)
+ .Case("call16", MipsMCExpr::MEK_GOT_CALL)
+ .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
+ .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
+ .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
+ .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
+ .Case("got", MipsMCExpr::MEK_GOT)
+ .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
+ .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
+ .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
+ .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
+ .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
+ .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
+ .Case("gp_rel", MipsMCExpr::MEK_GPREL)
+ .Case("hi", MipsMCExpr::MEK_HI)
+ .Case("higher", MipsMCExpr::MEK_HIGHER)
+ .Case("highest", MipsMCExpr::MEK_HIGHEST)
+ .Case("lo", MipsMCExpr::MEK_LO)
+ .Case("neg", MipsMCExpr::MEK_NEG)
+ .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
+ .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
+ .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
+ .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
+ .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
+ .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
+ .Default(MipsMCExpr::MEK_None);
+ };
+
+ MCAsmParser &Parser = getParser();
+ StringRef Name;
+ const MCExpr *Res = nullptr;
+ SmallVector<MipsMCExpr::MipsExprKind, 0> Ops;
+ while (parseOptionalToken(AsmToken::Percent)) {
+ if (Parser.parseIdentifier(Name) ||
+ Parser.parseToken(AsmToken::LParen, "expected '('"))
+ return nullptr;
+ auto Op = getOp(Name);
+ if (Op == MipsMCExpr::MEK_None) {
+ Error(Parser.getTok().getLoc(), "invalid relocation operator");
+ return nullptr;
+ }
+ Ops.push_back(Op);
+ }
+ if (Parser.parseExpression(Res))
+ return nullptr;
+ while (Ops.size()) {
+ if (Parser.parseToken(AsmToken::RParen, "expected ')'"))
+ return nullptr;
+ Res = MipsMCExpr::create(Ops.pop_back_val(), Res, getContext());
+ }
+ return Res;
+}
+
bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
MCAsmParser &Parser = getParser();
LLVM_DEBUG(dbgs() << "parseOperand\n");
@@ -6465,15 +6464,11 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
return false;
}
default: {
- LLVM_DEBUG(dbgs() << ".. generic integer expression\n");
-
- const MCExpr *Expr;
SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
- if (getParser().parseExpression(Expr))
+ const MCExpr *Expr = parseRelocExpr();
+ if (!Expr)
return true;
-
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-
Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
return false;
}
@@ -6512,14 +6507,6 @@ ParseStatus MipsAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
return (Reg == (unsigned)-1) ? ParseStatus::NoMatch : ParseStatus::Success;
}
-bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
- SMLoc S;
-
- if (isParenExpr)
- return getParser().parseExpression(Res, S) || getParser().parseRParen();
- return getParser().parseExpression(Res);
-}
-
ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
LLVM_DEBUG(dbgs() << "parseMemOperand\n");
@@ -6536,7 +6523,10 @@ ParseStatus MipsAsmParser::parseMemOperand(OperandVector &Operands) {
}
if (getLexer().getKind() != AsmToken::Dollar) {
- if (parseMemOffset(IdVal, isParenExpr))
+ IdVal = parseRelocExpr();
+ if (!IdVal)
+ return ParseStatus::Failure;
+ if (isParenExpr && Parser.parseRParen())
return ParseStatus::Failure;
const AsmToken &Tok = Parser.getTok(); // Get the next token.