X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=utils%2FTableGen%2FAsmMatcherEmitter.cpp;h=2ec65442a330b4689feb541a67739fde6104fbbe;hp=1277086ba823148aa57395f58373c468cedc8406;hb=8dd99ee81de8af8f0500e2baeacd29bf24b7f02c;hpb=c50f986b4d8ecbf3437c67e987e26e268ef5f06a diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1277086ba82..2ec65442a33 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -115,6 +115,7 @@ #include #include #include +#include using namespace llvm; #define DEBUG_TYPE "asm-matcher-emitter" @@ -255,15 +256,19 @@ public: return true; // ... or if any of its super classes are a subset of RHS. - for (std::vector::const_iterator it = SuperClasses.begin(), - ie = SuperClasses.end(); it != ie; ++it) - if ((*it)->isSubsetOf(RHS)) + for (const ClassInfo *CI : SuperClasses) + if (CI->isSubsetOf(RHS)) return true; return false; } /// 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,15 @@ public: } }; +class AsmVariantInfo { +public: + std::string RegisterPrefix; + std::string TokenizingCharacters; + std::string SeparatorCharacters; + std::string BreakCharacters; + int AsmVariantNo; +}; + /// MatchableInfo - Helper class for storing the necessary information for an /// instruction or alias which is capable of being matched. struct MatchableInfo { @@ -305,11 +319,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 @@ -391,6 +410,10 @@ struct MatchableInfo { /// AsmVariantID - Target's assembly syntax variant no. int AsmVariantID; + /// AsmString - The assembly string for this instruction (with variants + /// removed), e.g. "movsx $src, $dst". + std::string AsmString; + /// TheDef - This is the definition of the instruction or InstAlias that this /// matchable came from. Record *const TheDef; @@ -408,10 +431,6 @@ struct MatchableInfo { /// MCInst. SmallVector ResOperands; - /// AsmString - The assembly string for this instruction (with variants - /// removed), e.g. "movsx $src, $dst". - std::string AsmString; - /// Mnemonic - This is the first token of the matched instruction, its /// mnemonic. StringRef Mnemonic; @@ -423,7 +442,7 @@ struct MatchableInfo { SmallVector AsmOperands; /// Predicates - The required subtarget features to match this instruction. - SmallVector RequiredFeatures; + SmallVector RequiredFeatures; /// ConversionFnKind - The enum value which is passed to the generated /// convertToMCInst to convert parsed operands into an MCInst for this @@ -433,14 +452,39 @@ 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), TheDef(CGI.TheDef), DefRec(&CGI), - AsmString(CGI.AsmString) { + : 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()), + UseInstAsmMatchConverter( + TheDef->getValueAsBit("UseInstAsmMatchConverter")) { } - MatchableInfo(const CodeGenInstAlias *Alias) - : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias), - AsmString(Alias->AsmString) { + // 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() { + delete DefRec.dyn_cast(); } // Two-operand aliases clone from the main matchable, but mark the second @@ -448,19 +492,14 @@ struct MatchableInfo { void formTwoOperandAlias(StringRef Constraint); void initialize(const AsmMatcherInfo &Info, - SmallPtrSet &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix); + SmallPtrSetImpl &SingletonRegisters, + AsmVariantInfo const &Variant, + bool HasMnemonicFirst); /// 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 { @@ -516,7 +555,7 @@ struct MatchableInfo { /// couldMatchAmbiguouslyWith - Check whether this matchable could /// ambiguously match the same set of operands as \p RHS (without being a /// strictly superior match). - bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) { + bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const { // The primary comparator is the instruction mnemonic. if (Mnemonic != RHS.Mnemonic) return false; @@ -552,10 +591,12 @@ struct MatchableInfo { return !(HasLT ^ HasGT); } - void dump(); + void dump() const; private: - void tokenizeAsmString(const AsmMatcherInfo &Info); + void tokenizeAsmString(AsmMatcherInfo const &Info, + AsmVariantInfo const &Variant); + void addAsmOperand(StringRef Token, bool IsIsolatedToken = false); }; /// SubtargetFeatureInfo - Helper class for storing information on a subtarget @@ -565,16 +606,16 @@ struct SubtargetFeatureInfo { Record *TheDef; /// \brief An unique index assigned to represent this feature. - unsigned Index; + uint64_t Index; - SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} /// \brief The name of the enumerated constant identifying this feature. std::string getEnumName() const { return "Feature_" + TheDef->getName(); } - void dump() { + void dump() const { errs() << getEnumName() << " " << Index << "\n"; TheDef->dump(); } @@ -582,10 +623,10 @@ struct SubtargetFeatureInfo { struct OperandMatchEntry { unsigned OperandMask; - MatchableInfo* MI; + const MatchableInfo* MI; ClassInfo *CI; - static OperandMatchEntry create(MatchableInfo* mi, ClassInfo *ci, + static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci, unsigned opMask) { OperandMatchEntry X; X.OperandMask = opMask; @@ -608,10 +649,10 @@ public: CodeGenTarget &Target; /// The classes which are needed for matching. - std::vector Classes; + std::forward_list Classes; /// The information on the matchables to match. - std::vector Matchables; + std::vector> Matchables; /// Info for custom matching operands by user defined methods. std::vector OperandMatchInfo; @@ -621,7 +662,7 @@ public: RegisterClassesTy RegisterClasses; /// Map of Predicate records to their subtarget information. - std::map SubtargetFeatures; + std::map SubtargetFeatures; /// Map of AsmOperandClass records to their class information. std::map AsmOperandClasses; @@ -644,7 +685,7 @@ private: /// buildRegisterClasses - Build the ClassInfo* instances for register /// classes. - void buildRegisterClasses(SmallPtrSet &SingletonRegisters); + void buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters); /// buildOperandClasses - Build the ClassInfo* instances for user defined /// operand classes. @@ -669,11 +710,10 @@ public: /// getSubtargetFeature - Lookup or create the subtarget feature info for the /// given operand. - SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { + const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - std::map::const_iterator I = - SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? nullptr : I->second; + const auto &I = SubtargetFeatures.find(Def); + return I == SubtargetFeatures.end() ? nullptr : &I->second; } RecordKeeper &getRecords() const { @@ -683,11 +723,11 @@ public: } // End anonymous namespace -void MatchableInfo::dump() { +void MatchableInfo::dump() const { errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n"; for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - AsmOperand &Op = AsmOperands[i]; + const AsmOperand &Op = AsmOperands[i]; errs() << " op[" << i << "] = " << Op.Class->ClassName << " - "; errs() << '\"' << Op.Token << "\"\n"; } @@ -735,8 +775,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { // Find the ResOperand that refers to the operand we're aliasing away // and update it to refer to the combined operand instead. - for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) { - ResOperand &Op = ResOperands[i]; + for (ResOperand &Op : ResOperands) { if (Op.Kind == ResOperand::RenderAsmOperand && Op.AsmOperandNum == (unsigned)SrcAsmOperand) { Op.AsmOperandNum = DstAsmOperand; @@ -747,8 +786,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand); // Adjust the ResOperand references to any AsmOperands that followed // the one we just deleted. - for (unsigned i = 0, e = ResOperands.size(); i != e; ++i) { - ResOperand &Op = ResOperands[i]; + for (ResOperand &Op : ResOperands) { switch(Op.Kind) { default: // Nothing to do for operands that don't reference AsmOperands. @@ -765,26 +803,77 @@ 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, - SmallPtrSet &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix) { - AsmVariantID = AsmVariantNo; + SmallPtrSetImpl &SingletonRegisters, + AsmVariantInfo const &Variant, + bool HasMnemonicFirst) { + AsmVariantID = Variant.AsmVariantNo; AsmString = - CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); + CodeGenInstruction::FlattenAsmStringVariants(AsmString, + Variant.AsmVariantNo); + + tokenizeAsmString(Info, Variant); + + // 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"); - tokenizeAsmString(Info); + assert(!AsmOperands[0].Token.empty()); + if (HasMnemonicFirst) { + Mnemonic = AsmOperands[0].Token; + 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()); + } else if (AsmOperands[0].Token[0] != '$') + Mnemonic = AsmOperands[0].Token; // Compute the require features. - std::vector Predicates =TheDef->getValueAsListOfDefs("Predicates"); - for (unsigned i = 0, e = Predicates.size(); i != e; ++i) - if (SubtargetFeatureInfo *Feature = - Info.getSubtargetFeature(Predicates[i])) + for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates")) + if (const SubtargetFeatureInfo *Feature = + 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, Variant.RegisterPrefix); + if (Record *Reg = Op.SingletonReg) SingletonRegisters.insert(Reg); } @@ -796,93 +885,94 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false; } +/// Append an AsmOperand for the given substring of AsmString. +void MatchableInfo::addAsmOperand(StringRef Token, bool IsIsolatedToken) { + AsmOperands.push_back(AsmOperand(IsIsolatedToken, Token)); +} + /// 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; - for (unsigned i = 0, e = String.size(); i != e; ++i) { - switch (String[i]) { - case '[': - case ']': - case '*': - case '!': - case ' ': - case '\t': - case ',': + size_t Prev = 0; + bool InTok = false; + bool IsIsolatedToken = true; + for (size_t i = 0, e = String.size(); i != e; ++i) { + char Char = String[i]; + if (Variant.BreakCharacters.find(Char) != std::string::npos) { + if (InTok) { + addAsmOperand(String.slice(Prev, i), false); + Prev = i; + IsIsolatedToken = false; + } + InTok = true; + continue; + } + if (Variant.TokenizingCharacters.find(Char) != std::string::npos) { if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(String.slice(Prev, i), IsIsolatedToken); InTok = false; + IsIsolatedToken = false; } - if (!isspace(String[i]) && String[i] != ',') - AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + addAsmOperand(String.slice(i, i + 1), IsIsolatedToken); Prev = i + 1; - break; + IsIsolatedToken = true; + continue; + } + if (Variant.SeparatorCharacters.find(Char) != std::string::npos) { + if (InTok) { + addAsmOperand(String.slice(Prev, i), IsIsolatedToken); + InTok = false; + } + Prev = i + 1; + IsIsolatedToken = true; + continue; + } + switch (Char) { case '\\': if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(String.slice(Prev, i), false); InTok = false; + IsIsolatedToken = false; } ++i; assert(i != String.size() && "Invalid quoted character"); - AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + addAsmOperand(String.slice(i, i + 1), IsIsolatedToken); Prev = i + 1; + IsIsolatedToken = false; break; case '$': { if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(String.slice(Prev, i), false); InTok = false; + IsIsolatedToken = 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; } - 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))); + size_t EndPos = String.find('}', i); + assert(EndPos != StringRef::npos && + "Missing brace in operand reference!"); + addAsmOperand(String.slice(i, EndPos+1), IsIsolatedToken); Prev = EndPos + 1; i = EndPos; + IsIsolatedToken = false; 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; + break; } } if (InTok && Prev != String.size()) - AsmOperands.push_back(AsmOperand(String.substr(Prev))); - - // 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()); + addAsmOperand(String.substr(Prev), IsIsolatedToken); } bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { @@ -912,8 +1002,8 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { // Also, check for instructions which reference the operand multiple times; // this implies a constraint we would not honor. std::set OperandNames; - for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - StringRef Tok = AsmOperands[i].Token; + for (const AsmOperand &Op : AsmOperands) { + StringRef Tok = Op.Token; if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) PrintFatalError(TheDef->getLoc(), "matchable with operand modifier '" + Tok + @@ -940,32 +1030,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; @@ -978,6 +1042,7 @@ static std::string getEnumNameForToken(StringRef Str) { case '.': Res += "_DOT_"; break; case '<': Res += "_LT_"; break; case '>': Res += "_GT_"; break; + case '-': Res += "_MINUS_"; break; default: if ((*it >= 'A' && *it <= 'Z') || (*it >= 'a' && *it <= 'z') || @@ -995,7 +1060,8 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { ClassInfo *&Entry = TokenClasses[Token]; if (!Entry) { - Entry = new ClassInfo(); + Classes.emplace_front(); + Entry = &Classes.front(); Entry->Kind = ClassInfo::Token; Entry->ClassName = "Token"; Entry->Name = "MCK_" + getEnumNameForToken(Token); @@ -1004,7 +1070,6 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { Entry->RenderMethod = ""; Entry->ParserMethod = ""; Entry->DiagnosticType = ""; - Classes.push_back(Entry); } return Entry; @@ -1075,11 +1140,9 @@ struct LessRegisterSet { }; void AsmMatcherInfo:: -buildRegisterClasses(SmallPtrSet &SingletonRegisters) { - const std::vector &Registers = - Target.getRegBank().getRegisters(); - ArrayRef RegClassList = - Target.getRegBank().getRegClasses(); +buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { + const auto &Registers = Target.getRegBank().getRegisters(); + auto &RegClassList = Target.getRegBank().getRegClasses(); typedef std::set RegisterSetSet; @@ -1087,15 +1150,12 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { RegisterSetSet RegisterSets; // Gather the defined sets. - for (ArrayRef::const_iterator it = - RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(RegisterSet( - (*it)->getOrder().begin(), (*it)->getOrder().end())); + for (const CodeGenRegisterClass &RC : RegClassList) + RegisterSets.insert( + RegisterSet(RC.getOrder().begin(), RC.getOrder().end())); // Add any required singleton sets. - for (SmallPtrSet::iterator it = SingletonRegisters.begin(), - ie = SingletonRegisters.end(); it != ie; ++it) { - Record *Rec = *it; + for (Record *Rec : SingletonRegisters) { RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); } @@ -1103,19 +1163,16 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map RegisterMap; - for (std::vector::const_iterator it = Registers.begin(), - ie = Registers.end(); it != ie; ++it) { - const CodeGenRegister &CGR = **it; + for (const CodeGenRegister &CGR : Registers) { // Compute the intersection of all sets containing this register. RegisterSet ContainingSet; - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it) { - if (!it->count(CGR.TheDef)) + for (const RegisterSet &RS : RegisterSets) { + if (!RS.count(CGR.TheDef)) continue; if (ContainingSet.empty()) { - ContainingSet = *it; + ContainingSet = RS; continue; } @@ -1123,7 +1180,7 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { std::swap(Tmp, ContainingSet); std::insert_iterator II(ContainingSet, ContainingSet.begin()); - std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II, + std::set_intersection(Tmp.begin(), Tmp.end(), RS.begin(), RS.end(), II, LessRecordByID()); } @@ -1136,39 +1193,35 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { // Construct the register classes. std::map RegisterSetClasses; unsigned Index = 0; - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it, ++Index) { - ClassInfo *CI = new ClassInfo(); + for (const RegisterSet &RS : RegisterSets) { + Classes.emplace_front(); + ClassInfo *CI = &Classes.front(); CI->Kind = ClassInfo::RegisterClass0 + Index; CI->ClassName = "Reg" + utostr(Index); CI->Name = "MCK_Reg" + utostr(Index); CI->ValueName = ""; CI->PredicateMethod = ""; // unused CI->RenderMethod = "addRegOperands"; - CI->Registers = *it; + CI->Registers = RS; // FIXME: diagnostic type. CI->DiagnosticType = ""; - Classes.push_back(CI); - RegisterSetClasses.insert(std::make_pair(*it, CI)); + RegisterSetClasses.insert(std::make_pair(RS, CI)); + ++Index; } // Find the superclasses; we could compute only the subgroup lattice edges, // but there isn't really a point. - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it) { - ClassInfo *CI = RegisterSetClasses[*it]; - for (RegisterSetSet::iterator it2 = RegisterSets.begin(), - ie2 = RegisterSets.end(); it2 != ie2; ++it2) - if (*it != *it2 && - std::includes(it2->begin(), it2->end(), it->begin(), it->end(), + for (const RegisterSet &RS : RegisterSets) { + ClassInfo *CI = RegisterSetClasses[RS]; + for (const RegisterSet &RS2 : RegisterSets) + if (RS != RS2 && + std::includes(RS2.begin(), RS2.end(), RS.begin(), RS.end(), LessRecordByID())) - CI->SuperClasses.push_back(RegisterSetClasses[*it2]); + CI->SuperClasses.push_back(RegisterSetClasses[RS2]); } // Name the register classes which correspond to a user defined RegisterClass. - for (ArrayRef::const_iterator - it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { - const CodeGenRegisterClass &RC = **it; + for (const CodeGenRegisterClass &RC : RegClassList) { // Def will be NULL for non-user defined register classes. Record *Def = RC.getDef(); if (!Def) @@ -1191,9 +1244,7 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (SmallPtrSet::iterator it = SingletonRegisters.begin(), - ie = SingletonRegisters.end(); it != ie; ++it) { - Record *Rec = *it; + for (Record *Rec : SingletonRegisters) { ClassInfo *CI = RegisterClasses[Rec]; assert(CI && "Missing singleton register class info!"); @@ -1211,36 +1262,36 @@ void AsmMatcherInfo::buildOperandClasses() { Records.getAllDerivedDefinitions("AsmOperandClass"); // Pre-populate AsmOperandClasses map. - for (std::vector::iterator it = AsmOperands.begin(), - ie = AsmOperands.end(); it != ie; ++it) - AsmOperandClasses[*it] = new ClassInfo(); + for (Record *Rec : AsmOperands) { + Classes.emplace_front(); + AsmOperandClasses[Rec] = &Classes.front(); + } unsigned Index = 0; - for (std::vector::iterator it = AsmOperands.begin(), - ie = AsmOperands.end(); it != ie; ++it, ++Index) { - ClassInfo *CI = AsmOperandClasses[*it]; + for (Record *Rec : AsmOperands) { + ClassInfo *CI = AsmOperandClasses[Rec]; CI->Kind = ClassInfo::UserClass0 + Index; - ListInit *Supers = (*it)->getValueAsListInit("SuperClasses"); - for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) { - DefInit *DI = dyn_cast(Supers->getElement(i)); + ListInit *Supers = Rec->getValueAsListInit("SuperClasses"); + for (Init *I : Supers->getValues()) { + DefInit *DI = dyn_cast(I); if (!DI) { - PrintError((*it)->getLoc(), "Invalid super class reference!"); + PrintError(Rec->getLoc(), "Invalid super class reference!"); continue; } ClassInfo *SC = AsmOperandClasses[DI->getDef()]; if (!SC) - PrintError((*it)->getLoc(), "Invalid super class reference!"); + PrintError(Rec->getLoc(), "Invalid super class reference!"); else CI->SuperClasses.push_back(SC); } - CI->ClassName = (*it)->getValueAsString("Name"); + CI->ClassName = Rec->getValueAsString("Name"); CI->Name = "MCK_" + CI->ClassName; - CI->ValueName = (*it)->getName(); + CI->ValueName = Rec->getName(); // Get or construct the predicate method name. - Init *PMName = (*it)->getValueInit("PredicateMethod"); + Init *PMName = Rec->getValueInit("PredicateMethod"); if (StringInit *SI = dyn_cast(PMName)) { CI->PredicateMethod = SI->getValue(); } else { @@ -1249,7 +1300,7 @@ void AsmMatcherInfo::buildOperandClasses() { } // Get or construct the render method name. - Init *RMName = (*it)->getValueInit("RenderMethod"); + Init *RMName = Rec->getValueInit("RenderMethod"); if (StringInit *SI = dyn_cast(RMName)) { CI->RenderMethod = SI->getValue(); } else { @@ -1258,18 +1309,17 @@ void AsmMatcherInfo::buildOperandClasses() { } // Get the parse method name or leave it as empty. - Init *PRMName = (*it)->getValueInit("ParserMethod"); + Init *PRMName = Rec->getValueInit("ParserMethod"); if (StringInit *SI = dyn_cast(PRMName)) CI->ParserMethod = SI->getValue(); // Get the diagnostic type or leave it as empty. // Get the parse method name or leave it as empty. - Init *DiagnosticType = (*it)->getValueInit("DiagnosticType"); + Init *DiagnosticType = Rec->getValueInit("DiagnosticType"); if (StringInit *SI = dyn_cast(DiagnosticType)) CI->DiagnosticType = SI->getValue(); - AsmOperandClasses[*it] = CI; - Classes.push_back(CI); + ++Index; } } @@ -1288,16 +1338,13 @@ void AsmMatcherInfo::buildOperandMatchInfo() { typedef std::map> OpClassMaskTy; OpClassMaskTy OpClassMask; - for (std::vector::const_iterator it = - Matchables.begin(), ie = Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; + for (const auto &MI : Matchables) { OpClassMask.clear(); // Keep track of all operands of this instructions which belong to the // same class. - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { + const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i]; if (Op.Class->ParserMethod.empty()) continue; unsigned &OperandMask = OpClassMask[Op.Class]; @@ -1305,11 +1352,11 @@ void AsmMatcherInfo::buildOperandMatchInfo() { } // Generate operand match info for each mnemonic/operand class pair. - for (OpClassMaskTy::iterator iit = OpClassMask.begin(), - iie = OpClassMask.end(); iit != iie; ++iit) { - unsigned OpMask = iit->second; - ClassInfo *CI = iit->first; - OperandMatchInfo.push_back(OperandMatchEntry::create(&II, CI, OpMask)); + for (const auto &OCM : OpClassMask) { + unsigned OpMask = OCM.second; + ClassInfo *CI = OCM.first; + OperandMatchInfo.push_back(OperandMatchEntry::create(MI.get(), CI, + OpMask)); } } } @@ -1318,8 +1365,7 @@ void AsmMatcherInfo::buildInfo() { // Build information about all of the AssemblerPredicates. std::vector AllPredicates = Records.getAllDerivedDefinitions("Predicate"); - for (unsigned i = 0, e = AllPredicates.size(); i != e; ++i) { - Record *Pred = AllPredicates[i]; + for (Record *Pred : AllPredicates) { // Ignore predicates that are not intended for the assembler. if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) continue; @@ -1327,12 +1373,14 @@ void AsmMatcherInfo::buildInfo() { if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - unsigned FeatureNo = SubtargetFeatures.size(); - SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); - DEBUG(SubtargetFeatures[Pred]->dump()); - assert(FeatureNo < 32 && "Too many subtarget features!"); + SubtargetFeatures.insert(std::make_pair( + Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()))); + DEBUG(SubtargetFeatures.find(Pred)->second.dump()); + assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); } + bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst"); + // Parse the instructions; we need to do this first so that we can gather the // singleton register classes. SmallPtrSet SingletonRegisters; @@ -1341,39 +1389,37 @@ void AsmMatcherInfo::buildInfo() { Record *AsmVariant = Target.getAsmParserVariant(VC); std::string CommentDelimiter = AsmVariant->getValueAsString("CommentDelimiter"); - std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); - int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - const CodeGenInstruction &CGI = **I; + AsmVariantInfo Variant; + Variant.RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); + Variant.TokenizingCharacters = + AsmVariant->getValueAsString("TokenizingCharacters"); + Variant.SeparatorCharacters = + AsmVariant->getValueAsString("SeparatorCharacters"); + Variant.BreakCharacters = + AsmVariant->getValueAsString("BreakCharacters"); + Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant"); + + for (const CodeGenInstruction *CGI : Target.instructions()) { // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instructions we consider. - if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) + if (!StringRef(CGI->TheDef->getName()).startswith(MatchPrefix)) continue; // Ignore "codegen only" instructions. - if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) + 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, Variant, HasMnemonicFirst); // Ignore instructions which shouldn't be matched and diagnose invalid // instruction definitions with an error. if (!II->validate(CommentDelimiter, true)) continue; - // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. - // - // FIXME: This is a total hack. - if (StringRef(II->TheDef->getName()).startswith("Int_") || - StringRef(II->TheDef->getName()).endswith("_Int")) - continue; - - Matchables.push_back(II.release()); + Matchables.push_back(std::move(II)); } // Parse all of the InstAlias definitions and stick them in the list of @@ -1381,8 +1427,9 @@ void AsmMatcherInfo::buildInfo() { std::vector AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { - CodeGenInstAlias *Alias = - new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target); + auto Alias = llvm::make_unique(AllInstAliases[i], + Variant.AsmVariantNo, + Target); // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instruction aliases we consider, based on the target @@ -1391,14 +1438,14 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - std::unique_ptr II(new MatchableInfo(Alias)); + auto II = llvm::make_unique(std::move(Alias)); - II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst); // Validate the alias definitions. II->validate(CommentDelimiter, false); - Matchables.push_back(II.release()); + Matchables.push_back(std::move(II)); } } @@ -1410,11 +1457,8 @@ void AsmMatcherInfo::buildInfo() { // Build the information about matchables, now that we have fully formed // classes. - std::vector NewMatchables; - for (std::vector::iterator it = Matchables.begin(), - ie = Matchables.end(); it != ie; ++it) { - MatchableInfo *II = *it; - + std::vector> NewMatchables; + for (auto &II : Matchables) { // Parse the tokens after the mnemonic. // Note: buildInstructionOperandReference may insert new AsmOperands, so // don't precompute the loop bound. @@ -1423,7 +1467,7 @@ void AsmMatcherInfo::buildInfo() { StringRef Token = Op.Token; // Check for singleton registers. - if (Record *RegRecord = II->AsmOperands[i].SingletonReg) { + if (Record *RegRecord = Op.SingletonReg) { Op.Class = RegisterClasses[RegRecord]; assert(Op.Class && Op.Class->Registers.size() == 1 && "Unexpected class for singleton register"); @@ -1449,9 +1493,9 @@ void AsmMatcherInfo::buildInfo() { OperandName = Token.substr(1); if (II->DefRec.is()) - buildInstructionOperandReference(II, OperandName, i); + buildInstructionOperandReference(II.get(), OperandName, i); else - buildAliasOperandReference(II, OperandName, Op); + buildAliasOperandReference(II.get(), OperandName, Op); } if (II->DefRec.is()) { @@ -1463,27 +1507,27 @@ 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); // Add the alias to the matchables list. - NewMatchables.push_back(AliasII.release()); + NewMatchables.push_back(std::move(AliasII)); } } else II->buildAliasResultOperands(); } if (!NewMatchables.empty()) - Matchables.insert(Matchables.end(), NewMatchables.begin(), - NewMatchables.end()); + 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. std::vector AllTokenAliases = Records.getAllDerivedDefinitions("TokenAlias"); - for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) { - Record *Rec = AllTokenAliases[i]; + for (Record *Rec : AllTokenAliases) { ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); if (FromClass == ToClass) @@ -1493,7 +1537,7 @@ void AsmMatcherInfo::buildInfo() { } // Reorder classes so that classes precede super classes. - std::sort(Classes.begin(), Classes.end(), less_ptr()); + Classes.sort(); } /// buildInstructionOperandReference - The specified operand is a reference to a @@ -1523,7 +1567,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); } @@ -1591,9 +1635,7 @@ void MatchableInfo::buildInstructionResultOperands() { // Loop over all operands of the result instruction, determining how to // populate them. - for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { - const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; - + for (const CGIOperandList::OperandInfo &OpInfo : ResultInst->Operands) { // If this is a tied operand, just copy from the previously handled operand. int TiedOp = -1; if (OpInfo.MINumOperands == 1) @@ -1689,7 +1731,7 @@ void MatchableInfo::buildAliasResultOperands() { } static unsigned getConverterOperandID(const std::string &Name, - SetVector &Table, + SmallSetVector &Table, bool &IsNew) { IsNew = Table.insert(Name); @@ -1703,10 +1745,10 @@ static unsigned getConverterOperandID(const std::string &Name, static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, - std::vector &Infos, - raw_ostream &OS) { - SetVector OperandConversionKinds; - SetVector InstructionConversionKinds; + std::vector> &Infos, + bool HasMnemonicFirst, raw_ostream &OS) { + SmallSetVector OperandConversionKinds; + SmallSetVector InstructionConversionKinds; std::vector > ConversionTable; size_t MaxRowLength = 2; // minimum is custom converter plus terminator. @@ -1767,16 +1809,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, OperandConversionKinds.insert("CVT_Tied"); enum { CVT_Done, CVT_Reg, CVT_Tied }; - for (std::vector::const_iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - MatchableInfo &II = **it; - + for (auto &II : Infos) { // Check if we have a custom match function. std::string AsmMatchConverter = - II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); - if (!AsmMatchConverter.empty()) { + II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); + if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) { std::string Signature = "ConvertCustom_" + AsmMatchConverter; - II.ConversionFnKind = Signature; + II->ConversionFnKind = Signature; // Check if we have already generated this signature. if (!InstructionConversionKinds.insert(Signature)) @@ -1788,7 +1827,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); @@ -1808,16 +1847,17 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector ConversionRow; // Compute the convert enum and the case body. - MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 ); + MaxRowLength = std::max(MaxRowLength, II->ResOperands.size()*2 + 1 ); - for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { - const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; + for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) { + const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i]; // Generate code to populate each result operand. switch (OpInfo.Kind) { case MatchableInfo::ResOperand::RenderAsmOperand: { // This comes from something we parsed. - MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum]; + const MatchableInfo::AsmOperand &Op = + II->AsmOperands[OpInfo.AsmOperandNum]; // Registers are always converted the same, don't duplicate the // conversion function based on them. @@ -1840,7 +1880,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 + HasMnemonicFirst); if (!IsNewConverter) break; @@ -1879,6 +1919,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, case MatchableInfo::ResOperand::ImmOperand: { int64_t Val = OpInfo.ImmVal; std::string Ty = "imm_" + itostr(Val); + Ty = getEnumNameForToken(Ty); Signature += "__" + Ty; std::string Name = "CVT_" + Ty; @@ -1893,7 +1934,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" @@ -1924,7 +1965,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" @@ -1940,7 +1981,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, if (Signature == "Convert") Signature += "_NoOperands"; - II.ConversionFnKind = Signature; + II->ConversionFnKind = Signature; // Save the signature. If we already have it, don't add a new row // to the table. @@ -1948,7 +1989,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. @@ -1961,17 +2002,15 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Output the operand conversion kind enum. OS << "enum OperatorConversionKind {\n"; - for (unsigned i = 0, e = OperandConversionKinds.size(); i != e; ++i) - OS << " " << OperandConversionKinds[i] << ",\n"; + for (const std::string &Converter : OperandConversionKinds) + OS << " " << Converter << ",\n"; OS << " CVT_NUM_CONVERTERS\n"; OS << "};\n\n"; // 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"; @@ -2003,7 +2042,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, /// emitMatchClassEnumeration - Emit the enumeration for match class kinds. static void emitMatchClassEnumeration(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { OS << "namespace {\n\n"; @@ -2011,9 +2050,7 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target, << "/// instruction matching.\n"; OS << "enum MatchClassKind {\n"; OS << " InvalidMatchClass = 0,\n"; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &CI = **it; + for (const auto &CI : Infos) { OS << " " << CI.Name << ", // "; if (CI.Kind == ClassInfo::Token) { OS << "'" << CI.ValueName << "'\n"; @@ -2053,10 +2090,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, // Check the user classes. We don't care what order since we're only // actually matching against one of them. - for (std::vector::iterator it = Info.Classes.begin(), - ie = Info.Classes.end(); it != ie; ++it) { - ClassInfo &CI = **it; - + for (const auto &CI : Info.Classes) { if (!CI.isUserClass()) continue; @@ -2075,11 +2109,9 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, OS << " MatchClassKind OpKind;\n"; OS << " switch (Operand.getReg()) {\n"; OS << " default: OpKind = InvalidMatchClass; break;\n"; - for (AsmMatcherInfo::RegisterClassesTy::iterator - it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end(); - it != ie; ++it) + for (const auto &RC : Info.RegisterClasses) OS << " case " << Info.Target.getName() << "::" - << it->first->getName() << ": OpKind = " << it->second->Name + << RC.first->getName() << ": OpKind = " << RC.second->Name << "; break;\n"; OS << " }\n"; OS << " return isSubclass(OpKind, Kind) ? " @@ -2094,60 +2126,55 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, /// emitIsSubclass - Emit the subclass predicate function. static void emitIsSubclass(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n"; OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n"; OS << " if (A == B)\n"; OS << " return true;\n\n"; - std::string OStr; - raw_string_ostream SS(OStr); - unsigned Count = 0; - SS << " switch (A) {\n"; - SS << " default:\n"; - SS << " return false;\n"; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &A = **it; - + bool EmittedSwitch = false; + for (const auto &A : Infos) { std::vector SuperClasses; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &B = **it; - + for (const auto &B : Infos) { if (&A != &B && A.isSubsetOf(B)) SuperClasses.push_back(B.Name); } if (SuperClasses.empty()) continue; - ++Count; - SS << "\n case " << A.Name << ":\n"; + // If this is the first SuperClass, emit the switch header. + if (!EmittedSwitch) { + OS << " switch (A) {\n"; + OS << " default:\n"; + OS << " return false;\n"; + EmittedSwitch = true; + } + + OS << "\n case " << A.Name << ":\n"; if (SuperClasses.size() == 1) { - SS << " return B == " << SuperClasses.back().str() << ";\n"; + OS << " return B == " << SuperClasses.back() << ";\n"; continue; } if (!SuperClasses.empty()) { - SS << " switch (B) {\n"; - SS << " default: return false;\n"; - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - SS << " case " << SuperClasses[i].str() << ": return true;\n"; - SS << " }\n"; + OS << " switch (B) {\n"; + OS << " default: return false;\n"; + for (StringRef SC : SuperClasses) + OS << " case " << SC << ": return true;\n"; + OS << " }\n"; } else { // No case statement to emit - SS << " return false;\n"; + OS << " return false;\n"; } } - SS << " }\n"; - // If there were case statements emitted into the string stream, write them - // to the output stream, otherwise write the default. - if (Count) - OS << SS.str(); + // If there were case statements emitted into the string stream write the + // default. + if (EmittedSwitch) + OS << " }\n"; else OS << " return false;\n"; @@ -2157,17 +2184,13 @@ static void emitIsSubclass(CodeGenTarget &Target, /// emitMatchTokenString - Emit the function to match a token string to the /// appropriate match class value. static void emitMatchTokenString(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { // Construct the match list. std::vector Matches; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &CI = **it; - + 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"; @@ -2184,16 +2207,13 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, raw_ostream &OS) { // Construct the match list. std::vector Matches; - const std::vector &Regs = - Target.getRegBank().getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - if (Reg->TheDef->getValueAsString("AsmName").empty()) + const auto &Regs = Target.getRegBank().getRegisters(); + for (const CodeGenRegister &Reg : Regs) { + 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"; @@ -2205,7 +2225,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, } static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFFFFFFULL) + return "uint64_t"; if (Range > 0xFFFF) return "uint32_t"; if (Range > 0xFF) @@ -2228,11 +2250,9 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) << " {\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2242,19 +2262,16 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { // Get the set of diagnostic types from all of the operand classes. std::set Types; - for (std::map::const_iterator - I = Info.AsmOperandClasses.begin(), - E = Info.AsmOperandClasses.end(); I != E; ++I) { - if (!I->second->DiagnosticType.empty()) - Types.insert(I->second->DiagnosticType); + for (const auto &OpClassEntry : Info.AsmOperandClasses) { + if (!OpClassEntry.second->DiagnosticType.empty()) + Types.insert(OpClassEntry.second->DiagnosticType); } if (Types.empty()) return; // Now emit the enum entries. - for (std::set::const_iterator I = Types.begin(), E = Types.end(); - I != E; ++I) - OS << " Match_" << *I << ",\n"; + for (StringRef Type : Types) + OS << " Match_" << Type << ",\n"; OS << " END_OPERAND_DIAGNOSTIC_TYPES\n"; } @@ -2263,13 +2280,11 @@ static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// User-level names for subtarget features that participate in\n" << "// instruction matching.\n" - << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; + << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; - typedef std::map RecFeatMap; - for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; // FIXME: Totally just a placeholder name to get the algorithm working. OS << " case " << SFI.getEnumName() << ": return \"" << SFI.TheDef->getValueAsString("PredicateName") << "\";\n"; @@ -2290,13 +2305,11 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(uint64_t FB) const {\n"; - OS << " unsigned Features = 0;\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" + << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; + OS << " uint64_t Features = 0;\n"; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; OS << " if ("; std::string CondStorage = @@ -2315,12 +2328,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; @@ -2342,7 +2353,7 @@ static std::string GetAliasRequiredFeatures(Record *R, std::string Result; unsigned NumFeatures = 0; for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { - SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); + const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); if (!F) PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + @@ -2368,8 +2379,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, // iteration order of the map is stable. std::map > AliasesFromMnemonic; - for (unsigned i = 0, e = Aliases.size(); i != e; ++i) { - Record *R = Aliases[i]; + for (Record *R : Aliases) { // FIXME: Allow AssemblerVariantName to be a comma separated list. std::string AsmVariantName = R->getValueAsString("AsmVariantName"); if (AsmVariantName != AsmParserVariantName) @@ -2382,10 +2392,8 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, // Process each alias a "from" mnemonic at a time, building the code executed // by the string remapper. std::vector Cases; - for (std::map >::iterator - I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end(); - I != E; ++I) { - const std::vector &ToVec = I->second; + for (const auto &AliasEntry : AliasesFromMnemonic) { + const std::vector &ToVec = AliasEntry.second; // Loop through each alias and emit code that handles each case. If there // are two instructions without predicates, emit an error. If there is one, @@ -2410,7 +2418,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, AliasWithNoPredicate = i; continue; } - if (R->getValueAsString("ToMnemonic") == I->first) + if (R->getValueAsString("ToMnemonic") == AliasEntry.first) PrintFatalError(R->getLoc(), "MnemonicAlias to the same string"); if (!MatchCode.empty()) @@ -2428,7 +2436,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, MatchCode += "return;"; - Cases.push_back(std::make_pair(I->first, MatchCode)); + Cases.push_back(std::make_pair(AliasEntry.first, MatchCode)); } StringMatcher("Mnemonic", Cases, OS).Emit(Indent); } @@ -2446,7 +2454,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "unsigned Features, unsigned VariantID) {\n"; + "uint64_t Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2471,12 +2479,10 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, const AsmMatcherInfo &Info, StringRef ClassName, StringToOffsetTable &StringTable, - unsigned MaxMnemonicIndex) { + unsigned MaxMnemonicIndex, bool HasMnemonicFirst) { unsigned MaxMask = 0; - for (std::vector::const_iterator it = - Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); - it != ie; ++it) { - MaxMask |= it->OperandMask; + for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) { + MaxMask |= OMI.OperandMask; } // Emit the static custom operand parsing table; @@ -2486,8 +2492,8 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; - OS << " " << getMinimalTypeForRange(Info.Classes.size()) - << " Class;\n"; + OS << " " << getMinimalTypeForRange(std::distance( + Info.Classes.begin(), Info.Classes.end())) << " Class;\n"; OS << " " << getMinimalTypeForRange(MaxMask) << " OperandMask;\n\n"; OS << " StringRef getMnemonic() const {\n"; @@ -2516,10 +2522,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << Info.OperandMatchInfo.size() << "] = {\n"; OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n"; - for (std::vector::const_iterator it = - Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); - it != ie; ++it) { - const OperandMatchEntry &OMI = *it; + for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) { const MatchableInfo &II = *OMI.MI; OS << " { "; @@ -2564,13 +2567,11 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; - for (std::vector::const_iterator it = Info.Classes.begin(), - ie = Info.Classes.end(); it != ie; ++it) { - ClassInfo *CI = *it; - if (CI->ParserMethod.empty()) + for (const auto &CI : Info.Classes) { + if (CI.ParserMethod.empty()) continue; - OS << " case " << CI->Name << ":\n" - << " return " << CI->ParserMethod << "(Operands);\n"; + OS << " case " << CI.Name << ":\n" + << " return " << CI.ParserMethod << "(Operands);\n"; } OS << " default:\n"; @@ -2589,18 +2590,28 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + 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()" + << (HasMnemonicFirst ? " - 1" : "") << ";\n"; // Emit code to search the table. OS << " // Search the table.\n"; - OS << " std::pair"; - OS << " MnemonicRange =\n"; - OS << " std::equal_range(OperandMatchTable, OperandMatchTable+" - << Info.OperandMatchInfo.size() << ", Mnemonic,\n" - << " LessOpcodeOperand());\n\n"; + if (HasMnemonicFirst) { + OS << " auto MnemonicRange =\n"; + OS << " std::equal_range(std::begin(OperandMatchTable), " + "std::end(OperandMatchTable),\n"; + OS << " Mnemonic, LessOpcodeOperand());\n\n"; + } else { + OS << " auto MnemonicRange = std::make_pair(std::begin(OperandMatchTable)," + " std::end(OperandMatchTable));\n"; + OS << " if (!Mnemonic.empty())\n"; + OS << " MnemonicRange =\n"; + OS << " std::equal_range(std::begin(OperandMatchTable), " + "std::end(OperandMatchTable),\n"; + OS << " Mnemonic, LessOpcodeOperand());\n\n"; + } OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; OS << " return MatchOperand_NoMatch;\n\n"; @@ -2649,22 +2660,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), - less_ptr()); + [](const std::unique_ptr &a, + const std::unique_ptr &b){ + return *a < *b;}); DEBUG_WITH_TYPE("instruction_info", { - for (std::vector::iterator - it = Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) - (*it)->dump(); + for (const auto &MI : Info.Matchables) + MI->dump(); }); // Check for ambiguous matchables. DEBUG_WITH_TYPE("ambiguous_instrs", { unsigned NumAmbiguous = 0; - for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) { - for (unsigned j = i + 1; j != e; ++j) { - MatchableInfo &A = *Info.Matchables[i]; - MatchableInfo &B = *Info.Matchables[j]; + for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E; + ++I) { + for (auto J = std::next(I); J != E; ++J) { + const MatchableInfo &A = **I; + const MatchableInfo &B = **J; if (A.couldMatchAmbiguouslyWith(B)) { errs() << "warning: ambiguous matchables:\n"; @@ -2684,6 +2696,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Compute the information on the custom operand parsing. Info.buildOperandMatchInfo(); + bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst"); + // Write the output. // Information for the class declaration. @@ -2691,23 +2705,22 @@ 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 << " unsigned 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 " << "&Operands);\n"; OS << " void convertToMapAndConstraints(unsigned Kind,\n "; OS << " const OperandVector &Operands) override;\n"; - OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n"; - OS << " unsigned MatchInstructionImpl(\n"; - OS.indent(27); - OS << "const OperandVector &Operands,\n" + if (HasMnemonicFirst) + OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n"; + OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" << " MCInst &Inst,\n" - << " unsigned &ErrorInfo," + << " uint64_t &ErrorInfo," << " 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"; @@ -2761,7 +2774,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Generate the convertToMCInst function to convert operands into an MCInst. // Also, generate the convertToMapAndConstraints function for MS-style inline // assembly. The latter doesn't actually generate a MCInst. - emitConvertFuncs(Target, ClassName, Info.Matchables, OS); + emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst, OS); // Emit the enumeration for classes which participate in matching. emitMatchClassEnumeration(Target, Info.Classes, OS); @@ -2784,15 +2797,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { size_t MaxNumOperands = 0; unsigned MaxMnemonicIndex = 0; bool HasDeprecation = false; - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; - MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size()); - HasDeprecation |= II.HasDeprecation; + for (const auto &MI : Info.Matchables) { + MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size()); + HasDeprecation |= MI->HasDeprecation; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); MaxMnemonicIndex = std::max(MaxMnemonicIndex, StringTable.GetOrAddStringOffset(LenMnemonic, false)); } @@ -2820,8 +2830,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " ConvertFn;\n"; OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; - OS << " " << getMinimalTypeForRange(Info.Classes.size()) - << " Classes[" << MaxNumOperands << "];\n"; + OS << " " << getMinimalTypeForRange( + std::distance(Info.Classes.begin(), Info.Classes.end())) + << " Classes[" << MaxNumOperands << "];\n"; OS << " StringRef getMnemonic() const {\n"; OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; OS << " MnemonicTable[Mnemonic]);\n"; @@ -2850,33 +2861,30 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; - if (II.AsmVariantID != AsmVariantNo) + for (const auto &MI : Info.Matchables) { + if (MI->AsmVariantID != AsmVariantNo) continue; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) - << " /* " << II.Mnemonic << " */, " + << " /* " << MI->Mnemonic << " */, " << Target.getName() << "::" - << II.getResultInst()->TheDef->getName() << ", " - << II.ConversionFnKind << ", "; + << MI->getResultInst()->TheDef->getName() << ", " + << MI->ConversionFnKind << ", "; // Write the required features mask. - if (!II.RequiredFeatures.empty()) { - for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (!MI->RequiredFeatures.empty()) { + for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) { if (i) OS << "|"; - OS << II.RequiredFeatures[i]->getEnumName(); + OS << MI->RequiredFeatures[i]->getEnumName(); } } else OS << "0"; OS << ", { "; - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { + const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i]; if (i) OS << ", "; OS << Op.Class->Name; @@ -2888,45 +2896,55 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { } // A method to determine if a mnemonic is in the list. - OS << "bool " << Target.getName() << ClassName << "::\n" - << "mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n"; - OS << " // Find the appropriate table for this asm variant.\n"; - OS << " const MatchEntry *Start, *End;\n"; - OS << " switch (VariantID) {\n"; - OS << " default: // unreachable\n"; - for (unsigned VC = 0; VC != VariantCount; ++VC) { - Record *AsmVariant = Target.getAsmParserVariant(VC); - int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC - << "); End = std::end(MatchTable" << VC << "); break;\n"; + if (HasMnemonicFirst) { + OS << "bool " << Target.getName() << ClassName << "::\n" + << "mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n"; + OS << " // Find the appropriate table for this asm variant.\n"; + OS << " const MatchEntry *Start, *End;\n"; + OS << " switch (VariantID) {\n"; + OS << " default: llvm_unreachable(\"invalid variant!\");\n"; + for (unsigned VC = 0; VC != VariantCount; ++VC) { + Record *AsmVariant = Target.getAsmParserVariant(VC); + int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); + OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC + << "); End = std::end(MatchTable" << VC << "); break;\n"; + } + OS << " }\n"; + OS << " // Search the table.\n"; + OS << " auto MnemonicRange = "; + OS << "std::equal_range(Start, End, Mnemonic, LessOpcode());\n"; + OS << " return MnemonicRange.first != MnemonicRange.second;\n"; + OS << "}\n\n"; } - OS << " }\n"; - OS << " // Search the table.\n"; - OS << " std::pair MnemonicRange =\n"; - OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n"; - OS << " return MnemonicRange.first != MnemonicRange.second;\n"; - OS << "}\n\n"; // Finally, build the match function. OS << "unsigned " << Target.getName() << ClassName << "::\n" - << "MatchInstructionImpl(const OperandVector" - << " &Operands,\n"; - OS << " MCInst &Inst,\n" - << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; + << "MatchInstructionImpl(const OperandVector &Operands,\n"; + OS << " MCInst &Inst, uint64_t &ErrorInfo,\n" + << " 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 + HasMnemonicFirst) << ") {\n"; + OS << " ErrorInfo = " + << (MaxNumOperands + HasMnemonicFirst) << ";\n"; OS << " return Match_InvalidOperand;\n"; OS << " }\n\n"; // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; - OS << " StringRef Mnemonic = ((" << Target.getName() - << "Operand&)*Operands[0]).getToken();\n\n"; + if (HasMnemonicFirst) { + OS << " StringRef Mnemonic = ((" << Target.getName() + << "Operand&)*Operands[0]).getToken();\n\n"; + } else { + OS << " StringRef Mnemonic;\n"; + OS << " if (Operands[0]->isToken())\n"; + OS << " Mnemonic = ((" << Target.getName() + << "Operand&)*Operands[0]).getToken();\n\n"; + } if (HasMnemonicAliases) { OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; @@ -2938,16 +2956,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " unsigned MissingFeatures = ~0U;\n"; + 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"; OS << " const MatchEntry *Start, *End;\n"; OS << " switch (VariantID) {\n"; - OS << " default: // unreachable\n"; + OS << " default: llvm_unreachable(\"invalid variant!\");\n"; for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); @@ -2955,9 +2973,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "); End = std::end(MatchTable" << VC << "); break;\n"; } OS << " }\n"; + OS << " // Search the table.\n"; - OS << " std::pair MnemonicRange =\n"; - OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n"; + if (HasMnemonicFirst) { + OS << " auto MnemonicRange = " + "std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n"; + } else { + OS << " auto MnemonicRange = std::make_pair(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"; @@ -2967,28 +2994,32 @@ 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"; + if (HasMnemonicFirst) { + 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 = " << (HasMnemonicFirst ? "0" : "SIndex") + << "; i != " << MaxNumOperands << "; ++i) {\n"; + OS << " auto Formal = static_cast(it->Classes[i]);\n"; + OS << " if (i" << (HasMnemonicFirst ? "+1" : "") + << " >= Operands.size()) {\n"; + OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n"; + OS << " if (!OperandsValid) ErrorInfo = i" + << (HasMnemonicFirst ? "+1" : "") << ";\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" + << (HasMnemonicFirst ? "+1" : "") << "];\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"; @@ -2997,8 +3028,9 @@ 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" + << (HasMnemonicFirst ? "+1" : "") << ")) {\n"; + OS << " ErrorInfo = i" << (HasMnemonicFirst ? "+1" : "") << ";\n"; OS << " // InvalidOperand is the default. Prefer specificity.\n"; OS << " if (Diag != Match_InvalidOperand)\n"; OS << " RetCode = Diag;\n"; @@ -3014,14 +3046,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if ((AvailableFeatures & it->RequiredFeatures) " << "!= it->RequiredFeatures) {\n"; OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " + OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" - " CountPopulation_32(MissingFeatures))\n"; + OS << " if (countPopulation(NewMissingFeatures) <=\n" + " countPopulation(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; OS << "\n"; + OS << " Inst.clear();\n\n"; OS << " if (matchingInlineAsm) {\n"; OS << " Inst.setOpcode(it->Opcode);\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; @@ -3052,10 +3085,10 @@ 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 << " Parser.Warning(Loc, Info, None);\n"; + OS << " getParser().Warning(Loc, Info, None);\n"; OS << " }\n"; } @@ -3070,9 +3103,9 @@ 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); + MaxMnemonicIndex, HasMnemonicFirst); OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n"; }