diff options
Diffstat (limited to 'contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp')
-rw-r--r-- | contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp | 264 |
1 files changed, 88 insertions, 176 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 76228e0..1272d2b 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -97,6 +97,9 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" +#include "Types.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -126,7 +129,6 @@ MatchPrefix("match-prefix", cl::init(""), namespace { class AsmMatcherInfo; -struct SubtargetFeatureInfo; // Register sets are used as keys in some second-order sets TableGen creates // when generating its data structures. This means that the order of two @@ -353,6 +355,7 @@ public: std::string TokenizingCharacters; std::string SeparatorCharacters; std::string BreakCharacters; + std::string Name; int AsmVariantNo; }; @@ -556,20 +559,17 @@ struct MatchableInfo { /// findAsmOperand - Find the AsmOperand with the specified name and /// suboperand index. int findAsmOperand(StringRef N, int SubOpIdx) const { - auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(), - [&](const AsmOperand &Op) { - return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx; - }); + auto I = find_if(AsmOperands, [&](const AsmOperand &Op) { + return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx; + }); return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1; } /// findAsmOperandNamed - Find the first AsmOperand with the specified name. /// This does not check the suboperand index. int findAsmOperandNamed(StringRef N) const { - auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(), - [&](const AsmOperand &Op) { - return Op.SrcOpName == N; - }); + auto I = find_if(AsmOperands, + [&](const AsmOperand &Op) { return Op.SrcOpName == N; }); return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1; } @@ -653,28 +653,6 @@ private: void addAsmOperand(StringRef Token, bool IsIsolatedToken = false); }; -/// SubtargetFeatureInfo - Helper class for storing information on a subtarget -/// feature which participates in instruction matching. -struct SubtargetFeatureInfo { - /// \brief The predicate record for this feature. - Record *TheDef; - - /// \brief An unique index assigned to represent this feature. - uint64_t Index; - - 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() const { - errs() << getEnumName() << " " << Index << "\n"; - TheDef->dump(); - } -}; - struct OperandMatchEntry { unsigned OperandMask; const MatchableInfo* MI; @@ -754,7 +732,7 @@ public: CodeGenTarget &Target, RecordKeeper &Records); - /// buildInfo - Construct the various tables used during matching. + /// Construct the various tables used during matching. void buildInfo(); /// buildOperandMatchInfo - Build the necessary information to handle user @@ -774,9 +752,9 @@ public: } bool hasOptionalOperands() const { - return std::find_if(Classes.begin(), Classes.end(), - [](const ClassInfo& Class){ return Class.IsOptional; }) - != Classes.end(); + return find_if(Classes, [](const ClassInfo &Class) { + return Class.IsOptional; + }) != Classes.end(); } }; @@ -1311,10 +1289,10 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) { if (CI->ValueName.empty()) { CI->ClassName = Rec->getName(); - CI->Name = "MCK_" + Rec->getName(); + CI->Name = "MCK_" + Rec->getName().str(); CI->ValueName = Rec->getName(); } else - CI->ValueName = CI->ValueName + "," + Rec->getName(); + CI->ValueName = CI->ValueName + "," + Rec->getName().str(); } } @@ -1437,21 +1415,15 @@ void AsmMatcherInfo::buildOperandMatchInfo() { void AsmMatcherInfo::buildInfo() { // Build information about all of the AssemblerPredicates. - std::vector<Record*> AllPredicates = - Records.getAllDerivedDefinitions("Predicate"); - for (Record *Pred : AllPredicates) { - // Ignore predicates that are not intended for the assembler. - if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) - continue; - - if (Pred->getName().empty()) - PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - - SubtargetFeatures.insert(std::make_pair( - Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()))); - DEBUG(SubtargetFeatures.find(Pred)->second.dump()); - assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); - } + const std::vector<std::pair<Record *, SubtargetFeatureInfo>> + &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records); + SubtargetFeatures.insert(SubtargetFeaturePairs.begin(), + SubtargetFeaturePairs.end()); +#ifndef NDEBUG + for (const auto &Pair : SubtargetFeatures) + DEBUG(Pair.second.dump()); +#endif // NDEBUG + assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst"); @@ -1471,6 +1443,7 @@ void AsmMatcherInfo::buildInfo() { AsmVariant->getValueAsString("SeparatorCharacters"); Variant.BreakCharacters = AsmVariant->getValueAsString("BreakCharacters"); + Variant.Name = AsmVariant->getValueAsString("Name"); Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant"); for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) { @@ -1484,6 +1457,11 @@ void AsmMatcherInfo::buildInfo() { if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; + // Ignore instructions for different instructions + const std::string V = CGI->TheDef->getValueAsString("AsmVariantName"); + if (!V.empty() && V != Variant.Name) + continue; + auto II = llvm::make_unique<MatchableInfo>(*CGI); II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst); @@ -1512,6 +1490,10 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; + const std::string V = Alias->TheDef->getValueAsString("AsmVariantName"); + if (!V.empty() && V != Variant.Name) + continue; + auto II = llvm::make_unique<MatchableInfo>(std::move(Alias)); II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst); @@ -1613,15 +1595,15 @@ void AsmMatcherInfo::buildInfo() { // Reorder classes so that classes precede super classes. Classes.sort(); -#ifndef NDEBUG - // Verify that the table is now sorted +#ifdef EXPENSIVE_CHECKS + // Verify that the table is sorted and operator < works transitively. for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) { for (auto J = I; J != E; ++J) { assert(!(*J < *I)); assert(I == J || !J->isSubsetOf(*I)); } } -#endif // NDEBUG +#endif } /// buildInstructionOperandReference - The specified operand is a reference to a @@ -1814,13 +1796,13 @@ void MatchableInfo::buildAliasResultOperands() { } } -static unsigned getConverterOperandID(const std::string &Name, - SmallSetVector<std::string, 16> &Table, - bool &IsNew) { - IsNew = Table.insert(Name); +static unsigned +getConverterOperandID(const std::string &Name, + SmallSetVector<CachedHashString, 16> &Table, + bool &IsNew) { + IsNew = Table.insert(CachedHashString(Name)); - unsigned ID = IsNew ? Table.size() - 1 : - std::find(Table.begin(), Table.end(), Name) - Table.begin(); + unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin(); assert(ID < Table.size()); @@ -1831,13 +1813,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector<std::unique_ptr<MatchableInfo>> &Infos, bool HasMnemonicFirst, bool HasOptionalOperands, raw_ostream &OS) { - SmallSetVector<std::string, 16> OperandConversionKinds; - SmallSetVector<std::string, 16> InstructionConversionKinds; + SmallSetVector<CachedHashString, 16> OperandConversionKinds; + SmallSetVector<CachedHashString, 16> InstructionConversionKinds; std::vector<std::vector<uint8_t> > ConversionTable; size_t MaxRowLength = 2; // minimum is custom converter plus terminator. // TargetOperandClass - This is the target's operand class, like X86Operand. - std::string TargetOperandClass = Target.getName() + "Operand"; + std::string TargetOperandClass = Target.getName().str() + "Operand"; // Write the convert function to a separate stream, so we can drop it after // the enum. We'll build up the conversion handlers for the individual @@ -1904,9 +1886,9 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Pre-populate the operand conversion kinds with the standard always // available entries. - OperandConversionKinds.insert("CVT_Done"); - OperandConversionKinds.insert("CVT_Reg"); - OperandConversionKinds.insert("CVT_Tied"); + OperandConversionKinds.insert(CachedHashString("CVT_Done")); + OperandConversionKinds.insert(CachedHashString("CVT_Reg")); + OperandConversionKinds.insert(CachedHashString("CVT_Tied")); enum { CVT_Done, CVT_Reg, CVT_Tied }; for (auto &II : Infos) { @@ -1918,13 +1900,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, II->ConversionFnKind = Signature; // Check if we have already generated this signature. - if (!InstructionConversionKinds.insert(Signature)) + if (!InstructionConversionKinds.insert(CachedHashString(Signature))) continue; // Remember this converter for the kind enum. unsigned KindID = OperandConversionKinds.size(); - OperandConversionKinds.insert("CVT_" + - getEnumNameForToken(AsmMatchConverter)); + OperandConversionKinds.insert( + CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter))); // Add the converter row for this instruction. ConversionTable.emplace_back(); @@ -2072,7 +2054,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, Reg = "0"; } else { Reg = getQualifiedName(OpInfo.Register); - Name = "reg" + OpInfo.Register->getName(); + Name = "reg" + OpInfo.Register->getName().str(); } Signature += "__" + Name; Name = "CVT_" + Name; @@ -2106,7 +2088,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Save the signature. If we already have it, don't add a new row // to the table. - if (!InstructionConversionKinds.insert(Signature)) + if (!InstructionConversionKinds.insert(CachedHashString(Signature))) continue; // Add the row to the table. @@ -2123,14 +2105,14 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Output the operand conversion kind enum. OS << "enum OperatorConversionKind {\n"; - for (const std::string &Converter : OperandConversionKinds) + for (const auto &Converter : OperandConversionKinds) OS << " " << Converter << ",\n"; OS << " CVT_NUM_CONVERTERS\n"; OS << "};\n\n"; // Output the instruction conversion kind enum. OS << "enum InstructionConversionKind {\n"; - for (const std::string &Signature : InstructionConversionKinds) + for (const auto &Signature : InstructionConversionKinds) OS << " " << Signature << ",\n"; OS << " CVT_NUM_SIGNATURES\n"; OS << "};\n\n"; @@ -2382,40 +2364,6 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser, OS << "}\n\n"; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFFFFFFULL) - return "uint64_t"; - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - -static const char *getMinimalRequiredFeaturesType(const AsmMatcherInfo &Info) { - uint64_t MaxIndex = Info.SubtargetFeatures.size(); - if (MaxIndex > 0) - MaxIndex--; - return getMinimalTypeForRange(1ULL << MaxIndex); -} - -/// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag -/// definitions. -static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, - raw_ostream &OS) { - OS << "// Flags for subtarget features that participate in " - << "instruction matching.\n"; - OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) - << " {\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"; -} - /// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types. static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { // Get the set of diagnostic types from all of the operand classes. @@ -2456,55 +2404,6 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "}\n\n"; } -/// emitComputeAvailableFeatures - Emit the function to compute the list of -/// available features given a subtarget. -static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, - raw_ostream &OS) { - std::string ClassName = - Info.AsmParser->getValueAsString("AsmParserClassName"); - - 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 = - SFI.TheDef->getValueAsString("AssemblerCondString"); - StringRef Conds = CondStorage; - std::pair<StringRef,StringRef> Comma = Conds.split(','); - bool First = true; - do { - if (!First) - OS << " && "; - - bool Neg = false; - StringRef Cond = Comma.first; - if (Cond[0] == '!') { - Neg = true; - Cond = Cond.substr(1); - } - - OS << "("; - if (Neg) - OS << "!"; - OS << "FB[" << Info.Target.getName() << "::" << Cond << "])"; - - if (Comma.second.empty()) - break; - - First = false; - Comma = Comma.second.split(','); - } while (true); - - OS << ")\n"; - OS << " Features |= " << SFI.getEnumName() << ";\n"; - } - OS << " return Features;\n"; - OS << "}\n\n"; -} - static std::string GetAliasRequiredFeatures(Record *R, const AsmMatcherInfo &Info) { std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates"); @@ -2646,7 +2545,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; @@ -2719,8 +2618,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the operand class switch to call the correct custom parser for // the found operand class. - OS << Target.getName() << ClassName << "::OperandMatchResultTy " - << Target.getName() << ClassName << "::\n" + OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n" << "tryCustomParseOperand(OperandVector" << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; @@ -2741,8 +2639,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parser. This code is very similar with // the other matcher. Also use MatchResultTy here just in case we go for // a better error handling. - OS << Target.getName() << ClassName << "::OperandMatchResultTy " - << Target.getName() << ClassName << "::\n" + OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n" << "MatchOperandParserImpl(OperandVector" << " &Operands,\n StringRef Mnemonic) {\n"; @@ -2822,15 +2719,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { const std::unique_ptr<MatchableInfo> &b){ return *a < *b;}); -#ifndef NDEBUG - // Verify that the table is now sorted +#ifdef EXPENSIVE_CHECKS + // Verify that the table is sorted and operator < works transitively. for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E; ++I) { for (auto J = I; J != E; ++J) { assert(!(**J < **I)); } } -#endif // NDEBUG +#endif DEBUG_WITH_TYPE("instruction_info", { for (const auto &MI : Info.Matchables) @@ -2896,11 +2793,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " unsigned VariantID = 0);\n"; if (!Info.OperandMatchInfo.empty()) { - OS << "\n enum OperandMatchResultTy {\n"; - OS << " MatchOperand_Success, // operand matched successfully\n"; - OS << " MatchOperand_NoMatch, // operand did not match\n"; - OS << " MatchOperand_ParseFail // operand matched but had errors\n"; - OS << " };\n"; OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; OS << " OperandVector &Operands,\n"; OS << " StringRef Mnemonic);\n"; @@ -2922,7 +2814,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_REGISTER_MATCHER\n\n"; // Emit the subtarget feature enumeration. - emitSubtargetFeatureFlagEnumeration(Info, OS); + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + Info.SubtargetFeatures, OS); // Emit the function to match a register name to number. // This should be omitted for Mips target @@ -2967,7 +2860,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { emitValidateOperandClass(Info, OS); // Emit the available features compute function. - emitComputeAvailableFeatures(Info, OS); + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Info.Target.getName(), ClassName, "ComputeAvailableFeatures", + Info.SubtargetFeatures, OS); StringToOffsetTable StringTable; @@ -3005,7 +2900,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange( std::distance(Info.Classes.begin(), Info.Classes.end())) @@ -3254,8 +3149,24 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " }\n"; OS << "\n"; OS << " Inst.clear();\n\n"; + OS << " Inst.setOpcode(it->Opcode);\n"; + // Verify the instruction with the target-specific match predicate function. + OS << " // We have a potential match but have not rendered the operands.\n" + << " // Check the target predicate to handle any context sensitive\n" + " // constraints.\n" + << " // For example, Ties that are referenced multiple times must be\n" + " // checked here to ensure the input is the same for each match\n" + " // constraints. If we leave it any later the ties will have been\n" + " // canonicalized\n" + << " unsigned MatchResult;\n" + << " if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, " + "Operands)) != Match_Success) {\n" + << " Inst.clear();\n" + << " RetCode = MatchResult;\n" + << " HadMatchOtherThanPredicate = true;\n" + << " continue;\n" + << " }\n\n"; OS << " if (matchingInlineAsm) {\n"; - OS << " Inst.setOpcode(it->Opcode);\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; OS << " return Match_Success;\n"; OS << " }\n\n"; @@ -3272,7 +3183,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Verify the instruction with the target-specific match predicate function. OS << " // We have a potential match. Check the target predicate to\n" << " // handle any context sensitive constraints.\n" - << " unsigned MatchResult;\n" << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !=" << " Match_Success) {\n" << " Inst.clear();\n" @@ -3289,7 +3199,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (HasDeprecation) { OS << " std::string Info;\n"; - OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n"; + OS << " if (!getParser().getTargetParser().\n"; + OS << " getTargetOptions().MCNoDeprecatedWarn &&\n"; + OS << " MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; OS << " getParser().Warning(Loc, Info, None);\n"; |