X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FAsmMatcherEmitter.cpp;h=a19df793cf5ce1a85a29a1164b30be3974ee93af;hb=e778f82a1e33826ab012bb970a406c9acf37349b;hp=b45d40a0a9ba4655a69ba83b6f1b32826f796795;hpb=54911a5303f44694c43608eedf2142e9d65d7c22;p=oota-llvm.git diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index b45d40a0a9b..a19df793cf5 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -97,7 +97,6 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" -#include "StringToOffsetTable.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" @@ -110,6 +109,7 @@ #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" +#include "llvm/TableGen/StringToOffsetTable.h" #include "llvm/TableGen/TableGenBackend.h" #include #include @@ -125,6 +125,13 @@ 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 +// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and +// can even affect compiler output (at least seen in diagnostics produced when +// all matches fail). So we use a type that sorts them consistently. +typedef std::set RegisterSet; + class AsmMatcherEmitter { RecordKeeper &Records; public: @@ -185,7 +192,7 @@ struct ClassInfo { std::string ParserMethod; /// For register classes, the records for all the registers in this class. - std::set Registers; + RegisterSet Registers; /// For custom match classes, he diagnostic kind for when the predicate fails. std::string DiagnosticType; @@ -213,11 +220,11 @@ public: if (!isRegisterClass() || !RHS.isRegisterClass()) return false; - std::set Tmp; - std::insert_iterator< std::set > II(Tmp, Tmp.begin()); + RegisterSet Tmp; + std::insert_iterator II(Tmp, Tmp.begin()); std::set_intersection(Registers.begin(), Registers.end(), RHS.Registers.begin(), RHS.Registers.end(), - II); + II, LessRecordByID()); return !Tmp.empty(); } @@ -430,6 +437,9 @@ struct MatchableInfo { /// function. std::string ConversionFnKind; + /// If this instruction is deprecated in some form. + bool HasDeprecation; + MatchableInfo(const CodeGenInstruction &CGI) : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI), AsmString(CGI.AsmString) { @@ -613,7 +623,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; @@ -663,7 +673,7 @@ public: /// given operand. SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - std::map::const_iterator I = + std::map::const_iterator I = SubtargetFeatures.find(Def); return I == SubtargetFeatures.end() ? 0 : I->second; } @@ -779,6 +789,13 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, if (Record *Reg = AsmOperands[i].SingletonReg) SingletonRegisters.insert(Reg); } + + const RecordVal *DepMask = TheDef->getValue("DeprecatedFeatureMask"); + if (!DepMask) + DepMask = TheDef->getValue("ComplexDeprecationPredicate"); + + HasDeprecation = + DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false; } /// tokenizeAsmString - Tokenize a simplified assembly string. @@ -837,9 +854,11 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { } case '.': - if (InTok) - AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); - Prev = i; + if (!Info.AsmParser->getValueAsBit("MnemonicContainsDot")) { + if (InTok) + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + Prev = i; + } InTok = true; break; @@ -1045,6 +1064,18 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { PrintFatalError(Rec->getLoc(), "operand has no match class!"); } +struct LessRegisterSet { + bool operator() (const RegisterSet &LHS, const RegisterSet & RHS) const { + // std::set defines its own compariso "operator<", but it + // performs a lexicographical comparison by T's innate comparison + // for some reason. We don't want non-deterministic pointer + // comparisons so use this instead. + return std::lexicographical_compare(LHS.begin(), LHS.end(), + RHS.begin(), RHS.end(), + LessRecordByID()); + } +}; + void AsmMatcherInfo:: buildRegisterClasses(SmallPtrSet &SingletonRegisters) { const std::vector &Registers = @@ -1052,33 +1083,35 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { ArrayRef RegClassList = Target.getRegBank().getRegClasses(); + typedef std::set RegisterSetSet; + // The register sets used for matching. - std::set< std::set > RegisterSets; + RegisterSetSet RegisterSets; // Gather the defined sets. for (ArrayRef::const_iterator it = - RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(std::set( + RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) + RegisterSets.insert(RegisterSet( (*it)->getOrder().begin(), (*it)->getOrder().end())); // Add any required singleton sets. for (SmallPtrSet::iterator it = SingletonRegisters.begin(), ie = SingletonRegisters.end(); it != ie; ++it) { Record *Rec = *it; - RegisterSets.insert(std::set(&Rec, &Rec + 1)); + RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); } // Introduce derived sets where necessary (when a register does not determine // a unique register set class), and build the mapping of registers to the set // they should classify to. - std::map > RegisterMap; + std::map RegisterMap; for (std::vector::const_iterator it = Registers.begin(), ie = Registers.end(); it != ie; ++it) { const CodeGenRegister &CGR = **it; // Compute the intersection of all sets containing this register. - std::set ContainingSet; + RegisterSet ContainingSet; - for (std::set< std::set >::iterator it = RegisterSets.begin(), + for (RegisterSetSet::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it) { if (!it->count(CGR.TheDef)) continue; @@ -1088,11 +1121,12 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { continue; } - std::set Tmp; + RegisterSet Tmp; std::swap(Tmp, ContainingSet); - std::insert_iterator< std::set > II(ContainingSet, - ContainingSet.begin()); - std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II); + std::insert_iterator II(ContainingSet, + ContainingSet.begin()); + std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II, + LessRecordByID()); } if (!ContainingSet.empty()) { @@ -1102,9 +1136,9 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { } // Construct the register classes. - std::map, ClassInfo*> RegisterSetClasses; + std::map RegisterSetClasses; unsigned Index = 0; - for (std::set< std::set >::iterator it = RegisterSets.begin(), + for (RegisterSetSet::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it, ++Index) { ClassInfo *CI = new ClassInfo(); CI->Kind = ClassInfo::RegisterClass0 + Index; @@ -1122,13 +1156,14 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { // Find the superclasses; we could compute only the subgroup lattice edges, // but there isn't really a point. - for (std::set< std::set >::iterator it = RegisterSets.begin(), + for (RegisterSetSet::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it) { ClassInfo *CI = RegisterSetClasses[*it]; - for (std::set< std::set >::iterator it2 = RegisterSets.begin(), + 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())) + std::includes(it2->begin(), it2->end(), it->begin(), it->end(), + LessRecordByID())) CI->SuperClasses.push_back(RegisterSetClasses[*it2]); } @@ -1140,8 +1175,8 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { Record *Def = RC.getDef(); if (!Def) continue; - ClassInfo *CI = RegisterSetClasses[std::set(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(); @@ -1153,7 +1188,7 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { } // Populate the map for individual registers. - for (std::map >::iterator it = RegisterMap.begin(), + for (std::map::iterator it = RegisterMap.begin(), ie = RegisterMap.end(); it != ie; ++it) RegisterClasses[it->first] = RegisterSetClasses[it->second]; @@ -2067,7 +2102,8 @@ static void emitIsSubclass(CodeGenTarget &Target, OS << " if (A == B)\n"; OS << " return true;\n\n"; - std::stringstream SS; + std::string OStr; + raw_string_ostream SS(OStr); unsigned Count = 0; SS << " switch (A) {\n"; SS << " default:\n"; @@ -2176,7 +2212,7 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, OS << "// Flags for subtarget features that participate in " << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag {\n"; - for (std::map::const_iterator + for (std::map::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; @@ -2214,9 +2250,9 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { + typedef std::map RecFeatMap; + for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(), + ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; // FIXME: Totally just a placeholder name to get the algorithm working. OS << " case " << SFI.getEnumName() << ": return \"" @@ -2241,7 +2277,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(uint64_t FB) const {\n"; OS << " unsigned Features = 0;\n"; - for (std::map::const_iterator + for (std::map::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; @@ -2326,7 +2362,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info, } if (AliasesFromMnemonic.empty()) return; - + // Process each alias a "from" mnemonic at a time, building the code executed // by the string remapper. std::vector Cases; @@ -2655,7 +2691,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << "&Operands);\n"; OS << " void convertToMapAndConstraints(unsigned Kind,\n "; OS << " const SmallVectorImpl &Operands);\n"; - OS << " bool mnemonicIsValid(StringRef Mnemonic);\n"; + OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n"; OS << " unsigned MatchInstructionImpl(\n"; OS.indent(27); OS << "const SmallVectorImpl &Operands,\n" @@ -2740,11 +2776,13 @@ 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; // Store a pascal-style length byte in the mnemonic. std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); @@ -2777,7 +2815,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(Info.Classes.size()) << " Classes[" << MaxNumOperands << "];\n"; - OS << " uint8_t AsmVariantID;\n\n"; OS << " StringRef getMnemonic() const {\n"; OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; OS << " MnemonicTable[Mnemonic]);\n"; @@ -2799,51 +2836,67 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "} // end anonymous namespace.\n\n"; - OS << "static const MatchEntry MatchTable[" - << Info.Matchables.size() << "] = {\n"; + unsigned VariantCount = Target.getAsmParserVariantCount(); + for (unsigned VC = 0; VC != VariantCount; ++VC) { + Record *AsmVariant = Target.getAsmParserVariant(VC); + int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; + OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; - // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); - OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) - << " /* " << II.Mnemonic << " */, " - << Target.getName() << "::" - << II.getResultInst()->TheDef->getName() << ", " - << II.ConversionFnKind << ", "; + for (std::vector::const_iterator it = + Info.Matchables.begin(), ie = Info.Matchables.end(); + it != ie; ++it) { + MatchableInfo &II = **it; + if (II.AsmVariantID != AsmVariantNo) + continue; - // Write the required features mask. - if (!II.RequiredFeatures.empty()) { - for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { - if (i) OS << "|"; - OS << II.RequiredFeatures[i]->getEnumName(); - } - } else - OS << "0"; + // Store a pascal-style length byte in the mnemonic. + std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) + << " /* " << II.Mnemonic << " */, " + << Target.getName() << "::" + << II.getResultInst()->TheDef->getName() << ", " + << II.ConversionFnKind << ", "; + + // Write the required features mask. + if (!II.RequiredFeatures.empty()) { + for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (i) OS << "|"; + OS << II.RequiredFeatures[i]->getEnumName(); + } + } else + OS << "0"; - OS << ", { "; - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + OS << ", { "; + for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { + MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; - if (i) OS << ", "; - OS << Op.Class->Name; + if (i) OS << ", "; + OS << Op.Class->Name; + } + OS << " }, },\n"; } - OS << " }, " << II.AsmVariantID; - OS << "},\n"; - } - OS << "};\n\n"; + OS << "};\n\n"; + } // A method to determine if a mnemonic is in the list. OS << "bool " << Target.getName() << ClassName << "::\n" - << "mnemonicIsValid(StringRef Mnemonic) {\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 = MatchTable" << VC + << "; End = array_endof(MatchTable" << VC << "); break;\n"; + } + OS << " }\n"; OS << " // Search the table.\n"; OS << " std::pair MnemonicRange =\n"; - OS << " std::equal_range(MatchTable, MatchTable+" - << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n"; + OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n"; OS << " return MnemonicRange.first != MnemonicRange.second;\n"; OS << "}\n\n"; @@ -2885,10 +2938,20 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " ErrorInfo = ~0U;\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"; + for (unsigned VC = 0; VC != VariantCount; ++VC) { + Record *AsmVariant = Target.getAsmParserVariant(VC); + int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); + OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC + << "; End = array_endof(MatchTable" << VC << "); break;\n"; + } + OS << " }\n"; OS << " // Search the table.\n"; OS << " std::pair MnemonicRange =\n"; - OS << " std::equal_range(MatchTable, MatchTable+" - << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n\n"; + OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n"; OS << " // Return a more specific error code if no mnemonics match.\n"; OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; @@ -2902,7 +2965,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " assert(Mnemonic == it->getMnemonic());\n"; // Emit check that the subclasses match. - OS << " if (VariantID != it->AsmVariantID) continue;\n"; OS << " bool OperandsValid = true;\n"; OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; OS << " if (i + 1 >= Operands.size()) {\n"; @@ -2982,6 +3044,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (!InsnCleanupFn.empty()) OS << " " << InsnCleanupFn << "(Inst);\n"; + if (HasDeprecation) { + OS << " std::string Info;\n"; + OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; + OS << " SMLoc Loc = ((" << Target.getName() << "Operand*)Operands[0])->getStartLoc();\n"; + OS << " Parser.Warning(Loc, Info, None);\n"; + OS << " }\n"; + } + OS << " return Match_Success;\n"; OS << " }\n\n";