X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=utils%2FTableGen%2FAsmMatcherEmitter.cpp;h=e55bbd37610bf29f387cf9a7fd8534f90f08d0a5;hp=ad2f6af8ba122aeb71819655679bb65129136004;hb=d33bb62823b37dab31f996cfbe7a5b8563d85e9b;hpb=5a40bef7979813149432fba5f6f287f2eb7dc5a2 diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index ad2f6af8ba1..e55bbd37610 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -264,6 +264,11 @@ public: } /// operator< - Compare two classes. + // FIXME: This ordering seems to be broken. For example: + // u64 < i64, i64 < s8, s8 < u64, forming a cycle + // u64 is a subset of i64 + // i64 and s8 are not subsets of each other, so are ordered by name + // s8 and u64 are not subsets of each other, so are ordered by name bool operator<(const ClassInfo &RHS) const { if (this == &RHS) return false; @@ -289,6 +294,13 @@ public: } }; +class AsmVariantInfo { +public: + std::string TokenizingCharacters; + std::string SeparatorCharacters; + std::string BreakCharacters; +}; + /// MatchableInfo - Helper class for storing the necessary information for an /// instruction or alias which is capable of being matched. struct MatchableInfo { @@ -305,11 +317,16 @@ struct MatchableInfo { /// The suboperand index within SrcOpName, or -1 for the entire operand. int SubOpIdx; + /// Whether the token is "isolated", i.e., it is preceded and followed + /// by separators. + bool IsIsolatedToken; + /// Register record if this token is singleton register. Record *SingletonReg; - explicit AsmOperand(StringRef T) : Token(T), Class(nullptr), SubOpIdx(-1), - SingletonReg(nullptr) {} + explicit AsmOperand(bool IsIsolatedToken, StringRef T) + : Token(T), Class(nullptr), SubOpIdx(-1), + IsIsolatedToken(IsIsolatedToken), SingletonReg(nullptr) {} }; /// ResOperand - This represents a single operand in the result instruction @@ -433,12 +450,35 @@ struct MatchableInfo { /// If this instruction is deprecated in some form. bool HasDeprecation; + /// If this is an alias, this is use to determine whether or not to using + /// the conversion function defined by the instruction's AsmMatchConverter + /// or to use the function generated by the alias. + bool UseInstAsmMatchConverter; + MatchableInfo(const CodeGenInstruction &CGI) - : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI) { + : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI), + UseInstAsmMatchConverter(true) { } MatchableInfo(std::unique_ptr Alias) - : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) { + : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), + DefRec(Alias.release()), + UseInstAsmMatchConverter( + TheDef->getValueAsBit("UseInstAsmMatchConverter")) { + } + + // Could remove this and the dtor if PointerUnion supported unique_ptr + // elements with a dynamic failure/assertion (like the one below) in the case + // where it was copied while being in an owning state. + MatchableInfo(const MatchableInfo &RHS) + : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString), + TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands), + Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands), + RequiredFeatures(RHS.RequiredFeatures), + ConversionFnKind(RHS.ConversionFnKind), + HasDeprecation(RHS.HasDeprecation), + UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) { + assert(!DefRec.is()); } ~MatchableInfo() { @@ -451,18 +491,13 @@ struct MatchableInfo { void initialize(const AsmMatcherInfo &Info, SmallPtrSetImpl &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix); + int AsmVariantNo, StringRef RegisterPrefix, + AsmVariantInfo const &Variant); /// validate - Return true if this matchable is a valid thing to match against /// and perform a bunch of validity checking. bool validate(StringRef CommentDelimiter, bool Hack) const; - /// extractSingletonRegisterForAsmOperand - Extract singleton register, - /// if present, from specified token. - void - extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info, - std::string &RegisterPrefix); - /// findAsmOperand - Find the AsmOperand with the specified name and /// suboperand index. int findAsmOperand(StringRef N, int SubOpIdx) const { @@ -557,7 +592,10 @@ struct MatchableInfo { void dump() const; private: - void tokenizeAsmString(const AsmMatcherInfo &Info); + void tokenizeAsmString(AsmMatcherInfo const &Info, + AsmVariantInfo const &Variant); + void addAsmOperand(size_t Start, size_t End, + std::string const &SeparatorCharacters); }; /// SubtargetFeatureInfo - Helper class for storing information on a subtarget @@ -766,26 +804,58 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { } } +/// extractSingletonRegisterForAsmOperand - Extract singleton register, +/// if present, from specified token. +static void +extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op, + const AsmMatcherInfo &Info, + StringRef RegisterPrefix) { + StringRef Tok = Op.Token; + + // If this token is not an isolated token, i.e., it isn't separated from + // other tokens (e.g. with whitespace), don't interpret it as a register name. + if (!Op.IsIsolatedToken) + return; + + if (RegisterPrefix.empty()) { + std::string LoweredTok = Tok.lower(); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) + Op.SingletonReg = Reg->TheDef; + return; + } + + if (!Tok.startswith(RegisterPrefix)) + return; + + StringRef RegName = Tok.substr(RegisterPrefix.size()); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) + Op.SingletonReg = Reg->TheDef; + + // If there is no register prefix (i.e. "%" in "%eax"), then this may + // be some random non-register token, just ignore it. + return; +} + void MatchableInfo::initialize(const AsmMatcherInfo &Info, SmallPtrSetImpl &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix) { + int AsmVariantNo, StringRef RegisterPrefix, + AsmVariantInfo const &Variant) { AsmVariantID = AsmVariantNo; AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); - tokenizeAsmString(Info); + tokenizeAsmString(Info, Variant); // Compute the require features. - std::vector Predicates =TheDef->getValueAsListOfDefs("Predicates"); - for (unsigned i = 0, e = Predicates.size(); i != e; ++i) + for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates")) if (const SubtargetFeatureInfo *Feature = - Info.getSubtargetFeature(Predicates[i])) + Info.getSubtargetFeature(Predicate)) RequiredFeatures.push_back(Feature); // Collect singleton registers, if used. - for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix); - if (Record *Reg = AsmOperands[i].SingletonReg) + for (MatchableInfo::AsmOperand &Op : AsmOperands) { + extractSingletonRegisterForAsmOperand(Op, Info, RegisterPrefix); + if (Record *Reg = Op.SingletonReg) SingletonRegisters.insert(Reg); } @@ -797,47 +867,72 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false; } +/// Append an AsmOperand for the given substring of AsmString. +void MatchableInfo::addAsmOperand(size_t Start, size_t End, + std::string const &Separators) { + StringRef String = AsmString; + // Look for separators before and after to figure out is this token is + // isolated. Accept '$$' as that's how we escape '$'. + bool IsIsolatedToken = + (!Start || Separators.find(String[Start - 1]) != StringRef::npos || + String.substr(Start - 1, 2) == "$$") && + (End >= String.size() || Separators.find(String[End]) != StringRef::npos); + AsmOperands.push_back(AsmOperand(IsIsolatedToken, String.slice(Start, End))); +} + /// tokenizeAsmString - Tokenize a simplified assembly string. -void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { +void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info, + AsmVariantInfo const &Variant) { StringRef String = AsmString; unsigned Prev = 0; - bool InTok = true; + bool InTok = false; + std::string Separators = Variant.TokenizingCharacters + + Variant.SeparatorCharacters; for (unsigned i = 0, e = String.size(); i != e; ++i) { - switch (String[i]) { - case '[': - case ']': - case '*': - case '!': - case ' ': - case '\t': - case ',': - if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + if(Variant.BreakCharacters.find(String[i]) != std::string::npos) { + if(InTok) { + addAsmOperand(Prev, i, Separators); + Prev = i; + } + InTok = true; + continue; + } + if(Variant.TokenizingCharacters.find(String[i]) != std::string::npos) { + if(InTok) { + addAsmOperand(Prev, i, Separators); InTok = false; } - if (!isspace(String[i]) && String[i] != ',') - AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + addAsmOperand(i, i + 1, Separators); Prev = i + 1; - break; - + continue; + } + if(Variant.SeparatorCharacters.find(String[i]) != std::string::npos) { + if(InTok) { + addAsmOperand(Prev, i, Separators); + InTok = false; + } + Prev = i + 1; + continue; + } + switch (String[i]) { case '\\': if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(Prev, i, Separators); InTok = false; } ++i; assert(i != String.size() && "Invalid quoted character"); - AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + addAsmOperand(i, i + 1, Separators); Prev = i + 1; break; case '$': { - if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + if (InTok && Prev != i) { + addAsmOperand(Prev, i, Separators); InTok = false; } - // If this isn't "${", treat like a normal token. + // If this isn't "${", start new identifier looking like "$xxx" if (i + 1 == String.size() || String[i + 1] != '{') { Prev = i; break; @@ -846,44 +941,26 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { StringRef::iterator End = std::find(String.begin() + i, String.end(),'}'); assert(End != String.end() && "Missing brace in operand reference!"); size_t EndPos = End - String.begin(); - AsmOperands.push_back(AsmOperand(String.slice(i, EndPos+1))); + addAsmOperand(i, EndPos+1, Separators); Prev = EndPos + 1; i = EndPos; break; } - - case '.': - if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) { - if (InTok) - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); - Prev = i; - } - InTok = true; - break; - default: InTok = true; } } if (InTok && Prev != String.size()) - AsmOperands.push_back(AsmOperand(String.substr(Prev))); + addAsmOperand(Prev, StringRef::npos, Separators); // The first token of the instruction is the mnemonic, which must be a // simple string, not a $foo variable or a singleton register. if (AsmOperands.empty()) PrintFatalError(TheDef->getLoc(), "Instruction '" + TheDef->getName() + "' has no tokens"); - Mnemonic = AsmOperands[0].Token; - if (Mnemonic.empty()) - PrintFatalError(TheDef->getLoc(), - "Missing instruction mnemonic"); - // FIXME : Check and raise an error if it is a register. - if (Mnemonic[0] == '$') - PrintFatalError(TheDef->getLoc(), - "Invalid instruction mnemonic '" + Mnemonic + "'!"); - - // Remove the first operand, it is tracked in the mnemonic field. - AsmOperands.erase(AsmOperands.begin()); + assert(!AsmOperands[0].Token.empty()); + if (AsmOperands[0].Token[0] != '$') + Mnemonic = AsmOperands[0].Token; } bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { @@ -941,32 +1018,6 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { return true; } -/// extractSingletonRegisterForAsmOperand - Extract singleton register, -/// if present, from specified token. -void MatchableInfo:: -extractSingletonRegisterForAsmOperand(unsigned OperandNo, - const AsmMatcherInfo &Info, - std::string &RegisterPrefix) { - StringRef Tok = AsmOperands[OperandNo].Token; - if (RegisterPrefix.empty()) { - std::string LoweredTok = Tok.lower(); - if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) - AsmOperands[OperandNo].SingletonReg = Reg->TheDef; - return; - } - - if (!Tok.startswith(RegisterPrefix)) - return; - - StringRef RegName = Tok.substr(RegisterPrefix.size()); - if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) - AsmOperands[OperandNo].SingletonReg = Reg->TheDef; - - // If there is no register prefix (i.e. "%" in "%eax"), then this may - // be some random non-register token, just ignore it. - return; -} - static std::string getEnumNameForToken(StringRef Str) { std::string Res; @@ -1210,8 +1261,8 @@ void AsmMatcherInfo::buildOperandClasses() { CI->Kind = ClassInfo::UserClass0 + Index; ListInit *Supers = Rec->getValueAsListInit("SuperClasses"); - for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) { - DefInit *DI = dyn_cast(Supers->getElement(i)); + for (Init *I : Supers->getValues()) { + DefInit *DI = dyn_cast(I); if (!DI) { PrintError(Rec->getLoc(), "Invalid super class reference!"); continue; @@ -1326,6 +1377,13 @@ void AsmMatcherInfo::buildInfo() { std::string CommentDelimiter = AsmVariant->getValueAsString("CommentDelimiter"); std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); + AsmVariantInfo Variant; + Variant.TokenizingCharacters = + AsmVariant->getValueAsString("TokenizingCharacters"); + Variant.SeparatorCharacters = + AsmVariant->getValueAsString("SeparatorCharacters"); + Variant.BreakCharacters = + AsmVariant->getValueAsString("BreakCharacters"); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); for (const CodeGenInstruction *CGI : Target.instructions()) { @@ -1339,9 +1397,10 @@ void AsmMatcherInfo::buildInfo() { if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; - std::unique_ptr II(new MatchableInfo(*CGI)); + auto II = llvm::make_unique(*CGI); - II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix, + Variant); // Ignore instructions which shouldn't be matched and diagnose invalid // instruction definitions with an error. @@ -1366,9 +1425,10 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - std::unique_ptr II(new MatchableInfo(std::move(Alias))); + auto II = llvm::make_unique(std::move(Alias)); - II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix, + Variant); // Validate the alias definitions. II->validate(CommentDelimiter, false); @@ -1435,7 +1495,7 @@ void AsmMatcherInfo::buildInfo() { II->TheDef->getValueAsString("TwoOperandAliasConstraint"); if (Constraint != "") { // Start by making a copy of the original matchable. - std::unique_ptr AliasII(new MatchableInfo(*II)); + auto AliasII = llvm::make_unique(*II); // Adjust it to be a two-operand alias. AliasII->formTwoOperandAlias(Constraint); @@ -1447,8 +1507,9 @@ void AsmMatcherInfo::buildInfo() { II->buildAliasResultOperands(); } if (!NewMatchables.empty()) - std::move(NewMatchables.begin(), NewMatchables.end(), - std::back_inserter(Matchables)); + Matchables.insert(Matchables.end(), + std::make_move_iterator(NewMatchables.begin()), + std::make_move_iterator(NewMatchables.end())); // Process token alias definitions and set up the associated superclass // information. @@ -1495,7 +1556,7 @@ buildInstructionOperandReference(MatchableInfo *II, // Insert remaining suboperands after AsmOpIdx in II->AsmOperands. StringRef Token = Op->Token; // save this in case Op gets moved for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) { - MatchableInfo::AsmOperand NewAsmOp(Token); + MatchableInfo::AsmOperand NewAsmOp(/*IsIsolatedToken=*/true, Token); NewAsmOp.SubOpIdx = SI; II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp); } @@ -1661,7 +1722,7 @@ void MatchableInfo::buildAliasResultOperands() { } static unsigned getConverterOperandID(const std::string &Name, - SetVector &Table, + SmallSetVector &Table, bool &IsNew) { IsNew = Table.insert(Name); @@ -1677,8 +1738,8 @@ static unsigned getConverterOperandID(const std::string &Name, static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector> &Infos, raw_ostream &OS) { - SetVector OperandConversionKinds; - SetVector InstructionConversionKinds; + SmallSetVector OperandConversionKinds; + SmallSetVector InstructionConversionKinds; std::vector > ConversionTable; size_t MaxRowLength = 2; // minimum is custom converter plus terminator. @@ -1743,7 +1804,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Check if we have a custom match function. std::string AsmMatchConverter = II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); - if (!AsmMatchConverter.empty()) { + if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) { std::string Signature = "ConvertCustom_" + AsmMatchConverter; II->ConversionFnKind = Signature; @@ -1757,7 +1818,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, getEnumNameForToken(AsmMatchConverter)); // Add the converter row for this instruction. - ConversionTable.push_back(std::vector()); + ConversionTable.emplace_back(); ConversionTable.back().push_back(KindID); ConversionTable.back().push_back(CVT_Done); @@ -1810,7 +1871,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Add the operand entry to the instruction kind conversion row. ConversionRow.push_back(ID); - ConversionRow.push_back(OpInfo.AsmOperandNum + 1); + ConversionRow.push_back(OpInfo.AsmOperandNum); if (!IsNewConverter) break; @@ -1864,7 +1925,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, break; CvtOS << " case " << Name << ":\n" - << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n" + << " Inst.addOperand(MCOperand::createImm(" << Val << "));\n" << " break;\n"; OpOS << " case " << Name << ":\n" @@ -1895,7 +1956,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, if (!IsNewConverter) break; CvtOS << " case " << Name << ":\n" - << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n" + << " Inst.addOperand(MCOperand::createReg(" << Reg << "));\n" << " break;\n"; OpOS << " case " << Name << ":\n" @@ -1919,7 +1980,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, continue; // Add the row to the table. - ConversionTable.push_back(ConversionRow); + ConversionTable.push_back(std::move(ConversionRow)); } // Finish up the converter driver function. @@ -1939,10 +2000,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Output the instruction conversion kind enum. OS << "enum InstructionConversionKind {\n"; - for (SetVector::const_iterator - i = InstructionConversionKinds.begin(), - e = InstructionConversionKinds.end(); i != e; ++i) - OS << " " << *i << ",\n"; + for (const std::string &Signature : InstructionConversionKinds) + OS << " " << Signature << ",\n"; OS << " CVT_NUM_SIGNATURES\n"; OS << "};\n\n"; @@ -2121,8 +2180,7 @@ static void emitMatchTokenString(CodeGenTarget &Target, std::vector Matches; for (const auto &CI : Infos) { if (CI.Kind == ClassInfo::Token) - Matches.push_back( - StringMatcher::StringPair(CI.ValueName, "return " + CI.Name + ";")); + Matches.emplace_back(CI.ValueName, "return " + CI.Name + ";"); } OS << "static MatchClassKind matchTokenString(StringRef Name) {\n"; @@ -2144,9 +2202,8 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, if (Reg.TheDef->getValueAsString("AsmName").empty()) continue; - Matches.push_back( - StringMatcher::StringPair(Reg.TheDef->getValueAsString("AsmName"), - "return " + utostr(Reg.EnumValue) + ";")); + Matches.emplace_back(Reg.TheDef->getValueAsString("AsmName"), + "return " + utostr(Reg.EnumValue) + ";"); } OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; @@ -2242,7 +2299,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, Info.AsmParser->getValueAsString("AsmParserClassName"); OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(uint64_t FB) const {\n"; + << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n"; for (const auto &SF : Info.SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; @@ -2264,12 +2321,10 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, Cond = Cond.substr(1); } - OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; + OS << "("; if (Neg) - OS << " == 0"; - else - OS << " != 0"; - OS << ")"; + OS << "!"; + OS << "FB[" << Info.Target.getName() << "::" << Cond << "])"; if (Comma.second.empty()) break; @@ -2539,13 +2594,17 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; - OS << " unsigned NextOpNum = Operands.size()-1;\n"; + OS << " unsigned NextOpNum = Operands.size();\n"; // Emit code to search the table. OS << " // Search the table.\n"; OS << " std::pair"; - OS << " MnemonicRange =\n"; - OS << " std::equal_range(OperandMatchTable, OperandMatchTable+" + OS << " MnemonicRange\n"; + OS << " (OperandMatchTable, OperandMatchTable+"; + OS << Info.OperandMatchInfo.size() << ");\n"; + OS << " if(!Mnemonic.empty())\n"; + OS << " MnemonicRange = std::equal_range(OperandMatchTable,"; + OS << " OperandMatchTable+" << Info.OperandMatchInfo.size() << ", Mnemonic,\n" << " LessOpcodeOperand());\n\n"; @@ -2639,7 +2698,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2653,7 +2712,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; - if (Info.OperandMatchInfo.size()) { + if (!Info.OperandMatchInfo.empty()) { OS << "\n enum OperandMatchResultTy {\n"; OS << " MatchOperand_Success, // operand matched successfully\n"; OS << " MatchOperand_NoMatch, // operand did not match\n"; @@ -2855,8 +2914,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; - OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; - OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; + OS << " if (Operands.size() > " << MaxNumOperands << ") {\n"; + OS << " ErrorInfo = " << MaxNumOperands << ";\n"; OS << " return Match_InvalidOperand;\n"; OS << " }\n\n"; @@ -2865,7 +2924,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; - OS << " StringRef Mnemonic = ((" << Target.getName() + OS << " StringRef Mnemonic;\n"; + OS << " if (Operands[0]->isToken())\n"; + OS << " Mnemonic = ((" << Target.getName() << "Operand&)*Operands[0]).getToken();\n\n"; if (HasMnemonicAliases) { @@ -2881,7 +2942,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint64_t MissingFeatures = ~0ULL;\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; - OS << " ErrorInfo = ~0U;\n"; + OS << " ErrorInfo = ~0ULL;\n"; // Emit code to search the table. OS << " // Find the appropriate table for this asm variant.\n"; @@ -2896,8 +2957,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { } OS << " }\n"; OS << " // Search the table.\n"; - OS << " std::pair MnemonicRange =\n"; - OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n"; + OS << " std::pair" + "MnemonicRange(Start, End);\n"; + OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n"; + OS << " if (!Mnemonic.empty())\n"; + OS << " MnemonicRange = std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n"; OS << " // Return a more specific error code if no mnemonics match.\n"; OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; @@ -2907,28 +2971,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "*ie = MnemonicRange.second;\n"; OS << " it != ie; ++it) {\n"; - OS << " // equal_range guarantees that instruction mnemonic matches.\n"; - OS << " assert(Mnemonic == it->getMnemonic());\n"; - // Emit check that the subclasses match. OS << " bool OperandsValid = true;\n"; - OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; - OS << " if (i + 1 >= Operands.size()) {\n"; - OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; - OS << " if (!OperandsValid) ErrorInfo = i + 1;\n"; + OS << " for (unsigned i = SIndex; i != " << MaxNumOperands << "; ++i) {\n"; + OS << " auto Formal = static_cast(it->Classes[i]);\n"; + OS << " if (i >= Operands.size()) {\n"; + OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n"; + OS << " if (!OperandsValid) ErrorInfo = i;\n"; OS << " break;\n"; OS << " }\n"; - OS << " unsigned Diag = validateOperandClass(*Operands[i+1],\n"; - OS.indent(43); - OS << "(MatchClassKind)it->Classes[i]);\n"; + OS << " MCParsedAsmOperand &Actual = *Operands[i];\n"; + OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n"; OS << " if (Diag == Match_Success)\n"; OS << " continue;\n"; OS << " // If the generic handler indicates an invalid operand\n"; OS << " // failure, check for a special case.\n"; OS << " if (Diag == Match_InvalidOperand) {\n"; - OS << " Diag = validateTargetOperandClass(*Operands[i+1],\n"; - OS.indent(43); - OS << "(MatchClassKind)it->Classes[i]);\n"; + OS << " Diag = validateTargetOperandClass(Actual, Formal);\n"; OS << " if (Diag == Match_Success)\n"; OS << " continue;\n"; OS << " }\n"; @@ -2937,8 +2996,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // If we already had a match that only failed due to a\n"; OS << " // target predicate, that diagnostic is preferred.\n"; OS << " if (!HadMatchOtherThanPredicate &&\n"; - OS << " (it == MnemonicRange.first || ErrorInfo <= i+1)) {\n"; - OS << " ErrorInfo = i+1;\n"; + OS << " (it == MnemonicRange.first || ErrorInfo <= i)) {\n"; + OS << " ErrorInfo = i;\n"; OS << " // InvalidOperand is the default. Prefer specificity.\n"; OS << " if (Diag != Match_InvalidOperand)\n"; OS << " RetCode = Diag;\n"; @@ -2956,8 +3015,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " HadMatchOtherThanFeatures = true;\n"; OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" - " CountPopulation_64(MissingFeatures))\n"; + OS << " if (countPopulation(NewMissingFeatures) <=\n" + " countPopulation(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; @@ -2993,7 +3052,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (HasDeprecation) { OS << " std::string Info;\n"; - OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; + OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; OS << " getParser().Warning(Loc, Info, None);\n"; @@ -3011,7 +3070,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " return Match_MissingFeature;\n"; OS << "}\n\n"; - if (Info.OperandMatchInfo.size()) + if (!Info.OperandMatchInfo.empty()) emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable, MaxMnemonicIndex);