diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
| commit | b60736ec1405bb0a8dd40989f67ef4c93da068ab (patch) | |
| tree | 5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/utils/TableGen/SearchableTableEmitter.cpp | |
| parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) | |
Diffstat (limited to 'llvm/utils/TableGen/SearchableTableEmitter.cpp')
| -rw-r--r-- | llvm/utils/TableGen/SearchableTableEmitter.cpp | 227 |
1 files changed, 132 insertions, 95 deletions
diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp index 326cb4e54edc..912d43b2caa1 100644 --- a/llvm/utils/TableGen/SearchableTableEmitter.cpp +++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenIntrinsics.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Format.h" @@ -19,7 +21,6 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" -#include "CodeGenIntrinsics.h" #include <algorithm> #include <set> #include <string> @@ -53,6 +54,7 @@ struct GenericEnum { struct GenericField { std::string Name; RecTy *RecType = nullptr; + bool IsCode = false; bool IsIntrinsic = false; bool IsInstruction = false; GenericEnum *Enum = nullptr; @@ -62,12 +64,14 @@ struct GenericField { struct SearchIndex { std::string Name; + SMLoc Loc; // Source location of PrimaryKey or Key field definition. SmallVector<GenericField, 1> Fields; bool EarlyOut = false; }; struct GenericTable { std::string Name; + ArrayRef<SMLoc> Locs; // Source locations from the Record instance. std::string PreprocessorGuard; std::string CppTypeName; SmallVector<GenericField, 2> Fields; @@ -106,15 +110,17 @@ private: TypeInArgument, }; - std::string primaryRepresentation(const GenericField &Field, Init *I) { - if (StringInit *SI = dyn_cast<StringInit>(I)) - return SI->getAsString(); - else if (BitsInit *BI = dyn_cast<BitsInit>(I)) + std::string primaryRepresentation(SMLoc Loc, const GenericField &Field, + Init *I) { + if (StringInit *SI = dyn_cast<StringInit>(I)) { + if (Field.IsCode || SI->hasCodeFormat()) + return std::string(SI->getValue()); + else + return SI->getAsString(); + } else if (BitsInit *BI = dyn_cast<BitsInit>(I)) return "0x" + utohexstr(getAsInt(BI)); else if (BitInit *BI = dyn_cast<BitInit>(I)) return BI->getValue() ? "true" : "false"; - else if (CodeInit *CI = dyn_cast<CodeInit>(I)) - return std::string(CI->getValue()); else if (Field.IsIntrinsic) return "Intrinsic::" + getIntrinsic(I).EnumName; else if (Field.IsInstruction) @@ -122,11 +128,12 @@ private: else if (Field.Enum) { auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()]; if (!Entry) - PrintFatalError(Twine("Entry for field '") + Field.Name + "' is null"); + PrintFatalError(Loc, + Twine("Entry for field '") + Field.Name + "' is null"); return std::string(Entry->first); } - PrintFatalError(Twine("invalid field type for field '") + Field.Name + - "', expected: string, bits, bit or code"); + PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name + + "'; expected: bit, bits, string, or code"); } bool isIntrinsic(Init *I) { @@ -138,17 +145,16 @@ private: CodeGenIntrinsic &getIntrinsic(Init *I) { std::unique_ptr<CodeGenIntrinsic> &Intr = Intrinsics[I]; if (!Intr) - Intr = std::make_unique<CodeGenIntrinsic>(cast<DefInit>(I)->getDef()); + Intr = std::make_unique<CodeGenIntrinsic>(cast<DefInit>(I)->getDef(), + std::vector<Record *>()); return *Intr; } bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index); - bool isIntegral(Init *I) { - return isa<BitsInit>(I) || isa<CodeInit>(I) || isIntrinsic(I); - } - - std::string searchableFieldType(const GenericField &Field, TypeContext Ctx) { + std::string searchableFieldType(const GenericTable &Table, + const SearchIndex &Index, + const GenericField &Field, TypeContext Ctx) { if (isa<StringRecTy>(Field.RecType)) { if (Ctx == TypeInStaticStruct) return "const char *"; @@ -165,12 +171,16 @@ private: return "uint32_t"; if (NumBits <= 64) return "uint64_t"; - PrintFatalError(Twine("bitfield '") + Field.Name + - "' too large to search"); + PrintFatalError(Index.Loc, Twine("In table '") + Table.Name + + "' lookup method '" + Index.Name + + "', key field '" + Field.Name + + "' of type bits is too large"); } else if (Field.Enum || Field.IsIntrinsic || Field.IsInstruction) return "unsigned"; - PrintFatalError(Twine("Field '") + Field.Name + "' has unknown type '" + - Field.RecType->getAsString() + "' to search by"); + PrintFatalError(Index.Loc, + Twine("In table '") + Table.Name + "' lookup method '" + + Index.Name + "', key field '" + Field.Name + + "' has invalid type: " + Field.RecType->getAsString()); } void emitGenericTable(const GenericTable &Table, raw_ostream &OS); @@ -183,7 +193,7 @@ private: bool parseFieldType(GenericField &Field, Init *II); std::unique_ptr<SearchIndex> - parseSearchIndex(GenericTable &Table, StringRef Name, + parseSearchIndex(GenericTable &Table, const RecordVal *RecVal, StringRef Name, const std::vector<StringRef> &Key, bool EarlyOut); void collectEnumEntries(GenericEnum &Enum, StringRef NameField, StringRef ValueField, @@ -258,8 +268,8 @@ bool SearchableTableEmitter::compareBy(Record *LHS, Record *RHS, if (LHSv > RHSv) return false; } else { - std::string LHSs = primaryRepresentation(Field, LHSI); - std::string RHSs = primaryRepresentation(Field, RHSI); + std::string LHSs = primaryRepresentation(Index.Loc, Field, LHSI); + std::string RHSs = primaryRepresentation(Index.Loc, Field, RHSI); if (isa<StringRecTy>(Field.RecType)) { LHSs = StringRef(LHSs).upper(); @@ -314,7 +324,8 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table, } else { OS << " struct IndexType {\n"; for (const auto &Field : Index.Fields) { - OS << " " << searchableFieldType(Field, TypeInStaticStruct) << " " + OS << " " + << searchableFieldType(Table, Index, Field, TypeInStaticStruct) << " " << Field.Name << ";\n"; } OS << " unsigned _index;\n"; @@ -327,11 +338,10 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table, for (unsigned i = 0; i < Table.Entries.size(); ++i) Entries.emplace_back(Table.Entries[i], i); - std::stable_sort(Entries.begin(), Entries.end(), - [&](const std::pair<Record *, unsigned> &LHS, - const std::pair<Record *, unsigned> &RHS) { - return compareBy(LHS.first, RHS.first, Index); - }); + llvm::stable_sort(Entries, [&](const std::pair<Record *, unsigned> &LHS, + const std::pair<Record *, unsigned> &RHS) { + return compareBy(LHS.first, RHS.first, Index); + }); IndexRowsStorage.reserve(Entries.size()); for (const auto &Entry : Entries) { @@ -344,8 +354,8 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table, OS << ", "; NeedComma = true; - std::string Repr = - primaryRepresentation(Field, Entry.first->getValueInit(Field.Name)); + std::string Repr = primaryRepresentation( + Index.Loc, Field, Entry.first->getValueInit(Field.Name)); if (isa<StringRecTy>(Field.RecType)) Repr = StringRef(Repr).upper(); OS << Repr; @@ -388,10 +398,10 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table, if (Index.EarlyOut) { const GenericField &Field = Index.Fields[0]; - std::string FirstRepr = - primaryRepresentation(Field, IndexRows[0]->getValueInit(Field.Name)); + std::string FirstRepr = primaryRepresentation( + Index.Loc, Field, IndexRows[0]->getValueInit(Field.Name)); std::string LastRepr = primaryRepresentation( - Field, IndexRows.back()->getValueInit(Field.Name)); + Index.Loc, Field, IndexRows.back()->getValueInit(Field.Name)); OS << " if ((" << Field.Name << " < " << FirstRepr << ") ||\n"; OS << " (" << Field.Name << " > " << LastRepr << "))\n"; OS << " return nullptr;\n\n"; @@ -399,11 +409,11 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table, OS << " struct KeyType {\n"; for (const auto &Field : Index.Fields) { - OS << " " << searchableFieldType(Field, TypeInTempStruct) << " " - << Field.Name << ";\n"; + OS << " " << searchableFieldType(Table, Index, Field, TypeInTempStruct) + << " " << Field.Name << ";\n"; } OS << " };\n"; - OS << " KeyType Key = { "; + OS << " KeyType Key = {"; bool NeedComma = false; for (const auto &Field : Index.Fields) { if (NeedComma) @@ -414,12 +424,14 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table, if (isa<StringRecTy>(Field.RecType)) { OS << ".upper()"; if (IsPrimary) - PrintFatalError(Twine("Use a secondary index for case-insensitive " - "comparison of field '") + - Field.Name + "' in table '" + Table.Name + "'"); + PrintFatalError(Index.Loc, + Twine("In table '") + Table.Name + + "', use a secondary lookup method for " + "case-insensitive comparison of field '" + + Field.Name + "'"); } } - OS << " };\n"; + OS << "};\n"; OS << " auto Table = makeArrayRef(" << IndexName << ");\n"; OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n"; @@ -476,7 +488,8 @@ void SearchableTableEmitter::emitLookupDeclaration(const GenericTable &Table, OS << ", "; NeedComma = true; - OS << searchableFieldType(Field, TypeInArgument) << " " << Field.Name; + OS << searchableFieldType(Table, Index, Field, TypeInArgument) << " " + << Field.Name; } OS << ")"; } @@ -511,7 +524,8 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table, OS << ", "; NeedComma = true; - OS << primaryRepresentation(Field, Entry->getValueInit(Field.Name)); + OS << primaryRepresentation(Table.Locs[0], Field, + Entry->getValueInit(Field.Name)); } OS << " }, // " << i << "\n"; @@ -528,40 +542,49 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table, OS << "#endif\n\n"; } -bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *II) { - if (auto DI = dyn_cast<DefInit>(II)) { - Record *TypeRec = DI->getDef(); - if (TypeRec->isSubClassOf("GenericEnum")) { - Field.Enum = EnumMap[TypeRec]; - Field.RecType = RecordRecTy::get(Field.Enum->Class); +bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) { + if (auto Type = dyn_cast<StringInit>(TypeOf)) { + if (Type->getValue() == "code") { + Field.IsCode = true; return true; + } else { + if (Record *TypeRec = Records.getDef(Type->getValue())) { + if (TypeRec->isSubClassOf("GenericEnum")) { + Field.Enum = EnumMap[TypeRec]; + Field.RecType = RecordRecTy::get(Field.Enum->Class); + return true; + } + } } } return false; } -std::unique_ptr<SearchIndex> -SearchableTableEmitter::parseSearchIndex(GenericTable &Table, StringRef Name, - const std::vector<StringRef> &Key, - bool EarlyOut) { +std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex( + GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name, + const std::vector<StringRef> &Key, bool EarlyOut) { auto Index = std::make_unique<SearchIndex>(); Index->Name = std::string(Name); + Index->Loc = KeyRecVal->getLoc(); Index->EarlyOut = EarlyOut; for (const auto &FieldName : Key) { const GenericField *Field = Table.getFieldByName(FieldName); if (!Field) - PrintFatalError(Twine("Search index '") + Name + - "' refers to non-existing field '" + FieldName + - "' in table '" + Table.Name + "'"); + PrintFatalError( + KeyRecVal, + Twine("In table '") + Table.Name + + "', 'PrimaryKey' or 'Key' refers to nonexistent field '" + + FieldName + "'"); + Index->Fields.push_back(*Field); } if (EarlyOut && isa<StringRecTy>(Index->Fields[0].RecType)) { PrintFatalError( - "Early-out is not supported for string types (in search index '" + - Twine(Name) + "'"); + KeyRecVal, Twine("In lookup method '") + Name + "', early-out is not " + + "supported for a first key field of type string"); } return Index; @@ -586,11 +609,11 @@ void SearchableTableEmitter::collectEnumEntries( } if (ValueField.empty()) { - std::stable_sort(Enum.Entries.begin(), Enum.Entries.end(), - [](const std::unique_ptr<GenericEnum::Entry> &LHS, - const std::unique_ptr<GenericEnum::Entry> &RHS) { - return LHS->first < RHS->first; - }); + llvm::stable_sort(Enum.Entries, + [](const std::unique_ptr<GenericEnum::Entry> &LHS, + const std::unique_ptr<GenericEnum::Entry> &RHS) { + return LHS->first < RHS->first; + }); for (size_t i = 0; i < Enum.Entries.size(); ++i) Enum.Entries[i]->second = i; @@ -600,31 +623,33 @@ void SearchableTableEmitter::collectEnumEntries( void SearchableTableEmitter::collectTableEntries( GenericTable &Table, const std::vector<Record *> &Items) { if (Items.empty()) - PrintWarning(Twine("Table '") + Table.Name + "' has no items"); + PrintFatalError(Table.Locs, + Twine("Table '") + Table.Name + "' has no entries"); for (auto EntryRec : Items) { for (auto &Field : Table.Fields) { auto TI = dyn_cast<TypedInit>(EntryRec->getValueInit(Field.Name)); if (!TI || !TI->isComplete()) { - PrintFatalError(EntryRec->getLoc(), - Twine("Record '") + EntryRec->getName() + - "' in table '" + Table.Name + - "' is missing field '" + Field.Name + "'"); + PrintFatalError(EntryRec, Twine("Record '") + EntryRec->getName() + + "' for table '" + Table.Name + + "' is missing field '" + Field.Name + + "'"); } if (!Field.RecType) { Field.RecType = TI->getType(); } else { RecTy *Ty = resolveTypes(Field.RecType, TI->getType()); if (!Ty) - PrintFatalError(Twine("Field '") + Field.Name + "' of table '" + - Table.Name + "' has incompatible type: " + - Field.RecType->getAsString() + " vs. " + - TI->getType()->getAsString()); + PrintFatalError(EntryRec->getValue(Field.Name), + Twine("Field '") + Field.Name + "' of table '" + + Table.Name + "' entry has incompatible type: " + + TI->getType()->getAsString() + " vs. " + + Field.RecType->getAsString()); Field.RecType = Ty; } } - Table.Entries.push_back(EntryRec); + Table.Entries.push_back(EntryRec); // Add record to table's record list. } Record *IntrinsicClass = Records.getClass("Intrinsic"); @@ -665,8 +690,9 @@ void SearchableTableEmitter::run(raw_ostream &OS) { StringRef FilterClass = EnumRec->getValueAsString("FilterClass"); Enum->Class = Records.getClass(FilterClass); if (!Enum->Class) - PrintFatalError(EnumRec->getLoc(), Twine("Enum FilterClass '") + - FilterClass + "' does not exist"); + PrintFatalError(EnumRec->getValue("FilterClass"), + Twine("Enum FilterClass '") + FilterClass + + "' does not exist"); collectEnumEntries(*Enum, NameField, ValueField, Records.getAllDerivedDefinitions(FilterClass)); @@ -677,36 +703,44 @@ void SearchableTableEmitter::run(raw_ostream &OS) { for (auto TableRec : Records.getAllDerivedDefinitions("GenericTable")) { auto Table = std::make_unique<GenericTable>(); Table->Name = std::string(TableRec->getName()); + Table->Locs = TableRec->getLoc(); Table->PreprocessorGuard = std::string(TableRec->getName()); Table->CppTypeName = std::string(TableRec->getValueAsString("CppTypeName")); std::vector<StringRef> Fields = TableRec->getValueAsListOfStrings("Fields"); for (const auto &FieldName : Fields) { - Table->Fields.emplace_back(FieldName); + Table->Fields.emplace_back(FieldName); // Construct a GenericField. - if (auto TypeOfVal = TableRec->getValue(("TypeOf_" + FieldName).str())) { - if (!parseFieldType(Table->Fields.back(), TypeOfVal->getValue())) { - PrintFatalError(TableRec->getLoc(), - Twine("Table '") + Table->Name + - "' has bad 'TypeOf_" + FieldName + - "': " + TypeOfVal->getValue()->getAsString()); + if (auto TypeOfRecordVal = TableRec->getValue(("TypeOf_" + FieldName).str())) { + if (!parseFieldType(Table->Fields.back(), TypeOfRecordVal->getValue())) { + PrintError(TypeOfRecordVal, + Twine("Table '") + Table->Name + + "' has invalid 'TypeOf_" + FieldName + + "': " + TypeOfRecordVal->getValue()->getAsString()); + PrintFatalNote("The 'TypeOf_xxx' field must be a string naming a " + "GenericEnum record, or \"code\""); } } } - collectTableEntries(*Table, Records.getAllDerivedDefinitions( - TableRec->getValueAsString("FilterClass"))); + StringRef FilterClass = TableRec->getValueAsString("FilterClass"); + if (!Records.getClass(FilterClass)) + PrintFatalError(TableRec->getValue("FilterClass"), + Twine("Table FilterClass '") + + FilterClass + "' does not exist"); + + collectTableEntries(*Table, Records.getAllDerivedDefinitions(FilterClass)); if (!TableRec->isValueUnset("PrimaryKey")) { Table->PrimaryKey = - parseSearchIndex(*Table, TableRec->getValueAsString("PrimaryKeyName"), + parseSearchIndex(*Table, TableRec->getValue("PrimaryKey"), + TableRec->getValueAsString("PrimaryKeyName"), TableRec->getValueAsListOfStrings("PrimaryKey"), TableRec->getValueAsBit("PrimaryKeyEarlyOut")); - std::stable_sort(Table->Entries.begin(), Table->Entries.end(), - [&](Record *LHS, Record *RHS) { - return compareBy(LHS, RHS, *Table->PrimaryKey); - }); + llvm::stable_sort(Table->Entries, [&](Record *LHS, Record *RHS) { + return compareBy(LHS, RHS, *Table->PrimaryKey); + }); } TableMap.insert(std::make_pair(TableRec, Table.get())); @@ -717,15 +751,16 @@ void SearchableTableEmitter::run(raw_ostream &OS) { Record *TableRec = IndexRec->getValueAsDef("Table"); auto It = TableMap.find(TableRec); if (It == TableMap.end()) - PrintFatalError(IndexRec->getLoc(), + PrintFatalError(IndexRec->getValue("Table"), Twine("SearchIndex '") + IndexRec->getName() + - "' refers to non-existing table '" + + "' refers to nonexistent table '" + TableRec->getName()); GenericTable &Table = *It->second; - Table.Indices.push_back(parseSearchIndex( - Table, IndexRec->getName(), IndexRec->getValueAsListOfStrings("Key"), - IndexRec->getValueAsBit("EarlyOut"))); + Table.Indices.push_back( + parseSearchIndex(Table, IndexRec->getValue("Key"), IndexRec->getName(), + IndexRec->getValueAsListOfStrings("Key"), + IndexRec->getValueAsBit("EarlyOut"))); } // Translate legacy tables. @@ -756,6 +791,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) { auto Table = std::make_unique<GenericTable>(); Table->Name = (Twine(Class->getName()) + "sList").str(); + Table->Locs = Class->getLoc(); Table->PreprocessorGuard = Class->getName().upper(); Table->CppTypeName = std::string(Class->getName()); @@ -778,7 +814,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) { Class->getValueAsListOfStrings("SearchableFields")) { std::string Name = (Twine("lookup") + Table->CppTypeName + "By" + Field).str(); - Table->Indices.push_back(parseSearchIndex(*Table, Name, {Field}, false)); + Table->Indices.push_back(parseSearchIndex(*Table, Class->getValue(Field), + Name, {Field}, false)); } Tables.emplace_back(std::move(Table)); |
