summaryrefslogtreecommitdiff
path: root/llvm/lib
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
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')
-rw-r--r--llvm/lib/MC/MCParser/AsmLexer.cpp39
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp36
-rw-r--r--llvm/lib/MC/MCParser/MCAsmLexer.cpp24
-rw-r--r--llvm/lib/MC/MCParser/MasmParser.cpp36
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp140
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp1
6 files changed, 65 insertions, 211 deletions
diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp
index 32b6e869cc63..41ff94d125a1 100644
--- a/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -879,45 +879,6 @@ AsmToken AsmLexer::LexToken() {
if (LexMotorolaIntegers && (*CurPtr == '0' || *CurPtr == '1')) {
return LexDigit();
}
-
- if (MAI.hasMipsExpressions()) {
- AsmToken::TokenKind Operator;
- unsigned OperatorLength;
-
- std::tie(Operator, OperatorLength) =
- StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>(
- StringRef(CurPtr))
- .StartsWith("call16", {AsmToken::PercentCall16, 7})
- .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
- .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
- .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
- .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
- .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
- .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
- .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
- .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
- .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
- .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
- .StartsWith("got", {AsmToken::PercentGot, 4})
- .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
- .StartsWith("higher", {AsmToken::PercentHigher, 7})
- .StartsWith("highest", {AsmToken::PercentHighest, 8})
- .StartsWith("hi", {AsmToken::PercentHi, 3})
- .StartsWith("lo", {AsmToken::PercentLo, 3})
- .StartsWith("neg", {AsmToken::PercentNeg, 4})
- .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
- .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
- .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
- .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
- .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
- .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
- .Default({AsmToken::Percent, 1});
-
- if (Operator != AsmToken::Percent) {
- CurPtr += OperatorLength - 1;
- return AsmToken(Operator, StringRef(TokStart, OperatorLength));
- }
- }
return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
case '/':
IsAtStartOfStatement = OldIsAtStartOfStatement;
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index db941d7d84bf..be90ac33f853 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1344,42 +1344,6 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
return true;
Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
return false;
- // MIPS unary expression operators. The lexer won't generate these tokens if
- // MCAsmInfo::HasMipsExpressions is false for the target.
- case AsmToken::PercentCall16:
- case AsmToken::PercentCall_Hi:
- case AsmToken::PercentCall_Lo:
- case AsmToken::PercentDtprel_Hi:
- case AsmToken::PercentDtprel_Lo:
- case AsmToken::PercentGot:
- case AsmToken::PercentGot_Disp:
- case AsmToken::PercentGot_Hi:
- case AsmToken::PercentGot_Lo:
- case AsmToken::PercentGot_Ofst:
- case AsmToken::PercentGot_Page:
- case AsmToken::PercentGottprel:
- case AsmToken::PercentGp_Rel:
- case AsmToken::PercentHi:
- case AsmToken::PercentHigher:
- case AsmToken::PercentHighest:
- case AsmToken::PercentLo:
- case AsmToken::PercentNeg:
- case AsmToken::PercentPcrel_Hi:
- case AsmToken::PercentPcrel_Lo:
- case AsmToken::PercentTlsgd:
- case AsmToken::PercentTlsldm:
- case AsmToken::PercentTprel_Hi:
- case AsmToken::PercentTprel_Lo:
- Lex(); // Eat the operator.
- if (Lexer.isNot(AsmToken::LParen))
- return TokError("expected '(' after operator");
- Lex(); // Eat the operator.
- if (parseExpression(Res, EndLoc))
- return true;
- if (parseRParen())
- return true;
- Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
- return !Res;
}
}
diff --git a/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/llvm/lib/MC/MCParser/MCAsmLexer.cpp
index f202b53732fc..8bdba218aa9c 100644
--- a/llvm/lib/MC/MCParser/MCAsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmLexer.cpp
@@ -96,30 +96,6 @@ void AsmToken::dump(raw_ostream &OS) const {
case AsmToken::Space: OS << "Space"; break;
case AsmToken::Star: OS << "Star"; break;
case AsmToken::Tilde: OS << "Tilde"; break;
- case AsmToken::PercentCall16: OS << "PercentCall16"; break;
- case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break;
- case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break;
- case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break;
- case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break;
- case AsmToken::PercentGot: OS << "PercentGot"; break;
- case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break;
- case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break;
- case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break;
- case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break;
- case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break;
- case AsmToken::PercentGottprel: OS << "PercentGottprel"; break;
- case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break;
- case AsmToken::PercentHi: OS << "PercentHi"; break;
- case AsmToken::PercentHigher: OS << "PercentHigher"; break;
- case AsmToken::PercentHighest: OS << "PercentHighest"; break;
- case AsmToken::PercentLo: OS << "PercentLo"; break;
- case AsmToken::PercentNeg: OS << "PercentNeg"; break;
- case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break;
- case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break;
- case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break;
- case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break;
- case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break;
- case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break;
}
// Print the token string.
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index 328411f080f1..19947b377f98 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -1610,42 +1610,6 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
return true;
Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
return false;
- // MIPS unary expression operators. The lexer won't generate these tokens if
- // MCAsmInfo::HasMipsExpressions is false for the target.
- case AsmToken::PercentCall16:
- case AsmToken::PercentCall_Hi:
- case AsmToken::PercentCall_Lo:
- case AsmToken::PercentDtprel_Hi:
- case AsmToken::PercentDtprel_Lo:
- case AsmToken::PercentGot:
- case AsmToken::PercentGot_Disp:
- case AsmToken::PercentGot_Hi:
- case AsmToken::PercentGot_Lo:
- case AsmToken::PercentGot_Ofst:
- case AsmToken::PercentGot_Page:
- case AsmToken::PercentGottprel:
- case AsmToken::PercentGp_Rel:
- case AsmToken::PercentHi:
- case AsmToken::PercentHigher:
- case AsmToken::PercentHighest:
- case AsmToken::PercentLo:
- case AsmToken::PercentNeg:
- case AsmToken::PercentPcrel_Hi:
- case AsmToken::PercentPcrel_Lo:
- case AsmToken::PercentTlsgd:
- case AsmToken::PercentTlsldm:
- case AsmToken::PercentTprel_Hi:
- case AsmToken::PercentTprel_Lo:
- Lex(); // Eat the operator.
- if (Lexer.isNot(AsmToken::LParen))
- return TokError("expected '(' after operator");
- Lex(); // Eat the operator.
- if (parseExpression(Res, EndLoc))
- return true;
- if (parseRParen())
- return true;
- Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
- return !Res;
}
}
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.
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index fa09a14b3e23..3d175e163eac 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -49,7 +49,6 @@ MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
DwarfRegNumForCFI = true;
- HasMipsExpressions = true;
}
void MipsCOFFMCAsmInfo::anchor() {}