mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 18:06:05 +00:00
[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).
This commit is contained in:
parent
6d847b1aad
commit
18e09da255
@ -432,10 +432,6 @@ protected:
|
||||
/// expressions as logical rather than arithmetic.
|
||||
bool UseLogicalShr = true;
|
||||
|
||||
// If true, then the lexer and expression parser will support %neg(),
|
||||
// %hi(), and similar unary operators.
|
||||
bool HasMipsExpressions = false;
|
||||
|
||||
// If true, use Motorola-style integers in Assembly (ex. $0ac).
|
||||
bool UseMotorolaIntegers = false;
|
||||
|
||||
@ -723,7 +719,6 @@ public:
|
||||
|
||||
bool shouldUseLogicalShr() const { return UseLogicalShr; }
|
||||
|
||||
bool hasMipsExpressions() const { return HasMipsExpressions; }
|
||||
bool shouldUseMotorolaIntegers() const { return UseMotorolaIntegers; }
|
||||
};
|
||||
|
||||
|
@ -52,14 +52,6 @@ public:
|
||||
Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
|
||||
Less, LessEqual, LessLess, LessGreater,
|
||||
Greater, GreaterEqual, GreaterGreater, At, MinusGreater,
|
||||
|
||||
// MIPS unary expression operators such as %neg.
|
||||
PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi,
|
||||
PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo,
|
||||
PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi,
|
||||
PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi,
|
||||
PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi,
|
||||
PercentTprel_Lo
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -524,12 +524,6 @@ public:
|
||||
/// output streamer, if the target does not emit them immediately.
|
||||
virtual void flushPendingInstructions(MCStreamer &Out) {}
|
||||
|
||||
virtual const MCExpr *createTargetUnaryExpr(const MCExpr *E,
|
||||
AsmToken::TokenKind OperatorToken,
|
||||
MCContext &Ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// For any initialization at the beginning of parsing.
|
||||
virtual void onBeginOfFile() {}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -49,7 +49,6 @@ MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
|
||||
SupportsDebugInformation = true;
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
DwarfRegNumForCFI = true;
|
||||
HasMipsExpressions = true;
|
||||
}
|
||||
|
||||
void MipsCOFFMCAsmInfo::anchor() {}
|
||||
|
@ -16,13 +16,10 @@
|
||||
# 32R2-EL: # fixup A - offset: 0, value: %lo(foo+(%lo(8))), kind: fixup_Mips_LO16
|
||||
# 32R2-EL: lw $4, %lo(12+foo)($4) # encoding: [A,A,0x84,0x8c]
|
||||
# 32R2-EL: # fixup A - offset: 0, value: %lo(12+foo), kind: fixup_Mips_LO16
|
||||
# 32R2-EL: lw $4, %lo(16+foo)($4) # encoding: [A,A,0x84,0x8c]
|
||||
# 32R2-EL: # fixup A - offset: 0, value: %lo(16+foo), kind: fixup_Mips_LO16
|
||||
# 32R2-EL: lw $4, 10($4) # encoding: [0x0a,0x00,0x84,0x8c]
|
||||
# 32R2-EL: lw $4, 15($4) # encoding: [0x0f,0x00,0x84,0x8c]
|
||||
# 32R2-EL: lw $4, 21($4) # encoding: [0x15,0x00,0x84,0x8c]
|
||||
# 32R2-EL: lw $4, 28($4) # encoding: [0x1c,0x00,0x84,0x8c]
|
||||
# 32R2-EL: lw $4, 6($4) # encoding: [0x06,0x00,0x84,0x8c]
|
||||
# 32R2-EL: .space 64
|
||||
|
||||
# MM-32R2-EL: .globl foo
|
||||
@ -37,13 +34,10 @@
|
||||
# MM-32R2-EL: # fixup A - offset: 0, value: %lo(foo+(%lo(8))), kind: fixup_MICROMIPS_LO16
|
||||
# MM-32R2-EL: lw $4, %lo(12+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
|
||||
# MM-32R2-EL: # fixup A - offset: 0, value: %lo(12+foo), kind: fixup_MICROMIPS_LO16
|
||||
# MM-32R2-EL: lw $4, %lo(16+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
|
||||
# MM-32R2-EL: # fixup A - offset: 0, value: %lo(16+foo), kind: fixup_MICROMIPS_LO16
|
||||
# MM-32R2-EL: lw $4, 10($4) # encoding: [0x84,0xfc,0x0a,0x00]
|
||||
# MM-32R2-EL: lw $4, 15($4) # encoding: [0x84,0xfc,0x0f,0x00]
|
||||
# MM-32R2-EL: lw $4, 21($4) # encoding: [0x84,0xfc,0x15,0x00]
|
||||
# MM-32R2-EL: lw $4, 28($4) # encoding: [0x84,0xfc,0x1c,0x00]
|
||||
# MM-32R2-EL: lw $4, 6($4) # encoding: [0x84,0xfc,0x06,0x00]
|
||||
# MM-32R2-EL: .space 64
|
||||
|
||||
.globl foo
|
||||
@ -53,11 +47,18 @@ foo:
|
||||
lw $4,((10 + 4) * 4)($4)
|
||||
lw $4,%lo (2 * 4) + foo($4)
|
||||
lw $4,%lo((3 * 4) + foo)($4)
|
||||
lw $4,(((%lo ((4 * 4) + foo))))($4)
|
||||
lw $4, (((1+2)+3)+4)($4)
|
||||
lw $4, ((((1+2)+3)+4)+5)($4)
|
||||
lw $4, (((((1+2)+3)+4)+5)+6)($4)
|
||||
lw $4, ((((((1+2)+3)+4)+5)+6)+7)($4)
|
||||
lw $4, (%lo((1+2)+65536)+3)($4)
|
||||
.space 64
|
||||
.end foo
|
||||
|
||||
.ifdef ERR
|
||||
# ERR: [[#@LINE+2]]:28: error: expected ')'
|
||||
# ERR: [[#@LINE+1]]:28: error: unexpected token in argument list
|
||||
lw $4, (%lo((1+2)+65536)+3)($4)
|
||||
# ERR: [[#@LINE+2]]:13: error: unexpected token in expression
|
||||
# ERR: [[#@LINE+1]]:13: error: unexpected token in argument list
|
||||
lw $4,(((%lo ((4 * 4) + foo))))($4)
|
||||
.endif
|
||||
|
@ -14,12 +14,12 @@
|
||||
subu $4, $a4, $a4 # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, $4, %hi(end) # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, $4, end + 4 # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, $4, end # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, $4, sp # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, $4, end + 4 # O32: [[@LINE]]:{{[0-9]+}}: error: unknown token in expression
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression
|
||||
subu $4, $4, end # O32: [[@LINE]]:{{[0-9]+}}: error: unknown token in expression
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression
|
||||
subu $4, $4, sp # O32: [[@LINE]]:{{[0-9]+}}: error: unknown token in expression
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression
|
||||
|
||||
subu $4, %lo($start) # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
@ -28,11 +28,11 @@
|
||||
subu $4, $a4 # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, %hi(end) # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, end + 4 # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, end # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, sp # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
|
||||
subu $4, end + 4 # O32: [[@LINE]]:{{[0-9]+}}: error: unknown token in expression
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression
|
||||
subu $4, end # O32: [[@LINE]]:{{[0-9]+}}: error: unknown token in expression
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression
|
||||
subu $4, sp # O32: [[@LINE]]:{{[0-9]+}}: error: unknown token in expression
|
||||
# N64: [[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression
|
||||
|
||||
$start:
|
||||
|
Loading…
x
Reference in New Issue
Block a user