diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h --- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -376,6 +376,14 @@ virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + /// tryParseRegister - parse one register if possible + /// + /// Check whether a register specification can be parsed at the current + /// location, without failing the entire parse if it can't. Must not consume + /// tokens if the parse fails. + virtual OperandMatchResultTy + tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + /// ParseInstruction - Parse one assembly instruction. /// /// The parser is positioned following the instruction name. The target diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -260,6 +260,8 @@ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseDirective(AsmToken DirectiveID) override; unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; @@ -2245,10 +2247,16 @@ bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + return tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success; +} + +OperandMatchResultTy AArch64AsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { StartLoc = getLoc(); auto Res = tryParseScalarRegister(RegNo); EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1); - return Res != MatchOperand_Success; + return Res; } // Matches a register name or register alias previously defined by '.req' diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1062,17 +1062,20 @@ bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1); - bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, - unsigned& RegNum, unsigned& RegWidth); - unsigned ParseRegularReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth); - unsigned ParseSpecialReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth); - unsigned ParseRegList(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth); + bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + bool RestoreOnFailure = false); + bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl &Tokens); + unsigned ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, + SmallVectorImpl &Tokens); + unsigned ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, + SmallVectorImpl &Tokens); + unsigned ParseRegList(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, SmallVectorImpl &Tokens); bool ParseRegRange(unsigned& Num, unsigned& Width); unsigned getRegularReg(RegisterKind RegKind, unsigned RegNum, @@ -1226,8 +1229,12 @@ bool isForcedSDWA() const { return ForcedSDWA; } ArrayRef getMatchedVariants() const; - std::unique_ptr parseRegister(); + std::unique_ptr parseRegister(bool RestoreOnFailure = false); + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, + bool RestoreOnFailure); bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; unsigned checkTargetMatchPredicate(MCInst &Inst) override; unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; @@ -1980,7 +1987,7 @@ } bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) { + SMLoc &EndLoc, bool RestoreOnFailure) { auto R = parseRegister(); if (!R) return true; assert(R->isReg()); @@ -1990,6 +1997,25 @@ return false; } +bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) { + return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false); +} + +OperandMatchResultTy AMDGPUAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { + bool Result = + ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true); + bool PendingErrors = getParser().hasPendingError(); + getParser().clearPendingErrors(); + if (PendingErrors) + return MatchOperand_ParseFail; + if (Result) + return MatchOperand_NoMatch; + return MatchOperand_Success; +} + bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth, RegisterKind RegKind, unsigned Reg1) { switch (RegKind) { @@ -2166,31 +2192,31 @@ return true; } -unsigned -AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth) { +unsigned AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl &Tokens) { assert(isToken(AsmToken::Identifier)); unsigned Reg = getSpecialRegForName(getTokenStr()); if (Reg) { RegNum = 0; RegWidth = 1; RegKind = IS_SPECIAL; + Tokens.push_back(getToken()); lex(); // skip register name } return Reg; } -unsigned -AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth) { +unsigned AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl &Tokens) { assert(isToken(AsmToken::Identifier)); StringRef RegName = getTokenStr(); const RegInfo *RI = getRegularRegInfo(RegName); if (!RI) return AMDGPU::NoRegister; + Tokens.push_back(getToken()); lex(); // skip register name RegKind = RI->Kind; @@ -2209,10 +2235,9 @@ return getRegularReg(RegKind, RegNum, RegWidth); } -unsigned -AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, - unsigned &RegNum, - unsigned &RegWidth) { +unsigned AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, unsigned &RegNum, + unsigned &RegWidth, + SmallVectorImpl &Tokens) { unsigned Reg = AMDGPU::NoRegister; if (!trySkipToken(AsmToken::LBrac)) @@ -2229,7 +2254,8 @@ RegisterKind NextRegKind; unsigned NextReg, NextRegNum, NextRegWidth; - if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth)) + if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth, + Tokens)) return AMDGPU::NoRegister; if (NextRegWidth != 1) return AMDGPU::NoRegister; @@ -2248,24 +2274,40 @@ return Reg; } -bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, - unsigned &Reg, - unsigned &RegNum, - unsigned &RegWidth) { +bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + SmallVectorImpl &Tokens) { Reg = AMDGPU::NoRegister; if (isToken(AsmToken::Identifier)) { - Reg = ParseSpecialReg(RegKind, RegNum, RegWidth); + Reg = ParseSpecialReg(RegKind, RegNum, RegWidth, Tokens); if (Reg == AMDGPU::NoRegister) - Reg = ParseRegularReg(RegKind, RegNum, RegWidth); + Reg = ParseRegularReg(RegKind, RegNum, RegWidth, Tokens); } else { - Reg = ParseRegList(RegKind, RegNum, RegWidth); + Reg = ParseRegList(RegKind, RegNum, RegWidth, Tokens); } const MCRegisterInfo *TRI = getContext().getRegisterInfo(); return Reg != AMDGPU::NoRegister && subtargetHasRegister(*TRI, Reg); } +bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, + unsigned &RegNum, unsigned &RegWidth, + bool RestoreOnFailure) { + Reg = AMDGPU::NoRegister; + + SmallVector Tokens; + if (ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, Tokens)) { + if (RestoreOnFailure) { + while (!Tokens.empty()) { + getLexer().UnLex(Tokens.pop_back_val()); + } + } + return true; + } + return false; +} + Optional AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) { switch (RegKind) { @@ -2314,7 +2356,8 @@ return true; } -std::unique_ptr AMDGPUAsmParser::parseRegister() { +std::unique_ptr +AMDGPUAsmParser::parseRegister(bool RestoreOnFailure) { const auto &Tok = Parser.getTok(); SMLoc StartLoc = Tok.getLoc(); SMLoc EndLoc = Tok.getEndLoc(); diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -628,6 +628,8 @@ // Implementation of the MCTargetAsmParser interface: bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; bool ParseDirective(AsmToken DirectiveID) override; @@ -3885,6 +3887,14 @@ return (RegNo == (unsigned)-1); } +OperandMatchResultTy ARMAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { + if (ParseRegister(RegNo, StartLoc, EndLoc)) + return MatchOperand_NoMatch; + return MatchOperand_Success; +} + /// Try to parse a register name. The token must be an Identifier when called, /// and if it is a register name the token is eaten and the register number is /// returned. Otherwise return -1. diff --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp --- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp +++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp @@ -53,6 +53,8 @@ bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -64,7 +66,7 @@ bool parseOperand(OperandVector &Operands); int parseRegisterName(unsigned (*matchFn)(StringRef)); int parseRegisterName(); - int parseRegister(); + int parseRegister(bool RestoreOnFailure = false); bool tryParseRegisterOperand(OperandVector &Operands); bool tryParseExpression(OperandVector &Operands); bool tryParseRelocExpression(OperandVector &Operands); @@ -359,19 +361,25 @@ return RegNum; } -int AVRAsmParser::parseRegister() { +int AVRAsmParser::parseRegister(bool RestoreOnFailure) { int RegNum = AVR::NoRegister; if (Parser.getTok().is(AsmToken::Identifier)) { // Check for register pair syntax if (Parser.getLexer().peekTok().is(AsmToken::Colon)) { + AsmToken HighTok = Parser.getTok(); Parser.Lex(); + AsmToken ColonTok = Parser.getTok(); Parser.Lex(); // Eat high (odd) register and colon if (Parser.getTok().is(AsmToken::Identifier)) { // Convert lower (even) register to DREG RegNum = toDREG(parseRegisterName()); } + if (RegNum == AVR::NoRegister && RestoreOnFailure) { + getLexer().UnLex(std::move(ColonTok)); + getLexer().UnLex(std::move(HighTok)); + } } else { RegNum = parseRegisterName(); } @@ -580,12 +588,24 @@ bool AVRAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { StartLoc = Parser.getTok().getLoc(); - RegNo = parseRegister(); + RegNo = parseRegister(/*RestoreOnFailure=*/false); EndLoc = Parser.getTok().getLoc(); return (RegNo == AVR::NoRegister); } +OperandMatchResultTy AVRAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { + StartLoc = Parser.getTok().getLoc(); + RegNo = parseRegister(/*RestoreOnFailure=*/true); + EndLoc = Parser.getTok().getLoc(); + + if (RegNo == AVR::NoRegister) + return MatchOperand_NoMatch; + return MatchOperand_Success; +} + void AVRAsmParser::eatComma() { if (getLexer().is(AsmToken::Comma)) { Parser.Lex(); diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp --- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp +++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp @@ -39,6 +39,8 @@ bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -322,6 +324,14 @@ bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + return Error(StartLoc, "invalid register name"); + return false; +} + +OperandMatchResultTy BPFAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); @@ -330,10 +340,10 @@ if (!MatchRegisterName(Name)) { getParser().Lex(); // Eat identifier token. - return false; + return MatchOperand_Success; } - return Error(StartLoc, "invalid register name"); + return MatchOperand_NoMatch; } OperandMatchResultTy diff --git a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp --- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp +++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp @@ -116,6 +116,8 @@ bool ParseDirectiveFalign(unsigned Size, SMLoc L); bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseDirectiveSubsection(SMLoc L); bool ParseDirectiveComm(bool IsLocal, SMLoc L); bool RegisterMatchesArch(unsigned MatchNum) const; @@ -964,6 +966,12 @@ bool HexagonAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + return tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success; +} + +OperandMatchResultTy HexagonAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { MCAsmLexer &Lexer = getLexer(); StartLoc = getLexer().getLoc(); SmallVector Lookahead; @@ -998,8 +1006,8 @@ RegNo = DotReg; EndLoc = Lexer.getLoc(); if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc)) - return true; - return false; + return MatchOperand_NoMatch; + return MatchOperand_Success; } else { RegNo = DotReg; size_t First = RawString.find('.'); @@ -1007,28 +1015,26 @@ Lexer.UnLex(AsmToken(AsmToken::Identifier, DotString)); EndLoc = Lexer.getLoc(); if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc)) - return true; - return false; + return MatchOperand_NoMatch; + return MatchOperand_Success; } } std::pair ColonSplit = StringRef(FullString).split(':'); unsigned ColonReg = matchRegister(ColonSplit.first.lower()); if (ColonReg != Hexagon::NoRegister && RegisterMatchesArch(DotReg)) { do { - Lexer.UnLex(Lookahead.back()); - Lookahead.pop_back(); - } while (!Lookahead.empty () && !Lexer.is(AsmToken::Colon)); + Lexer.UnLex(Lookahead.pop_back_val()); + } while (!Lookahead.empty() && !Lexer.is(AsmToken::Colon)); RegNo = ColonReg; EndLoc = Lexer.getLoc(); if (handleNoncontigiousRegister(!NeededWorkaround, StartLoc)) - return true; - return false; + return MatchOperand_NoMatch; + return MatchOperand_Success; } while (!Lookahead.empty()) { - Lexer.UnLex(Lookahead.back()); - Lookahead.pop_back(); + Lexer.UnLex(Lookahead.pop_back_val()); } - return true; + return MatchOperand_NoMatch; } bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) { diff --git a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp --- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp +++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp @@ -47,7 +47,7 @@ class LanaiAsmParser : public MCTargetAsmParser { // Parse operands - std::unique_ptr parseRegister(); + std::unique_ptr parseRegister(bool RestoreOnFailure = false); std::unique_ptr parseImmediate(); @@ -67,6 +67,8 @@ SMLoc NameLoc, OperandVector &Operands) override; bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -687,21 +689,30 @@ // backwards compatible with GCC and the different ways inline assembly is // handled. // TODO: see if there isn't a better way to do this. -std::unique_ptr LanaiAsmParser::parseRegister() { +std::unique_ptr +LanaiAsmParser::parseRegister(bool RestoreOnFailure) { SMLoc Start = Parser.getTok().getLoc(); SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Optional PercentTok; unsigned RegNum; // Eat the '%'. - if (Lexer.getKind() == AsmToken::Percent) + if (Lexer.getKind() == AsmToken::Percent) { + PercentTok = Parser.getTok(); Parser.Lex(); + } if (Lexer.getKind() == AsmToken::Identifier) { RegNum = MatchRegisterName(Lexer.getTok().getIdentifier()); - if (RegNum == 0) + if (RegNum == 0) { + if (PercentTok.hasValue()) + Lexer.UnLex(PercentTok.getValue()); return nullptr; + } Parser.Lex(); // Eat identifier token return LanaiOperand::createReg(RegNum, Start, End); } + if (PercentTok.hasValue()) + Lexer.UnLex(PercentTok.getValue()); return nullptr; } @@ -710,12 +721,25 @@ const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); - std::unique_ptr Op = parseRegister(); + std::unique_ptr Op = parseRegister(/*RestoreOnFailure=*/false); if (Op != nullptr) RegNum = Op->getReg(); return (Op == nullptr); } +OperandMatchResultTy LanaiAsmParser::tryParseRegister(unsigned &RegNum, + SMLoc &StartLoc, + SMLoc &EndLoc) { + const AsmToken &Tok = getParser().getTok(); + StartLoc = Tok.getLoc(); + EndLoc = Tok.getEndLoc(); + std::unique_ptr Op = parseRegister(/*RestoreOnFailure=*/true); + if (Op == nullptr) + return MatchOperand_NoMatch; + RegNum = Op->getReg(); + return MatchOperand_Success; +} + std::unique_ptr LanaiAsmParser::parseIdentifier() { SMLoc Start = Parser.getTok().getLoc(); SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); diff --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp --- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp +++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp @@ -46,6 +46,8 @@ bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -288,13 +290,28 @@ bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + switch (tryParseRegister(RegNo, StartLoc, EndLoc)) { + case MatchOperand_ParseFail: + return Error(StartLoc, "invalid register name"); + case MatchOperand_Success: + return false; + case MatchOperand_NoMatch: + return true; + } + + llvm_unreachable("unknown match result type"); +} + +OperandMatchResultTy MSP430AsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { if (getLexer().getKind() == AsmToken::Identifier) { auto Name = getLexer().getTok().getIdentifier().lower(); RegNo = MatchRegisterName(Name); if (RegNo == MSP430::NoRegister) { RegNo = MatchRegisterAltName(Name); if (RegNo == MSP430::NoRegister) - return true; + return MatchOperand_NoMatch; } AsmToken const &T = getParser().getTok(); @@ -302,10 +319,10 @@ EndLoc = T.getEndLoc(); getLexer().Lex(); // eat register token - return false; + return MatchOperand_Success; } - return Error(StartLoc, "invalid register name"); + return MatchOperand_ParseFail; } bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info, diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -179,6 +179,8 @@ /// Parse a register as used in CFI directives bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool parseParenSuffix(StringRef Name, OperandVector &Operands); @@ -6202,6 +6204,12 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + return tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success; +} + +OperandMatchResultTy MipsAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { SmallVector, 1> Operands; OperandMatchResultTy ResTy = parseAnyRegister(Operands); if (ResTy == MatchOperand_Success) { @@ -6219,11 +6227,12 @@ RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); } - return (RegNo == (unsigned)-1); + return (RegNo == (unsigned)-1) ? MatchOperand_NoMatch + : MatchOperand_Success; } assert(Operands.size() == 0); - return (RegNo == (unsigned)-1); + return (RegNo == (unsigned)-1) ? MatchOperand_NoMatch : MatchOperand_Success; } bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -109,6 +109,8 @@ bool MatchRegisterName(unsigned &RegNo, int64_t &IntVal); bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; const MCExpr *ExtractModifierFromExpr(const MCExpr *E, PPCMCExpr::VariantKind &Variant); @@ -1221,14 +1223,22 @@ bool PPCAsmParser:: ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + return TokError("invalid register name"); + return false; +} + +OperandMatchResultTy PPCAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); RegNo = 0; int64_t IntVal; if (MatchRegisterName(RegNo, IntVal)) - return TokError("invalid register name"); - return false; + return MatchOperand_NoMatch; + return MatchOperand_Success; } /// Extract \code @l/@ha \endcode modifier from expression. Recursively scan diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -74,6 +74,8 @@ bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; @@ -1025,17 +1027,25 @@ bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + return Error(StartLoc, "invalid register name"); + return false; +} + +OperandMatchResultTy RISCVAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); RegNo = 0; StringRef Name = getLexer().getTok().getIdentifier(); - if (matchRegisterNameHelper(isRV32E(), (Register&)RegNo, Name)) - return Error(StartLoc, "invalid register name"); + if (matchRegisterNameHelper(isRV32E(), (Register &)RegNo, Name)) + return MatchOperand_NoMatch; getParser().Lex(); // Eat identifier token. - return false; + return MatchOperand_Success; } OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands, diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -68,6 +68,8 @@ uint64_t &ErrorInfo, bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; bool ParseDirective(AsmToken DirectiveID) override; @@ -630,20 +632,29 @@ bool SparcAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + return Error(StartLoc, "invalid register name"); + return false; +} + +OperandMatchResultTy SparcAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = Parser.getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); RegNo = 0; if (getLexer().getKind() != AsmToken::Percent) - return false; + return MatchOperand_Success; Parser.Lex(); unsigned regKind = SparcOperand::rk_None; if (matchRegisterName(Tok, RegNo, regKind)) { Parser.Lex(); - return false; + return MatchOperand_Success; } - return Error(StartLoc, "invalid register name"); + getLexer().UnLex(Tok); + return MatchOperand_NoMatch; } static void applyMnemonicAliases(StringRef &Mnemonic, diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -405,7 +405,7 @@ SMLoc StartLoc, EndLoc; }; - bool parseRegister(Register &Reg); + bool parseRegister(Register &Reg, bool RestoreOnFailure = false); bool parseRegister(Register &Reg, RegisterGroup Group, const unsigned *Regs, bool IsAddress = false); @@ -449,6 +449,10 @@ // Override MCTargetAsmParser. bool ParseDirective(AsmToken DirectiveID) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, + bool RestoreOnFailure); + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override; bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, @@ -691,27 +695,37 @@ } // Parse one register of the form %. -bool SystemZAsmParser::parseRegister(Register &Reg) { +bool SystemZAsmParser::parseRegister(Register &Reg, bool RestoreOnFailure) { Reg.StartLoc = Parser.getTok().getLoc(); // Eat the % prefix. if (Parser.getTok().isNot(AsmToken::Percent)) return Error(Parser.getTok().getLoc(), "register expected"); + const AsmToken &PercentTok = Parser.getTok(); Parser.Lex(); // Expect a register name. - if (Parser.getTok().isNot(AsmToken::Identifier)) + if (Parser.getTok().isNot(AsmToken::Identifier)) { + if (RestoreOnFailure) + getLexer().UnLex(PercentTok); return Error(Reg.StartLoc, "invalid register"); + } // Check that there's a prefix. StringRef Name = Parser.getTok().getString(); - if (Name.size() < 2) + if (Name.size() < 2) { + if (RestoreOnFailure) + getLexer().UnLex(PercentTok); return Error(Reg.StartLoc, "invalid register"); + } char Prefix = Name[0]; // Treat the rest of the register name as a register number. - if (Name.substr(1).getAsInteger(10, Reg.Num)) + if (Name.substr(1).getAsInteger(10, Reg.Num)) { + if (RestoreOnFailure) + getLexer().UnLex(PercentTok); return Error(Reg.StartLoc, "invalid register"); + } // Look for valid combinations of prefix and number. if (Prefix == 'r' && Reg.Num < 16) @@ -724,8 +738,11 @@ Reg.Group = RegAR; else if (Prefix == 'c' && Reg.Num < 16) Reg.Group = RegCR; - else + else { + if (RestoreOnFailure) + getLexer().UnLex(PercentTok); return Error(Reg.StartLoc, "invalid register"); + } Reg.EndLoc = Parser.getTok().getLoc(); Parser.Lex(); @@ -1124,9 +1141,9 @@ } bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) { + SMLoc &EndLoc, bool RestoreOnFailure) { Register Reg; - if (parseRegister(Reg)) + if (parseRegister(Reg, RestoreOnFailure)) return true; if (Reg.Group == RegGR) RegNo = SystemZMC::GR64Regs[Reg.Num]; @@ -1143,6 +1160,25 @@ return false; } +bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) { + return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false); +} + +OperandMatchResultTy SystemZAsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { + bool Result = + ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true); + bool PendingErrors = getParser().hasPendingError(); + getParser().clearPendingErrors(); + if (PendingErrors) + return MatchOperand_ParseFail; + if (Result) + return MatchOperand_NoMatch; + return MatchOperand_Success; +} + bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -214,6 +214,11 @@ SMLoc & /*EndLoc*/) override { llvm_unreachable("ParseRegister is not implemented."); } + OperandMatchResultTy tryParseRegister(unsigned & /*RegNo*/, + SMLoc & /*StartLoc*/, + SMLoc & /*EndLoc*/) override { + llvm_unreachable("tryParseRegister is not implemented."); + } bool error(const Twine &Msg, const AsmToken &Tok) { return Parser.Error(Tok.getLoc(), Msg + Tok.getString()); diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -858,6 +858,9 @@ return nullptr; } + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, + bool RestoreOnFailure); + std::unique_ptr DefaultMemSIOperand(SMLoc Loc); std::unique_ptr DefaultMemDIOperand(SMLoc Loc); bool IsSIReg(unsigned Reg); @@ -1023,6 +1026,8 @@ } bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) override; bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; @@ -1129,22 +1134,36 @@ return checkScale(Scale, ErrMsg); } -bool X86AsmParser::ParseRegister(unsigned &RegNo, - SMLoc &StartLoc, SMLoc &EndLoc) { +bool X86AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc, bool RestoreOnFailure) { MCAsmParser &Parser = getParser(); + MCAsmLexer &Lexer = getLexer(); RegNo = 0; + + SmallVector Tokens; + auto OnFailure = [RestoreOnFailure, &Lexer, &Tokens]() { + if (RestoreOnFailure) { + while (!Tokens.empty()) { + Lexer.UnLex(Tokens.pop_back_val()); + } + } + }; + const AsmToken &PercentTok = Parser.getTok(); StartLoc = PercentTok.getLoc(); // If we encounter a %, ignore it. This code handles registers with and // without the prefix, unprefixed registers can occur in cfi directives. - if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) + if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) { + Tokens.push_back(PercentTok); Parser.Lex(); // Eat percent token. + } const AsmToken &Tok = Parser.getTok(); EndLoc = Tok.getEndLoc(); if (Tok.isNot(AsmToken::Identifier)) { + OnFailure(); if (isParsingIntelSyntax()) return true; return Error(StartLoc, "invalid register name", SMRange(StartLoc, EndLoc)); @@ -1173,7 +1192,10 @@ X86II::isX86_64NonExtLowByteReg(RegNo) || X86II::isX86_64ExtendedReg(RegNo)) { StringRef RegName = Tok.getString(); - Parser.Lex(); // Eat register name. + OnFailure(); + if (!RestoreOnFailure) { + Parser.Lex(); // Eat register name. + } return Error(StartLoc, "register %" + RegName + " is only available in 64-bit mode", SMRange(StartLoc, EndLoc)); @@ -1182,17 +1204,21 @@ // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens. if (RegNo == X86::ST0) { + Tokens.push_back(Tok); Parser.Lex(); // Eat 'st' // Check to see if we have '(4)' after %st. - if (getLexer().isNot(AsmToken::LParen)) + if (Lexer.isNot(AsmToken::LParen)) return false; // Lex the paren. - getParser().Lex(); + Tokens.push_back(Parser.getTok()); + Parser.Lex(); const AsmToken &IntTok = Parser.getTok(); - if (IntTok.isNot(AsmToken::Integer)) + if (IntTok.isNot(AsmToken::Integer)) { + OnFailure(); return Error(IntTok.getLoc(), "expected stack index"); + } switch (IntTok.getIntVal()) { case 0: RegNo = X86::ST0; break; case 1: RegNo = X86::ST1; break; @@ -1202,11 +1228,18 @@ case 5: RegNo = X86::ST5; break; case 6: RegNo = X86::ST6; break; case 7: RegNo = X86::ST7; break; - default: return Error(IntTok.getLoc(), "invalid stack index"); + default: + OnFailure(); + return Error(IntTok.getLoc(), "invalid stack index"); } - if (getParser().Lex().isNot(AsmToken::RParen)) + // Lex IntTok + Tokens.push_back(IntTok); + Parser.Lex(); + if (Lexer.isNot(AsmToken::RParen)) { + OnFailure(); return Error(Parser.getTok().getLoc(), "expected ')'"); + } EndLoc = Parser.getTok().getEndLoc(); Parser.Lex(); // Eat ')' @@ -1250,6 +1283,7 @@ } if (RegNo == 0) { + OnFailure(); if (isParsingIntelSyntax()) return true; return Error(StartLoc, "invalid register name", SMRange(StartLoc, EndLoc)); @@ -1259,6 +1293,25 @@ return false; } +bool X86AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) { + return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false); +} + +OperandMatchResultTy X86AsmParser::tryParseRegister(unsigned &RegNo, + SMLoc &StartLoc, + SMLoc &EndLoc) { + bool Result = + ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true); + bool PendingErrors = getParser().hasPendingError(); + getParser().clearPendingErrors(); + if (PendingErrors) + return MatchOperand_ParseFail; + if (Result) + return MatchOperand_NoMatch; + return MatchOperand_Success; +} + std::unique_ptr X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { bool Parse32 = is32BitMode() || Code16GCC; unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);