diff options
author | Jim Grosbach <grosbach@apple.com> | 2011-02-12 01:34:40 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2011-02-12 01:34:40 +0000 |
commit | f922c47143d247cbae14b294a0bada139bcd35f6 (patch) | |
tree | e6d368b6102e76c60523202176025779c306887b | |
parent | d7401b35e3a4d08e43b4ab81dffd58099a37c90d (diff) | |
download | external_llvm-f922c47143d247cbae14b294a0bada139bcd35f6.zip external_llvm-f922c47143d247cbae14b294a0bada139bcd35f6.tar.gz external_llvm-f922c47143d247cbae14b294a0bada139bcd35f6.tar.bz2 |
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
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 4 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 49 | ||||
-rw-r--r-- | utils/TableGen/AsmMatcherEmitter.cpp | 36 |
4 files changed, 51 insertions, 40 deletions
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 43e53ad..e018ab5 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -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 diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 961649b..2fd2532 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -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> { diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 87f77f2..089a08c 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -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: diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index ae817d5..35f5f6f 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -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"; } |