diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 4ae21bf28cb7..e5ac72b6c449 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -363,6 +363,10 @@ class MCAsmInfo { // X86_64 ELF. bool RelaxELFRelocations = true; + // If true, then the lexer and expression parser will support %neg(), + // %hi(), and similar unary operators. + bool HasMipsExpressions = false; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -582,6 +586,7 @@ class MCAsmInfo { bool canRelaxRelocations() const { return RelaxELFRelocations; } void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; } + bool hasMipsExpressions() const { return HasMipsExpressions; } }; } diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index 3dd22c93d363..3097a0c9a293 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -55,7 +55,15 @@ class AsmToken { Pipe, PipePipe, Caret, Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, Less, LessEqual, LessLess, LessGreater, - Greater, GreaterEqual, GreaterGreater, At + Greater, GreaterEqual, GreaterGreater, At, + + // 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: diff --git a/include/llvm/MC/MCParser/MCTargetAsmParser.h b/include/llvm/MC/MCParser/MCTargetAsmParser.h index 08a84a8b9c9e..b2f7b8ee5a87 100644 --- a/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -228,6 +228,12 @@ class MCTargetAsmParser : public MCAsmParserExtension { /// Ensure that all previously parsed instructions have been emitted to the /// 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; + } }; } // End llvm namespace diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index 7037bb1d5fab..be6e84460ea4 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/MemoryBuffer.h" @@ -600,7 +601,46 @@ AsmToken AsmLexer::LexToken() { return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); } return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1)); - case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); + case '%': + if (MAI.hasMipsExpressions()) { + AsmToken::TokenKind Operator; + unsigned OperatorLength; + + std::tie(Operator, OperatorLength) = + StringSwitch>( + 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; return LexSlash(); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 6d3240a3e11a..7a6d5dbd2d32 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -1064,6 +1064,43 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { return true; Res = MCUnaryExpr::createNot(Res, getContext()); 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 (Lexer.isNot(AsmToken::RParen)) + return TokError("expected ')'"); + Lex(); // Eat the operator. + Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx); + return !Res; } } diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 0291ef929e2c..e3f0d16d6609 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -252,9 +252,6 @@ class MipsAsmParser : public MCTargetAsmParser { bool reportParseError(SMLoc Loc, Twine ErrorMsg); bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); - bool parseRelocOperand(const MCExpr *&Res); - - const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); bool isEvaluated(const MCExpr *Expr); bool parseSetMips0Directive(); @@ -552,6 +549,64 @@ class MipsAsmParser : public MCTargetAsmParser { void warnIfNoMacro(SMLoc Loc); 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); + } + } }; } @@ -4187,9 +4242,6 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { DEBUG(dbgs() << ".. Generic Parser\n"); switch (getLexer().getKind()) { - default: - Error(Parser.getTok().getLoc(), "unexpected token in operand"); - return true; case AsmToken::Dollar: { // Parse the register. SMLoc S = Parser.getTok().getLoc(); @@ -4216,72 +4268,23 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); return false; } - // Else drop to expression parsing. - case AsmToken::LParen: - case AsmToken::Minus: - case AsmToken::Plus: - case AsmToken::Integer: - case AsmToken::Tilde: - case AsmToken::String: { - DEBUG(dbgs() << ".. generic integer\n"); - OperandMatchResultTy ResTy = parseImm(Operands); - return ResTy != MatchOperand_Success; - } - case AsmToken::Percent: { - // It is a symbol reference or constant expression. - const MCExpr *IdVal; + default: { + DEBUG(dbgs() << ".. generic integer expression\n"); + + const MCExpr *Expr; SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. - if (parseRelocOperand(IdVal)) + if (getParser().parseExpression(Expr)) return true; SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); + Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this)); return false; - } // case AsmToken::Percent + } } // switch(getLexer().getKind()) return true; } -const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, - StringRef RelocStr) { - if (RelocStr == "hi(%neg(%gp_rel") - return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext()); - else if (RelocStr == "lo(%neg(%gp_rel") - return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext()); - - MipsMCExpr::MipsExprKind Kind = - StringSwitch(RelocStr) - .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); - - assert(Kind != MipsMCExpr::MEK_None); - return MipsMCExpr::create(Kind, Expr, getContext()); -} - bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { switch (Expr->getKind()) { @@ -4303,49 +4306,6 @@ bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { return false; } -bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat the % token. - const AsmToken &Tok = Parser.getTok(); // Get next token, operation. - if (Tok.isNot(AsmToken::Identifier)) - return true; - - std::string Str = Tok.getIdentifier(); - - Parser.Lex(); // Eat the identifier. - // Now make an expression from the rest of the operand. - const MCExpr *IdVal; - SMLoc EndLoc; - - if (getLexer().getKind() == AsmToken::LParen) { - while (1) { - Parser.Lex(); // Eat the '(' token. - if (getLexer().getKind() == AsmToken::Percent) { - Parser.Lex(); // Eat the % token. - const AsmToken &nextTok = Parser.getTok(); - if (nextTok.isNot(AsmToken::Identifier)) - return true; - Str += "(%"; - Str += nextTok.getIdentifier(); - Parser.Lex(); // Eat the identifier. - if (getLexer().getKind() != AsmToken::LParen) - return true; - } else - break; - } - if (getParser().parseParenExpression(IdVal, EndLoc)) - return true; - - while (getLexer().getKind() == AsmToken::RParen) - Parser.Lex(); // Eat the ')' token. - - } else - return true; // Parenthesis must follow the relocation operand. - - Res = evaluateRelocExpr(IdVal, Str); - return false; -} - bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { SmallVector, 1> Operands; @@ -4373,35 +4333,11 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, } bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { - MCAsmParser &Parser = getParser(); SMLoc S; - bool Result = true; - unsigned NumOfLParen = 0; - - while (getLexer().getKind() == AsmToken::LParen) { - Parser.Lex(); - ++NumOfLParen; - } - switch (getLexer().getKind()) { - default: - return true; - case AsmToken::Identifier: - case AsmToken::LParen: - case AsmToken::Integer: - case AsmToken::Minus: - case AsmToken::Plus: - if (isParenExpr) - Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S); - else - Result = (getParser().parseExpression(Res)); - while (getLexer().getKind() == AsmToken::RParen) - Parser.Lex(); - break; - case AsmToken::Percent: - Result = parseRelocOperand(Res); - } - return Result; + if (isParenExpr) + return getParser().parseParenExprOfDepth(0, Res, S); + return getParser().parseExpression(Res); } MipsAsmParser::OperandMatchResultTy @@ -4631,31 +4567,6 @@ MipsAsmParser::parseAnyRegister(OperandVector &Operands) { return ResTy; } -MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseImm(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - switch (getLexer().getKind()) { - default: - return MatchOperand_NoMatch; - case AsmToken::LParen: - case AsmToken::Minus: - case AsmToken::Plus: - case AsmToken::Integer: - case AsmToken::Tilde: - case AsmToken::String: - break; - } - - const MCExpr *IdVal; - SMLoc S = Parser.getTok().getLoc(); - if (getParser().parseExpression(IdVal)) - return MatchOperand_ParseFail; - - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); - return MatchOperand_Success; -} - MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseJumpTarget(OperandVector &Operands) { MCAsmParser &Parser = getParser(); @@ -4663,16 +4574,12 @@ MipsAsmParser::parseJumpTarget(OperandVector &Operands) { SMLoc S = getLexer().getLoc(); - // Integers and expressions are acceptable - OperandMatchResultTy ResTy = parseImm(Operands); - if (ResTy != MatchOperand_NoMatch) - return ResTy; - // Registers are a valid target and have priority over symbols. - ResTy = parseAnyRegister(Operands); + OperandMatchResultTy ResTy = parseAnyRegister(Operands); if (ResTy != MatchOperand_NoMatch) return ResTy; + // Integers and expressions are acceptable const MCExpr *Expr = nullptr; if (Parser.parseExpression(Expr)) { // We have no way of knowing if a symbol was consumed so we must ParseFail diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 550c2894695c..3ee0cd9c7ec6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -62,6 +62,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case FK_GPRel_4: case FK_Data_4: case FK_Data_8: + case Mips::fixup_Mips_SUB: + case Mips::fixup_MICROMIPS_SUB: break; case Mips::fixup_Mips_PC16: // The displacement is then divided by 4 to give us an 18 bit @@ -361,7 +363,9 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_MICROMIPS_TLS_DTPREL_HI16", 0, 16, 0 }, { "fixup_MICROMIPS_TLS_DTPREL_LO16", 0, 16, 0 }, { "fixup_MICROMIPS_TLS_TPREL_HI16", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 } + { "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 }, + { "fixup_Mips_SUB", 0, 64, 0 }, + { "fixup_MICROMIPS_SUB", 0, 64, 0 } }; const static MCFixupKindInfo BigEndianInfos[Mips::NumTargetFixupKinds] = { @@ -430,7 +434,9 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_MICROMIPS_TLS_DTPREL_HI16", 16, 16, 0 }, { "fixup_MICROMIPS_TLS_DTPREL_LO16", 16, 16, 0 }, { "fixup_MICROMIPS_TLS_TPREL_HI16", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 } + { "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 }, + { "fixup_Mips_SUB", 0, 64, 0 }, + { "fixup_MICROMIPS_SUB", 0, 64, 0 } }; if (Kind < FirstTargetFixupKind) diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 20c5f3691d23..99ba18c972df 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -329,6 +329,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_MIPS_HIGHER; case Mips::fixup_Mips_HIGHEST: return ELF::R_MIPS_HIGHEST; + case Mips::fixup_Mips_SUB: + return ELF::R_MIPS_SUB; case Mips::fixup_Mips_GOT_HI16: return ELF::R_MIPS_GOT_HI16; case Mips::fixup_Mips_GOT_LO16: @@ -365,6 +367,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_MICROMIPS_TLS_TPREL_HI16; case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: return ELF::R_MICROMIPS_TLS_TPREL_LO16; + case Mips::fixup_MICROMIPS_SUB: + return ELF::R_MICROMIPS_SUB; } llvm_unreachable("invalid fixup kind!"); diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index b4d8e9494650..149296212eca 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -209,6 +209,10 @@ namespace Mips { // resulting in - R_MICROMIPS_TLS_TPREL_LO16 fixup_MICROMIPS_TLS_TPREL_LO16, + // resulting in - R_MIPS_SUB/R_MICROMIPS_SUB + fixup_Mips_SUB, + fixup_MICROMIPS_SUB, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 1ce8f07092b1..2c01f919befc 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -49,6 +49,7 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { SupportsDebugInformation = true; ExceptionsType = ExceptionHandling::DwarfCFI; DwarfRegNumForCFI = true; + HasMipsExpressions = true; // Enable IAS by default for O32. if (TheTriple.getArch() == Triple::mips || diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index c15c8a929bf1..4cc55f86a993 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -637,7 +637,6 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, Mips::Fixups FixupKind = Mips::Fixups(0); switch (MipsExpr->getKind()) { - case MipsMCExpr::MEK_NEG: case MipsMCExpr::MEK_None: case MipsMCExpr::MEK_Special: llvm_unreachable("Unhandled fixup kind!"); @@ -735,6 +734,10 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 : Mips::fixup_Mips_TPREL_LO; break; + case MipsMCExpr::MEK_NEG: + FixupKind = + isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB; + break; } Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); return 0; diff --git a/test/MC/Mips/expr1.s b/test/MC/Mips/expr1.s index a6ecff5d212c..a1897126abeb 100644 --- a/test/MC/Mips/expr1.s +++ b/test/MC/Mips/expr1.s @@ -10,17 +10,20 @@ # 32R2-EL: lw $4, %lo(foo)($4) # encoding: [A,A,0x84,0x8c] # 32R2-EL: # fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16 # 32R2-EL: lw $4, 56($4) # encoding: [0x38,0x00,0x84,0x8c] -# 32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [A,A,0x84,0x8c] -# 32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16 -# 32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [A,A,0x84,0x8c] -# 32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16 -# 32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [A,A,0x84,0x8c] -# 32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16 +# 32R2-EL: lui $1, %hi(foo+(%lo(8))) # encoding: [A,A,0x01,0x3c] +# 32R2-EL: # fixup A - offset: 0, value: %hi(foo+(%lo(8))), kind: fixup_Mips_HI16 +# 32R2-EL: addu $1, $1, $4 # encoding: [0x21,0x08,0x24,0x00] +# 32R2-EL: lw $4, %lo(foo+(%lo(8)))($1) # encoding: [A,A,0x24,0x8c] +# 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, %lo(65542)($4) # encoding: [0x06,0x00,0x84,0x8c] +# 32R2-EL: lw $4, 6($4) # encoding: [0x06,0x00,0x84,0x8c] # 32R2-EL: .space 64 # MM-32R2-EL: .text @@ -29,17 +32,20 @@ # MM-32R2-EL: lw $4, %lo(foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00] # MM-32R2-EL: # fixup A - offset: 0, value: %lo(foo), kind: fixup_MICROMIPS_LO16 # MM-32R2-EL: lw $4, 56($4) # encoding: [0x84,0xfc,0x38,0x00] -# MM-32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00] -# MM-32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16 -# MM-32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00] -# MM-32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16 -# MM-32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00] -# MM-32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16 +# MM-32R2-EL: lui $1, %hi(foo+(%lo(8))) # encoding: [0xa1'A',0x41'A',0x00,0x00] +# MM-32R2-EL: # fixup A - offset: 0, value: %hi(foo+(%lo(8))), kind: fixup_MICROMIPS_HI16 +# MM-32R2-EL: addu $1, $1, $4 # encoding: [0x81,0x00,0x50,0x09] +# MM-32R2-EL: lw $4, %lo(foo+(%lo(8)))($1) # encoding: [0x81'A',0xfc'A',0x00,0x00] +# 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, %lo(65542)($4) # encoding: [0x84,0xfc,0x06,0x00] +# MM-32R2-EL: lw $4, 6($4) # encoding: [0x84,0xfc,0x06,0x00] # MM-32R2-EL: .space 64 .globl foo @@ -48,8 +54,8 @@ foo: lw $4,%lo(foo)($4) lw $4,((10 + 4) * 4)($4) lw $4,%lo (2 * 4) + foo($4) - lw $4,%lo((2 * 4) + foo)($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) diff --git a/test/MC/Mips/relocation.s b/test/MC/Mips/relocation.s index 42a015dbdb95..a73d9530f1c5 100644 --- a/test/MC/Mips/relocation.s +++ b/test/MC/Mips/relocation.s @@ -153,7 +153,10 @@ baz: .long foo // RELOC: R_MIPS_32 foo // ENCLE: addiu $2, $3, %got_lo(foo) # encoding: [A,A,0x62,0x24] // FIXUP: # fixup A - offset: 0, value: %got_lo(foo), kind: fixup_Mips_GOT_LO16 -// addiu $2, $3, %neg(foo) // FIXME: R_MIPS_SUB foo + // It turns out that %neg() isn't actually usable for anything. It's + // not supported in .quad and it doesn't make sense to use a 64-bit + // reloc on a 32-bit instruction. + // .quad %neg(foo) // ?????: R_MIPS_SUB foo // ?????: R_MIPS_INSERT_A // ?????: R_MIPS_INSERT_B // ?????: R_MIPS_DELETE diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 01853a5c84ee..81ee3d83d559 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -314,6 +314,78 @@ static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, case AsmToken::Slash: OS << "Slash"; 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.