AsmMatcher custom operand parser failure enhancements.

Teach the AsmMatcher handling to distinguish between an error custom-parsing
an operand and a failure to match. The former should propogate the error
upwards, while the latter should continue attempting to parse with
alternative matchers.

Update the ARM asm parser accordingly.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125426 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach
2011-02-12 01:34:40 +00:00
parent d7401b35e3
commit f922c47143
4 changed files with 51 additions and 40 deletions

View File

@@ -152,7 +152,7 @@ def CCOutOperand : AsmOperandClass {
def MemBarrierOptOperand : AsmOperandClass { def MemBarrierOptOperand : AsmOperandClass {
let Name = "MemBarrierOpt"; let Name = "MemBarrierOpt";
let SuperClasses = []; let SuperClasses = [];
let ParserMethod = "ParseMemBarrierOptOperand"; let ParserMethod = "tryParseMemBarrierOptOperand";
} }
// ARM Predicate operand. Default to 14 = always (AL). Second part is CC // ARM Predicate operand. Default to 14 = always (AL). Second part is CC

View File

@@ -591,13 +591,13 @@ def nohash_imm : Operand<i32> {
def CoprocNumAsmOperand : AsmOperandClass { def CoprocNumAsmOperand : AsmOperandClass {
let Name = "CoprocNum"; let Name = "CoprocNum";
let SuperClasses = []; let SuperClasses = [];
let ParserMethod = "ParseCoprocNumOperand"; let ParserMethod = "tryParseCoprocNumOperand";
} }
def CoprocRegAsmOperand : AsmOperandClass { def CoprocRegAsmOperand : AsmOperandClass {
let Name = "CoprocReg"; let Name = "CoprocReg";
let SuperClasses = []; let SuperClasses = [];
let ParserMethod = "ParseCoprocRegOperand"; let ParserMethod = "tryParseCoprocRegOperand";
} }
def p_imm : Operand<i32> { def p_imm : Operand<i32> {

View File

@@ -55,10 +55,7 @@ class ARMAsmParser : public TargetAsmParser {
int TryParseRegister(); int TryParseRegister();
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
bool ParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic); bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
bool ParsePrefix(ARMMCExpr::VariantKind &RefKind); bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
@@ -95,6 +92,13 @@ class ARMAsmParser : public TargetAsmParser {
/// } /// }
OperandMatchResultTy tryParseCoprocNumOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy tryParseCoprocRegOperand(
SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy tryParseMemBarrierOptOperand(
SmallVectorImpl<MCParsedAsmOperand*> &);
public: public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
: TargetAsmParser(T), Parser(_Parser), TM(_TM) { : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
@@ -734,40 +738,40 @@ static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
return -1; return -1;
} }
/// ParseCoprocNumOperand - Try to parse an coprocessor number operand. The /// tryParseCoprocNumOperand - Try to parse an coprocessor number operand. The
/// token must be an Identifier when called, and if it is a coprocessor /// token must be an Identifier when called, and if it is a coprocessor
/// number, the token is eaten and the operand is added to the operand list. /// number, the token is eaten and the operand is added to the operand list.
bool ARMAsmParser:: ARMAsmParser::OperandMatchResultTy ARMAsmParser::
ParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { tryParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc(); SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok(); const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
int Num = MatchCoprocessorOperandName(Tok.getString(), 'p'); int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
if (Num == -1) if (Num == -1)
return true; return MatchOperand_NoMatch;
Parser.Lex(); // Eat identifier token. Parser.Lex(); // Eat identifier token.
Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
return false; return MatchOperand_Success;
} }
/// ParseCoprocRegOperand - Try to parse an coprocessor register operand. The /// tryParseCoprocRegOperand - Try to parse an coprocessor register operand. The
/// token must be an Identifier when called, and if it is a coprocessor /// token must be an Identifier when called, and if it is a coprocessor
/// number, the token is eaten and the operand is added to the operand list. /// number, the token is eaten and the operand is added to the operand list.
bool ARMAsmParser:: ARMAsmParser::OperandMatchResultTy ARMAsmParser::
ParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { tryParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc(); SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok(); const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c'); int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
if (Reg == -1) if (Reg == -1)
return true; return MatchOperand_NoMatch;
Parser.Lex(); // Eat identifier token. Parser.Lex(); // Eat identifier token.
Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
return false; return MatchOperand_Success;
} }
/// Parse a register list, return it if successful else return null. The first /// Parse a register list, return it if successful else return null. The first
@@ -854,9 +858,9 @@ ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return false; return false;
} }
/// ParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. /// tryParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
bool ARMAsmParser:: ARMAsmParser::OperandMatchResultTy ARMAsmParser::
ParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc(); SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok(); const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
@@ -874,11 +878,11 @@ ParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
.Default(~0U); .Default(~0U);
if (Opt == ~0U) if (Opt == ~0U)
return true; return MatchOperand_NoMatch;
Parser.Lex(); // Eat identifier token. Parser.Lex(); // Eat identifier token.
Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
return false; return MatchOperand_Success;
} }
/// Parse an ARM memory expression, return false if successful else return true /// Parse an ARM memory expression, return false if successful else return true
@@ -1105,9 +1109,14 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
// Check if the current operand has a custom associated parser, if so, try to // Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach. // custom parse the operand, or fallback to the general approach.
MatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
if (ResTy == Match_Success) if (ResTy == MatchOperand_Success)
return false; return false;
// If there wasn't a custom match, try the generic matcher below. Otherwise,
// there was a match, but an error occurred, in which case, just return that
// the operand parsing failed.
if (ResTy == MatchOperand_ParseFail)
return true;
switch (getLexer().getKind()) { switch (getLexer().getKind()) {
default: default:

View File

@@ -1974,7 +1974,8 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the operand class switch to call the correct custom parser for // Emit the operand class switch to call the correct custom parser for
// the found operand class. // the found operand class.
OS << "bool " << Target.getName() << ClassName << "::\n" OS << Target.getName() << ClassName << "::OperandMatchResultTy "
<< Target.getName() << ClassName << "::\n"
<< "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" << "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n unsigned MCK) {\n\n" << " &Operands,\n unsigned MCK) {\n\n"
<< " switch(MCK) {\n"; << " switch(MCK) {\n";
@@ -1989,15 +1990,15 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
} }
OS << " default:\n"; OS << " default:\n";
OS << " return true;\n"; OS << " return MatchOperand_NoMatch;\n";
OS << " }\n"; OS << " }\n";
OS << " return true;\n"; OS << " return MatchOperand_NoMatch;\n";
OS << "}\n\n"; OS << "}\n\n";
// Emit the static custom operand parser. This code is very similar with // Emit the static custom operand parser. This code is very similar with
// the other matcher. Also use MatchResultTy here just in case we go for // the other matcher. Also use MatchResultTy here just in case we go for
// a better error handling. // a better error handling.
OS << Target.getName() << ClassName << "::MatchResultTy " OS << Target.getName() << ClassName << "::OperandMatchResultTy "
<< Target.getName() << ClassName << "::\n" << Target.getName() << ClassName << "::\n"
<< "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>" << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n StringRef Mnemonic) {\n"; << " &Operands,\n StringRef Mnemonic) {\n";
@@ -2009,9 +2010,6 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << " // Get the next operand index.\n"; OS << " // Get the next operand index.\n";
OS << " unsigned NextOpNum = Operands.size()-1;\n"; OS << " unsigned NextOpNum = Operands.size()-1;\n";
OS << " // Some state to try to produce better error messages.\n";
OS << " bool HadMatchOtherThanFeatures = false;\n\n";
// Emit code to search the table. // Emit code to search the table.
OS << " // Search the table.\n"; OS << " // Search the table.\n";
OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>"; OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>";
@@ -2020,9 +2018,8 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
<< Info.OperandMatchInfo.size() << ", Mnemonic,\n" << Info.OperandMatchInfo.size() << ", Mnemonic,\n"
<< " LessOpcodeOperand());\n\n"; << " LessOpcodeOperand());\n\n";
OS << " // Return a more specific error code if no mnemonics match.\n";
OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
OS << " return Match_MnemonicFail;\n\n"; OS << " return MatchOperand_NoMatch;\n\n";
OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n" OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n"
<< " *ie = MnemonicRange.second; it != ie; ++it) {\n"; << " *ie = MnemonicRange.second; it != ie; ++it) {\n";
@@ -2034,7 +2031,6 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << " // check if the available features match\n"; OS << " // check if the available features match\n";
OS << " if ((AvailableFeatures & it->RequiredFeatures) " OS << " if ((AvailableFeatures & it->RequiredFeatures) "
<< "!= it->RequiredFeatures) {\n"; << "!= it->RequiredFeatures) {\n";
OS << " HadMatchOtherThanFeatures = true;\n";
OS << " continue;\n"; OS << " continue;\n";
OS << " }\n\n"; OS << " }\n\n";
@@ -2045,13 +2041,14 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit call to the custom parser method // Emit call to the custom parser method
OS << " // call custom parse method to handle the operand\n"; OS << " // call custom parse method to handle the operand\n";
OS << " if (!TryCustomParseOperand(Operands, it->Class))\n"; OS << " OperandMatchResultTy Result = ";
OS << " return Match_Success;\n"; OS << "TryCustomParseOperand(Operands, it->Class);\n";
OS << " if (Result != MatchOperand_NoMatch)\n";
OS << " return Result;\n";
OS << " }\n\n"; OS << " }\n\n";
OS << " // Okay, we had no match. Try to return a useful error code.\n"; OS << " // Okay, we had no match.\n";
OS << " if (HadMatchOtherThanFeatures) return Match_MissingFeature;\n"; OS << " return MatchOperand_NoMatch;\n";
OS << " return Match_InvalidOperand;\n";
OS << "}\n\n"; OS << "}\n\n";
} }
@@ -2131,11 +2128,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " MCInst &Inst, unsigned &ErrorInfo);\n"; OS << " MCInst &Inst, unsigned &ErrorInfo);\n";
if (Info.OperandMatchInfo.size()) { if (Info.OperandMatchInfo.size()) {
OS << " MatchResultTy MatchOperandParserImpl(\n"; OS << "\n enum OperandMatchResultTy {\n";
OS << " MatchOperand_Success, // operand matched successfully\n";
OS << " MatchOperand_NoMatch, // operand did not match\n";
OS << " MatchOperand_ParseFail // operand matched but had errors\n";
OS << " };\n";
OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " StringRef Mnemonic);\n"; OS << " StringRef Mnemonic);\n";
OS << " bool TryCustomParseOperand(\n"; OS << " OperandMatchResultTy TryCustomParseOperand(\n";
OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " unsigned MCK);\n\n"; OS << " unsigned MCK);\n\n";
} }