AsmMatcher custom operand parser failure enhancements.
authorJim Grosbach <grosbach@apple.com>
Sat, 12 Feb 2011 01:34:40 +0000 (01:34 +0000)
committerJim Grosbach <grosbach@apple.com>
Sat, 12 Feb 2011 01:34:40 +0000 (01:34 +0000)
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

lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
utils/TableGen/AsmMatcherEmitter.cpp

index 43e53ad8d485376cd806c09f34767c435c45b7fd..e018ab53ca455ccd90a638b732c68032f0d896f4 100644 (file)
@@ -152,7 +152,7 @@ def CCOutOperand : AsmOperandClass {
 def MemBarrierOptOperand : AsmOperandClass {
   let Name = "MemBarrierOpt";
   let SuperClasses = [];
-  let ParserMethod = "ParseMemBarrierOptOperand";
+  let ParserMethod = "tryParseMemBarrierOptOperand";
 }
 
 // ARM Predicate operand. Default to 14 = always (AL). Second part is CC
index 961649b67497d88e4eab61cacd96ffc554de5db7..2fd25328d3b3eadf94011a7f0769293a9dde10e8 100644 (file)
@@ -591,13 +591,13 @@ def nohash_imm : Operand<i32> {
 def CoprocNumAsmOperand : AsmOperandClass {
   let Name = "CoprocNum";
   let SuperClasses = [];
-  let ParserMethod = "ParseCoprocNumOperand";
+  let ParserMethod = "tryParseCoprocNumOperand";
 }
 
 def CoprocRegAsmOperand : AsmOperandClass {
   let Name = "CoprocReg";
   let SuperClasses = [];
-  let ParserMethod = "ParseCoprocRegOperand";
+  let ParserMethod = "tryParseCoprocRegOperand";
 }
 
 def p_imm : Operand<i32> {
index 87f77f25ef12eea315733da5219f448bd5ec737e..089a08c405f4ed6864c739248b81b269db09390e 100644 (file)
@@ -55,10 +55,7 @@ class ARMAsmParser : public TargetAsmParser {
   int TryParseRegister();
   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
   bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
-  bool ParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
-  bool ParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
   bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
-  bool ParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &);
   bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
   bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
   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:
   ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
     : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
@@ -734,40 +738,40 @@ static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
   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
 /// number, the token is eaten and the operand is added to the operand list.
-bool ARMAsmParser::
-ParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+tryParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
   SMLoc S = Parser.getTok().getLoc();
   const AsmToken &Tok = Parser.getTok();
   assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
 
   int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
   if (Num == -1)
-    return true;
+    return MatchOperand_NoMatch;
 
   Parser.Lex(); // Eat identifier token.
   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
 /// number, the token is eaten and the operand is added to the operand list.
-bool ARMAsmParser::
-ParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+tryParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
   SMLoc S = Parser.getTok().getLoc();
   const AsmToken &Tok = Parser.getTok();
   assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
 
   int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
   if (Reg == -1)
-    return true;
+    return MatchOperand_NoMatch;
 
   Parser.Lex(); // Eat identifier token.
   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
@@ -854,9 +858,9 @@ ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
   return false;
 }
 
-/// ParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
-bool ARMAsmParser::
-ParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+/// tryParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
   SMLoc S = Parser.getTok().getLoc();
   const AsmToken &Tok = Parser.getTok();
   assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
@@ -874,11 +878,11 @@ ParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
     .Default(~0U);
 
   if (Opt == ~0U)
-    return true;
+    return MatchOperand_NoMatch;
 
   Parser.Lex(); // Eat identifier token.
   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
@@ -1105,9 +1109,14 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
 
   // Check if the current operand has a custom associated parser, if so, try to
   // custom parse the operand, or fallback to the general approach.
-  MatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
-  if (ResTy == Match_Success)
+  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
+  if (ResTy == MatchOperand_Success)
     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()) {
   default:
index ae817d577d25b5da5aa0fbfabc9d3f37a4abc43e..35f5f6facc49fa2dac7b9aaab614886d3cc326ca 100644 (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
   // the found operand class.
-  OS << "bool " << Target.getName() << ClassName << "::\n"
+  OS << Target.getName() << ClassName << "::OperandMatchResultTy "
+     << Target.getName() << ClassName << "::\n"
      << "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>"
      << " &Operands,\n                      unsigned MCK) {\n\n"
      << "  switch(MCK) {\n";
@@ -1989,15 +1990,15 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
   }
 
   OS << "  default:\n";
-  OS << "    return true;\n";
+  OS << "    return MatchOperand_NoMatch;\n";
   OS << "  }\n";
-  OS << "  return true;\n";
+  OS << "  return MatchOperand_NoMatch;\n";
   OS << "}\n\n";
 
   // 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
   // a better error handling.
-  OS << Target.getName() << ClassName << "::MatchResultTy "
+  OS << Target.getName() << ClassName << "::OperandMatchResultTy "
      << Target.getName() << ClassName << "::\n"
      << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>"
      << " &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 << "  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.
   OS << "  // Search the table.\n";
   OS << "  std::pair<const OperandMatchEntry*, const OperandMatchEntry*>";
@@ -2020,9 +2018,8 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
      << Info.OperandMatchInfo.size() << ", Mnemonic,\n"
      << "                     LessOpcodeOperand());\n\n";
 
-  OS << "  // Return a more specific error code if no mnemonics match.\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"
      << "       *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 << "    if ((AvailableFeatures & it->RequiredFeatures) "
      << "!= it->RequiredFeatures) {\n";
-  OS << "      HadMatchOtherThanFeatures = true;\n";
   OS << "      continue;\n";
   OS << "    }\n\n";
 
@@ -2045,13 +2041,14 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
 
   // Emit call to the custom parser method
   OS << "    // call custom parse method to handle the operand\n";
-  OS << "    if (!TryCustomParseOperand(Operands, it->Class))\n";
-  OS << "      return Match_Success;\n";
+  OS << "    OperandMatchResultTy Result = ";
+  OS << "TryCustomParseOperand(Operands, it->Class);\n";
+  OS << "    if (Result != MatchOperand_NoMatch)\n";
+  OS << "      return Result;\n";
   OS << "  }\n\n";
 
-  OS << "  // Okay, we had no match.  Try to return a useful error code.\n";
-  OS << "  if (HadMatchOtherThanFeatures) return Match_MissingFeature;\n";
-  OS << "  return Match_InvalidOperand;\n";
+  OS << "  // Okay, we had no match.\n";
+  OS << "  return MatchOperand_NoMatch;\n";
   OS << "}\n\n";
 }
 
@@ -2131,11 +2128,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
   OS << "    MCInst &Inst, unsigned &ErrorInfo);\n";
 
   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 << "    StringRef Mnemonic);\n";
 
-    OS << "  bool TryCustomParseOperand(\n";
+    OS << "  OperandMatchResultTy TryCustomParseOperand(\n";
     OS << "    SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
     OS << "    unsigned MCK);\n\n";
   }