X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FAsmMatcherEmitter.cpp;h=3964330a4a84ab793007a8759cf54dd054e0d202;hb=47f0e3f434e2e43f951c3a826c40906cb15b7285;hp=92cf9534112bf128f8d6daebe06c3ec1cde44d9a;hpb=5f95140d02f90a2b5110ed8a4050918a6059064b;p=oota-llvm.git diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 92cf9534112..3964330a4a8 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; @@ -305,11 +310,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,14 +401,14 @@ struct MatchableInfo { /// AsmVariantID - Target's assembly syntax variant no. int AsmVariantID; - /// TheDef - This is the definition of the instruction or InstAlias that this - /// matchable came from. - Record *const TheDef; - /// 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; + /// DefRec - This is the definition that it came from. PointerUnion DefRec; @@ -433,15 +443,40 @@ 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), AsmString(CGI.AsmString), - DefRec(&CGI) {} + : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI), + UseInstAsmMatchConverter(true) { + } - MatchableInfo(std::unique_ptr Alias) - : AsmVariantID(0), TheDef(Alias->TheDef), AsmString(Alias->AsmString), - DefRec(Alias.release()) {} + MatchableInfo(std::unique_ptr Alias) + : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), + DefRec(Alias.release()), + UseInstAsmMatchConverter( + TheDef->getValueAsBit("UseInstAsmMatchConverter")) { + } - ~MatchableInfo() { delete DefRec.dyn_cast(); } + // 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 // operand as a tied operand of the first for purposes of the assembler. @@ -449,18 +484,12 @@ struct MatchableInfo { void initialize(const AsmMatcherInfo &Info, SmallPtrSetImpl &SingletonRegisters, - int AsmVariantNo, std::string &RegisterPrefix); + int AsmVariantNo, StringRef RegisterPrefix); /// 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 { @@ -556,6 +585,7 @@ struct MatchableInfo { private: void tokenizeAsmString(const AsmMatcherInfo &Info); + void addAsmOperand(size_t Start, size_t End); }; /// SubtargetFeatureInfo - Helper class for storing information on a subtarget @@ -611,7 +641,7 @@ public: std::forward_list Classes; /// The information on the matchables to match. - std::forward_list Matchables; + std::vector> Matchables; /// Info for custom matching operands by user defined methods. std::vector OperandMatchInfo; @@ -764,9 +794,41 @@ 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) { AsmVariantID = AsmVariantNo; AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); @@ -774,16 +836,15 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, tokenizeAsmString(Info); // 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); } @@ -795,12 +856,25 @@ 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) { + StringRef String = AsmString; + StringRef Separators = "[]*! \t,"; + // 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) { StringRef String = AsmString; - unsigned Prev = 0; + size_t Prev = 0; bool InTok = true; - for (unsigned i = 0, e = String.size(); i != e; ++i) { + for (size_t i = 0, e = String.size(); i != e; ++i) { switch (String[i]) { case '[': case ']': @@ -810,41 +884,42 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { case '\t': case ',': if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(Prev, i); InTok = false; } if (!isspace(String[i]) && String[i] != ',') - AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + addAsmOperand(i, i + 1); Prev = i + 1; break; case '\\': if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(Prev, i); InTok = false; } ++i; assert(i != String.size() && "Invalid quoted character"); - AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + addAsmOperand(i, i + 1); Prev = i + 1; break; case '$': { if (InTok) { - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(Prev, i); 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; } - 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))); + // If this is "${" find the next "}" and make an identifier like "${xxx}" + size_t EndPos = String.find('}', i); + assert(EndPos != StringRef::npos && + "Missing brace in operand reference!"); + addAsmOperand(i, EndPos+1); Prev = EndPos + 1; i = EndPos; break; @@ -853,7 +928,7 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { case '.': if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) { if (InTok) - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + addAsmOperand(Prev, i); Prev = i; } InTok = true; @@ -864,7 +939,7 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { } } if (InTok && Prev != String.size()) - AsmOperands.push_back(AsmOperand(String.substr(Prev))); + addAsmOperand(Prev, StringRef::npos); // The first token of the instruction is the mnemonic, which must be a // simple string, not a $foo variable or a singleton register. @@ -939,32 +1014,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; @@ -977,6 +1026,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') || @@ -1075,10 +1125,8 @@ struct LessRegisterSet { void AsmMatcherInfo:: buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { - const std::vector &Registers = - Target.getRegBank().getRegisters(); - ArrayRef RegClassList = - Target.getRegBank().getRegClasses(); + const auto &Registers = Target.getRegBank().getRegisters(); + auto &RegClassList = Target.getRegBank().getRegClasses(); typedef std::set RegisterSetSet; @@ -1086,9 +1134,9 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { RegisterSetSet RegisterSets; // Gather the defined sets. - for (const CodeGenRegisterClass *RC : RegClassList) - RegisterSets.insert(RegisterSet(RC->getOrder().begin(), - RC->getOrder().end())); + for (const CodeGenRegisterClass &RC : RegClassList) + RegisterSets.insert( + RegisterSet(RC.getOrder().begin(), RC.getOrder().end())); // Add any required singleton sets. for (Record *Rec : SingletonRegisters) { @@ -1099,12 +1147,12 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map RegisterMap; - for (const CodeGenRegister *CGR : Registers) { + for (const CodeGenRegister &CGR : Registers) { // Compute the intersection of all sets containing this register. RegisterSet ContainingSet; for (const RegisterSet &RS : RegisterSets) { - if (!RS.count(CGR->TheDef)) + if (!RS.count(CGR.TheDef)) continue; if (ContainingSet.empty()) { @@ -1122,7 +1170,7 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { if (!ContainingSet.empty()) { RegisterSets.insert(ContainingSet); - RegisterMap.insert(std::make_pair(CGR->TheDef, ContainingSet)); + RegisterMap.insert(std::make_pair(CGR.TheDef, ContainingSet)); } } @@ -1157,19 +1205,19 @@ buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { } // Name the register classes which correspond to a user defined RegisterClass. - for (const CodeGenRegisterClass *RC : RegClassList) { + for (const CodeGenRegisterClass &RC : RegClassList) { // Def will be NULL for non-user defined register classes. - Record *Def = RC->getDef(); + Record *Def = RC.getDef(); if (!Def) continue; - ClassInfo *CI = RegisterSetClasses[RegisterSet(RC->getOrder().begin(), - RC->getOrder().end())]; + ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(), + RC.getOrder().end())]; if (CI->ValueName.empty()) { - CI->ClassName = RC->getName(); - CI->Name = "MCK_" + RC->getName(); - CI->ValueName = RC->getName(); + CI->ClassName = RC.getName(); + CI->Name = "MCK_" + RC.getName(); + CI->ValueName = RC.getName(); } else - CI->ValueName = CI->ValueName + "," + RC->getName(); + CI->ValueName = CI->ValueName + "," + RC.getName(); RegisterClassClasses.insert(std::make_pair(Def, CI)); } @@ -1209,8 +1257,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; @@ -1279,8 +1327,8 @@ void AsmMatcherInfo::buildOperandMatchInfo() { // Keep track of all operands of this instructions which belong to the // same class. - for (unsigned i = 0, e = MI.AsmOperands.size(); i != e; ++i) { - const MatchableInfo::AsmOperand &Op = MI.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]; @@ -1291,7 +1339,8 @@ void AsmMatcherInfo::buildOperandMatchInfo() { for (const auto &OCM : OpClassMask) { unsigned OpMask = OCM.second; ClassInfo *CI = OCM.first; - OperandMatchInfo.push_back(OperandMatchEntry::create(&MI, CI, OpMask)); + OperandMatchInfo.push_back(OperandMatchEntry::create(MI.get(), CI, + OpMask)); } } } @@ -1337,15 +1386,16 @@ void AsmMatcherInfo::buildInfo() { if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; - Matchables.emplace_front(*CGI); - MatchableInfo *II = &Matchables.front(); + auto II = llvm::make_unique(*CGI); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); // Ignore instructions which shouldn't be matched and diagnose invalid // instruction definitions with an error. if (!II->validate(CommentDelimiter, true)) - Matchables.pop_front(); + continue; + + Matchables.push_back(std::move(II)); } // Parse all of the InstAlias definitions and stick them in the list of @@ -1363,13 +1413,14 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - Matchables.emplace_front(std::move(Alias)); - MatchableInfo *II = &Matchables.front(); + auto II = llvm::make_unique(std::move(Alias)); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); // Validate the alias definitions. II->validate(CommentDelimiter, false); + + Matchables.push_back(std::move(II)); } } @@ -1381,17 +1432,17 @@ void AsmMatcherInfo::buildInfo() { // Build the information about matchables, now that we have fully formed // classes. - std::forward_list NewMatchables; + 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. - for (unsigned i = 0; i != II.AsmOperands.size(); ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0; i != II->AsmOperands.size(); ++i) { + MatchableInfo::AsmOperand &Op = II->AsmOperands[i]; StringRef Token = Op.Token; // Check for singleton registers. - if (Record *RegRecord = II.AsmOperands[i].SingletonReg) { + if (Record *RegRecord = II->AsmOperands[i].SingletonReg) { Op.Class = RegisterClasses[RegRecord]; assert(Op.Class && Op.Class->Registers.size() == 1 && "Unexpected class for singleton register"); @@ -1416,30 +1467,36 @@ void AsmMatcherInfo::buildInfo() { else OperandName = Token.substr(1); - if (II.DefRec.is()) - buildInstructionOperandReference(&II, OperandName, i); + if (II->DefRec.is()) + buildInstructionOperandReference(II.get(), OperandName, i); else - buildAliasOperandReference(&II, OperandName, Op); + buildAliasOperandReference(II.get(), OperandName, Op); } - if (II.DefRec.is()) { - II.buildInstructionResultOperands(); + if (II->DefRec.is()) { + II->buildInstructionResultOperands(); // If the instruction has a two-operand alias, build up the // matchable here. We'll add them in bulk at the end to avoid // confusing this loop. std::string Constraint = - II.TheDef->getValueAsString("TwoOperandAliasConstraint"); + II->TheDef->getValueAsString("TwoOperandAliasConstraint"); if (Constraint != "") { // Start by making a copy of the original matchable. - NewMatchables.emplace_front(II); + auto AliasII = llvm::make_unique(*II); // Adjust it to be a two-operand alias. - NewMatchables.front().formTwoOperandAlias(Constraint); + AliasII->formTwoOperandAlias(Constraint); + + // Add the alias to the matchables list. + NewMatchables.push_back(std::move(AliasII)); } } else - II.buildAliasResultOperands(); + II->buildAliasResultOperands(); } - Matchables.splice_after(Matchables.before_begin(), NewMatchables); + if (!NewMatchables.empty()) + 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. @@ -1486,7 +1543,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); } @@ -1664,8 +1721,9 @@ static unsigned getConverterOperandID(const std::string &Name, return ID; } + static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, - std::forward_list &Infos, + std::vector> &Infos, raw_ostream &OS) { SetVector OperandConversionKinds; SetVector InstructionConversionKinds; @@ -1732,10 +1790,10 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, 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)) @@ -1747,7 +1805,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); @@ -1767,17 +1825,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. const MatchableInfo::AsmOperand &Op = - II.AsmOperands[OpInfo.AsmOperandNum]; + II->AsmOperands[OpInfo.AsmOperandNum]; // Registers are always converted the same, don't duplicate the // conversion function based on them. @@ -1839,6 +1897,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; @@ -1853,7 +1912,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" @@ -1884,7 +1943,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" @@ -1900,7 +1959,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. @@ -1908,7 +1967,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. @@ -1928,10 +1987,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"; @@ -2110,8 +2167,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"; @@ -2128,16 +2184,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"; @@ -2233,7 +2286,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; @@ -2255,12 +2308,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; @@ -2586,11 +2637,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Sort the instruction table using the partial order on classes. We use // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. - Info.Matchables.sort(); + std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), + [](const std::unique_ptr &a, + const std::unique_ptr &b){ + return *a < *b;}); DEBUG_WITH_TYPE("instruction_info", { for (const auto &MI : Info.Matchables) - MI.dump(); + MI->dump(); }); // Check for ambiguous matchables. @@ -2599,8 +2653,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { 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; + const MatchableInfo &A = **I; + const MatchableInfo &B = **J; if (A.couldMatchAmbiguouslyWith(B)) { errs() << "warning: ambiguous matchables:\n"; @@ -2627,7 +2681,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 " @@ -2635,15 +2689,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { 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" + OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" << " MCInst &Inst,\n" << " 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"; @@ -2721,11 +2773,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { unsigned MaxMnemonicIndex = 0; bool HasDeprecation = false; for (const auto &MI : Info.Matchables) { - MaxNumOperands = std::max(MaxNumOperands, MI.AsmOperands.size()); - HasDeprecation |= MI.HasDeprecation; + MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size()); + HasDeprecation |= MI->HasDeprecation; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(MI.Mnemonic.size()) + MI.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); MaxMnemonicIndex = std::max(MaxMnemonicIndex, StringTable.GetOrAddStringOffset(LenMnemonic, false)); } @@ -2749,9 +2801,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; OS << " uint16_t Opcode;\n"; - OS << " " << getMinimalTypeForRange(std::distance(Info.Matchables.begin(), - Info.Matchables.end())) - << " ConvertFn;\n"; + OS << " " << getMinimalTypeForRange(Info.Matchables.size()) + << " ConvertFn;\n"; OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange( @@ -2786,28 +2837,29 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; for (const auto &MI : Info.Matchables) { - if (MI.AsmVariantID != AsmVariantNo) + if (MI->AsmVariantID != AsmVariantNo) continue; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(MI.Mnemonic.size()) + MI.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) - << " /* " << MI.Mnemonic << " */, " << Target.getName() - << "::" << MI.getResultInst()->TheDef->getName() << ", " - << MI.ConversionFnKind << ", "; + << " /* " << MI->Mnemonic << " */, " + << Target.getName() << "::" + << MI->getResultInst()->TheDef->getName() << ", " + << MI->ConversionFnKind << ", "; // Write the required features mask. - if (!MI.RequiredFeatures.empty()) { - for (unsigned i = 0, e = MI.RequiredFeatures.size(); i != e; ++i) { + if (!MI->RequiredFeatures.empty()) { + for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) { if (i) OS << "|"; - OS << MI.RequiredFeatures[i]->getEnumName(); + OS << MI->RequiredFeatures[i]->getEnumName(); } } else OS << "0"; OS << ", { "; - for (unsigned i = 0, e = MI.AsmOperands.size(); i != e; ++i) { - const MatchableInfo::AsmOperand &Op = MI.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; @@ -2824,7 +2876,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { 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"); @@ -2840,10 +2892,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Finally, build the match function. OS << "unsigned " << Target.getName() << ClassName << "::\n" - << "MatchInstructionImpl(const OperandVector" - << " &Operands,\n"; - OS << " MCInst &Inst,\n" - << "uint64_t &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"; @@ -2872,13 +2923,13 @@ 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"; 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"); @@ -2947,12 +2998,13 @@ 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"; OS << "\n"; + OS << " Inst.clear();\n\n"; OS << " if (matchingInlineAsm) {\n"; OS << " Inst.setOpcode(it->Opcode);\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; @@ -3001,7 +3053,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);