[llvm] 8d5bf04 - [ms] [llvm-ml] Add support for attempted register parsing
Eric Astor via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 11 07:47:37 PST 2020
Author: Eric Astor
Date: 2020-02-11T10:45:33-05:00
New Revision: 8d5bf0422bc3c8cc7017602375122f7bfea70dab
URL: https://github.com/llvm/llvm-project/commit/8d5bf0422bc3c8cc7017602375122f7bfea70dab
DIFF: https://github.com/llvm/llvm-project/commit/8d5bf0422bc3c8cc7017602375122f7bfea70dab.diff
LOG: [ms] [llvm-ml] Add support for attempted register parsing
Summary:
Add a new method (tryParseRegister) that attempts to parse a register specification.
MASM allows the use of IFDEF <register>, as well as IFDEF <symbol>. To accommodate this, we make it possible to check whether a register specification can be parsed at the current location, without failing the entire parse if it can't.
Reviewers: thakis
Reviewed By: thakis
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D73486
Added:
Modified:
llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 6e4821cbc7b9..9ce1890916e9 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -376,6 +376,14 @@ class MCTargetAsmParser : public MCAsmParserExtension {
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
index fb09cc247a1a..55b09096bb95 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -260,6 +260,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
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 @@ static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
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
index 8c1f63e4ca86..3ef493bcb156 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -1065,17 +1065,20 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
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<AsmToken> &Tokens);
+ unsigned ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum,
+ unsigned &RegWidth,
+ SmallVectorImpl<AsmToken> &Tokens);
+ unsigned ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum,
+ unsigned &RegWidth,
+ SmallVectorImpl<AsmToken> &Tokens);
+ unsigned ParseRegList(RegisterKind &RegKind, unsigned &RegNum,
+ unsigned &RegWidth, SmallVectorImpl<AsmToken> &Tokens);
bool ParseRegRange(unsigned& Num, unsigned& Width);
unsigned getRegularReg(RegisterKind RegKind,
unsigned RegNum,
@@ -1233,8 +1236,12 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
bool isForcedSDWA() const { return ForcedSDWA; }
ArrayRef<unsigned> getMatchedVariants() const;
- std::unique_ptr<AMDGPUOperand> parseRegister();
+ std::unique_ptr<AMDGPUOperand> 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;
@@ -1987,7 +1994,7 @@ static unsigned getSpecialRegForName(StringRef RegName) {
}
bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
- SMLoc &EndLoc) {
+ SMLoc &EndLoc, bool RestoreOnFailure) {
auto R = parseRegister();
if (!R) return true;
assert(R->isReg());
@@ -1997,6 +2004,25 @@ bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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) {
@@ -2173,31 +2199,31 @@ AMDGPUAsmParser::ParseRegRange(unsigned& Num, unsigned& Width) {
return true;
}
-unsigned
-AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind,
- unsigned &RegNum,
- unsigned &RegWidth) {
+unsigned AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind,
+ unsigned &RegNum, unsigned &RegWidth,
+ SmallVectorImpl<AsmToken> &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<AsmToken> &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;
@@ -2216,10 +2242,9 @@ AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind,
return getRegularReg(RegKind, RegNum, RegWidth);
}
-unsigned
-AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind,
- unsigned &RegNum,
- unsigned &RegWidth) {
+unsigned AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, unsigned &RegNum,
+ unsigned &RegWidth,
+ SmallVectorImpl<AsmToken> &Tokens) {
unsigned Reg = AMDGPU::NoRegister;
if (!trySkipToken(AsmToken::LBrac))
@@ -2236,7 +2261,8 @@ AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind,
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;
@@ -2255,24 +2281,40 @@ AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind,
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<AsmToken> &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<AsmToken, 1> Tokens;
+ if (ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, Tokens)) {
+ if (RestoreOnFailure) {
+ while (!Tokens.empty()) {
+ getLexer().UnLex(Tokens.pop_back_val());
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
Optional<StringRef>
AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) {
switch (RegKind) {
@@ -2321,7 +2363,8 @@ bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind,
return true;
}
-std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
+std::unique_ptr<AMDGPUOperand>
+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
index 8921eb7306bb..e4f375c6f043 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -628,6 +628,8 @@ class ARMAsmParser : public MCTargetAsmParser {
// 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 @@ bool ARMAsmParser::ParseRegister(unsigned &RegNo,
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
index fc34583ae573..9d0dee8cc293 100644
--- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
+++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
@@ -53,6 +53,8 @@ class AVRAsmParser : public MCTargetAsmParser {
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 @@ class AVRAsmParser : public MCTargetAsmParser {
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 @@ int AVRAsmParser::parseRegisterName() {
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 @@ AVRAsmParser::parseMemriOperand(OperandVector &Operands) {
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
index 1f5d5025bc7b..dbcb156a43fd 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -39,6 +39,8 @@ class BPFAsmParser : public MCTargetAsmParser {
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::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
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 @@ bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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
index 5976a811c978..ae19b138b0c7 100644
--- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
+++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
@@ -116,6 +116,8 @@ class HexagonAsmParser : public MCTargetAsmParser {
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::handleNoncontigiousRegister(bool Contigious,
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<AsmToken, 5> Lookahead;
@@ -998,8 +1006,8 @@ bool HexagonAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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 @@ bool HexagonAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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<StringRef, StringRef> 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
index 8b8504978c75..9028f4ad93d9 100644
--- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
+++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
@@ -47,7 +47,7 @@ struct LanaiOperand;
class LanaiAsmParser : public MCTargetAsmParser {
// Parse operands
- std::unique_ptr<LanaiOperand> parseRegister();
+ std::unique_ptr<LanaiOperand> parseRegister(bool RestoreOnFailure = false);
std::unique_ptr<LanaiOperand> parseImmediate();
@@ -67,6 +67,8 @@ class LanaiAsmParser : public MCTargetAsmParser {
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 @@ bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
// backwards compatible with GCC and the
diff erent ways inline assembly is
// handled.
// TODO: see if there isn't a better way to do this.
-std::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() {
+std::unique_ptr<LanaiOperand>
+LanaiAsmParser::parseRegister(bool RestoreOnFailure) {
SMLoc Start = Parser.getTok().getLoc();
SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Optional<AsmToken> 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() && RestoreOnFailure)
+ Lexer.UnLex(PercentTok.getValue());
return nullptr;
+ }
Parser.Lex(); // Eat identifier token
return LanaiOperand::createReg(RegNum, Start, End);
}
+ if (PercentTok.hasValue() && RestoreOnFailure)
+ Lexer.UnLex(PercentTok.getValue());
return nullptr;
}
@@ -710,12 +721,25 @@ bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
const AsmToken &Tok = getParser().getTok();
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
- std::unique_ptr<LanaiOperand> Op = parseRegister();
+ std::unique_ptr<LanaiOperand> 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<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);
+ if (Op == nullptr)
+ return MatchOperand_NoMatch;
+ RegNum = Op->getReg();
+ return MatchOperand_Success;
+}
+
std::unique_ptr<LanaiOperand> 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
index 0995e80a0a09..daa1fb4b52cf 100644
--- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
+++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
@@ -46,6 +46,8 @@ class MSP430AsmParser : public MCTargetAsmParser {
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 @@ static unsigned MatchRegisterAltName(StringRef Name);
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 @@ bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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
index e467ed36938b..21b8d503741e 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -179,6 +179,8 @@ class MipsAsmParser : public MCTargetAsmParser {
/// 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::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
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<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
OperandMatchResultTy ResTy = parseAnyRegister(Operands);
if (ResTy == MatchOperand_Success) {
@@ -6219,11 +6227,12 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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
index ed98852088e7..7859b13ecfaa 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -109,6 +109,8 @@ class PPCAsmParser : public MCTargetAsmParser {
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::MatchRegisterName(unsigned &RegNo, int64_t &IntVal) {
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
index 0160c86950a8..3e72eb096850 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -74,6 +74,8 @@ class RISCVAsmParser : public MCTargetAsmParser {
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 @@ static bool matchRegisterNameHelper(bool IsRV32E, Register &RegNo,
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
index 2d3137f38821..dc75f5ccf973 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -68,6 +68,8 @@ class SparcAsmParser : public MCTargetAsmParser {
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::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
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
index 607266d552a6..00fdb9e846d6 100644
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -405,7 +405,7 @@ class SystemZAsmParser : public MCTargetAsmParser {
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 @@ class SystemZAsmParser : public MCTargetAsmParser {
// 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 @@ void SystemZOperand::print(raw_ostream &OS) const {
}
// Parse one register of the form %<prefix><number>.
-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 @@ bool SystemZAsmParser::parseRegister(Register &Reg) {
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::ParseDirectiveInsn(SMLoc L) {
}
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 @@ bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
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
index a46bf0649ac7..edd20900d810 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -214,6 +214,11 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
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
index d37d812df485..ea4d23d03f29 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -858,6 +858,9 @@ class X86AsmParser : public MCTargetAsmParser {
return nullptr;
}
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
+ bool RestoreOnFailure);
+
std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);
std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);
bool IsSIReg(unsigned Reg);
@@ -1023,6 +1026,8 @@ class X86AsmParser : public MCTargetAsmParser {
}
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 @@ static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,
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<AsmToken, 5> 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 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
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 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
// 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 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
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 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
}
if (RegNo == 0) {
+ OnFailure();
if (isParsingIntelSyntax()) return true;
return Error(StartLoc, "invalid register name",
SMRange(StartLoc, EndLoc));
@@ -1259,6 +1293,25 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
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<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
bool Parse32 = is32BitMode() || Code16GCC;
unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
More information about the llvm-commits
mailing list