diff options
| author | Fangrui Song <i@maskray.me> | 2025-03-02 11:27:15 -0800 |
|---|---|---|
| committer | Fangrui Song <i@maskray.me> | 2025-03-02 11:27:15 -0800 |
| commit | 18e09da2552d99a641b8257e22b4067730cdb2bc (patch) | |
| tree | 41041980bf8c815d8e22d491da79d557584b7559 /llvm/lib/Target/Mips/AsmParser | |
| parent | 6d847b1aada50d59c3e29f2e7eff779c0ee8182c (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.cpp | 140 |
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. |
