SearchableTableEmitter.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. //===- SearchableTableEmitter.cpp - Generate efficiently searchable tables -==//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This tablegen backend emits a generic array initialized by specified fields,
  10. // together with companion index tables and lookup functions (binary search,
  11. // currently).
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "CodeGenIntrinsics.h"
  15. #include "llvm/ADT/ArrayRef.h"
  16. #include "llvm/ADT/DenseMap.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include "llvm/ADT/StringExtras.h"
  19. #include "llvm/TableGen/Error.h"
  20. #include "llvm/TableGen/Record.h"
  21. #include <algorithm>
  22. #include <set>
  23. #include <string>
  24. #include <vector>
  25. using namespace llvm;
  26. #define DEBUG_TYPE "searchable-table-emitter"
  27. namespace {
  28. int getAsInt(Init *B) {
  29. return cast<IntInit>(
  30. B->convertInitializerTo(IntRecTy::get(B->getRecordKeeper())))
  31. ->getValue();
  32. }
  33. int getInt(Record *R, StringRef Field) {
  34. return getAsInt(R->getValueInit(Field));
  35. }
  36. struct GenericEnum {
  37. using Entry = std::pair<StringRef, int64_t>;
  38. std::string Name;
  39. Record *Class = nullptr;
  40. std::string PreprocessorGuard;
  41. std::vector<std::unique_ptr<Entry>> Entries;
  42. DenseMap<Record *, Entry *> EntryMap;
  43. };
  44. struct GenericField {
  45. std::string Name;
  46. RecTy *RecType = nullptr;
  47. bool IsCode = false;
  48. bool IsIntrinsic = false;
  49. bool IsInstruction = false;
  50. GenericEnum *Enum = nullptr;
  51. GenericField(StringRef Name) : Name(std::string(Name)) {}
  52. };
  53. struct SearchIndex {
  54. std::string Name;
  55. SMLoc Loc; // Source location of PrimaryKey or Key field definition.
  56. SmallVector<GenericField, 1> Fields;
  57. bool EarlyOut = false;
  58. };
  59. struct GenericTable {
  60. std::string Name;
  61. ArrayRef<SMLoc> Locs; // Source locations from the Record instance.
  62. std::string PreprocessorGuard;
  63. std::string CppTypeName;
  64. SmallVector<GenericField, 2> Fields;
  65. std::vector<Record *> Entries;
  66. std::unique_ptr<SearchIndex> PrimaryKey;
  67. SmallVector<std::unique_ptr<SearchIndex>, 2> Indices;
  68. const GenericField *getFieldByName(StringRef Name) const {
  69. for (const auto &Field : Fields) {
  70. if (Name == Field.Name)
  71. return &Field;
  72. }
  73. return nullptr;
  74. }
  75. };
  76. class SearchableTableEmitter {
  77. RecordKeeper &Records;
  78. DenseMap<Init *, std::unique_ptr<CodeGenIntrinsic>> Intrinsics;
  79. std::vector<std::unique_ptr<GenericEnum>> Enums;
  80. DenseMap<Record *, GenericEnum *> EnumMap;
  81. std::set<std::string> PreprocessorGuards;
  82. public:
  83. SearchableTableEmitter(RecordKeeper &R) : Records(R) {}
  84. void run(raw_ostream &OS);
  85. private:
  86. typedef std::pair<Init *, int> SearchTableEntry;
  87. enum TypeContext {
  88. TypeInStaticStruct,
  89. TypeInTempStruct,
  90. TypeInArgument,
  91. };
  92. std::string primaryRepresentation(SMLoc Loc, const GenericField &Field,
  93. Init *I) {
  94. if (StringInit *SI = dyn_cast<StringInit>(I)) {
  95. if (Field.IsCode || SI->hasCodeFormat())
  96. return std::string(SI->getValue());
  97. else
  98. return SI->getAsString();
  99. } else if (BitsInit *BI = dyn_cast<BitsInit>(I))
  100. return "0x" + utohexstr(getAsInt(BI));
  101. else if (BitInit *BI = dyn_cast<BitInit>(I))
  102. return BI->getValue() ? "true" : "false";
  103. else if (Field.IsIntrinsic)
  104. return "Intrinsic::" + getIntrinsic(I).EnumName;
  105. else if (Field.IsInstruction)
  106. return I->getAsString();
  107. else if (Field.Enum) {
  108. auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()];
  109. if (!Entry)
  110. PrintFatalError(Loc,
  111. Twine("Entry for field '") + Field.Name + "' is null");
  112. return std::string(Entry->first);
  113. }
  114. PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
  115. "'; expected: bit, bits, string, or code");
  116. }
  117. bool isIntrinsic(Init *I) {
  118. if (DefInit *DI = dyn_cast<DefInit>(I))
  119. return DI->getDef()->isSubClassOf("Intrinsic");
  120. return false;
  121. }
  122. CodeGenIntrinsic &getIntrinsic(Init *I) {
  123. std::unique_ptr<CodeGenIntrinsic> &Intr = Intrinsics[I];
  124. if (!Intr)
  125. Intr = std::make_unique<CodeGenIntrinsic>(cast<DefInit>(I)->getDef(),
  126. std::vector<Record *>());
  127. return *Intr;
  128. }
  129. bool compareBy(Record *LHS, Record *RHS, const SearchIndex &Index);
  130. std::string searchableFieldType(const GenericTable &Table,
  131. const SearchIndex &Index,
  132. const GenericField &Field, TypeContext Ctx) {
  133. if (isa<StringRecTy>(Field.RecType)) {
  134. if (Ctx == TypeInStaticStruct)
  135. return "const char *";
  136. if (Ctx == TypeInTempStruct)
  137. return "std::string";
  138. return "StringRef";
  139. } else if (BitsRecTy *BI = dyn_cast<BitsRecTy>(Field.RecType)) {
  140. unsigned NumBits = BI->getNumBits();
  141. if (NumBits <= 8)
  142. return "uint8_t";
  143. if (NumBits <= 16)
  144. return "uint16_t";
  145. if (NumBits <= 32)
  146. return "uint32_t";
  147. if (NumBits <= 64)
  148. return "uint64_t";
  149. PrintFatalError(Index.Loc, Twine("In table '") + Table.Name +
  150. "' lookup method '" + Index.Name +
  151. "', key field '" + Field.Name +
  152. "' of type bits is too large");
  153. } else if (Field.Enum || Field.IsIntrinsic || Field.IsInstruction)
  154. return "unsigned";
  155. PrintFatalError(Index.Loc,
  156. Twine("In table '") + Table.Name + "' lookup method '" +
  157. Index.Name + "', key field '" + Field.Name +
  158. "' has invalid type: " + Field.RecType->getAsString());
  159. }
  160. void emitGenericTable(const GenericTable &Table, raw_ostream &OS);
  161. void emitGenericEnum(const GenericEnum &Enum, raw_ostream &OS);
  162. void emitLookupDeclaration(const GenericTable &Table,
  163. const SearchIndex &Index, raw_ostream &OS);
  164. void emitLookupFunction(const GenericTable &Table, const SearchIndex &Index,
  165. bool IsPrimary, raw_ostream &OS);
  166. void emitIfdef(StringRef Guard, raw_ostream &OS);
  167. bool parseFieldType(GenericField &Field, Init *II);
  168. std::unique_ptr<SearchIndex>
  169. parseSearchIndex(GenericTable &Table, const RecordVal *RecVal, StringRef Name,
  170. const std::vector<StringRef> &Key, bool EarlyOut);
  171. void collectEnumEntries(GenericEnum &Enum, StringRef NameField,
  172. StringRef ValueField,
  173. const std::vector<Record *> &Items);
  174. void collectTableEntries(GenericTable &Table,
  175. const std::vector<Record *> &Items);
  176. };
  177. } // End anonymous namespace.
  178. // For search indices that consists of a single field whose numeric value is
  179. // known, return that numeric value.
  180. static int64_t getNumericKey(const SearchIndex &Index, Record *Rec) {
  181. assert(Index.Fields.size() == 1);
  182. if (Index.Fields[0].Enum) {
  183. Record *EnumEntry = Rec->getValueAsDef(Index.Fields[0].Name);
  184. return Index.Fields[0].Enum->EntryMap[EnumEntry]->second;
  185. }
  186. return getInt(Rec, Index.Fields[0].Name);
  187. }
  188. /// Less-than style comparison between \p LHS and \p RHS according to the
  189. /// key of \p Index.
  190. bool SearchableTableEmitter::compareBy(Record *LHS, Record *RHS,
  191. const SearchIndex &Index) {
  192. for (const auto &Field : Index.Fields) {
  193. Init *LHSI = LHS->getValueInit(Field.Name);
  194. Init *RHSI = RHS->getValueInit(Field.Name);
  195. if (isa<BitsRecTy>(Field.RecType) || isa<IntRecTy>(Field.RecType)) {
  196. int64_t LHSi = getAsInt(LHSI);
  197. int64_t RHSi = getAsInt(RHSI);
  198. if (LHSi < RHSi)
  199. return true;
  200. if (LHSi > RHSi)
  201. return false;
  202. } else if (Field.IsIntrinsic) {
  203. CodeGenIntrinsic &LHSi = getIntrinsic(LHSI);
  204. CodeGenIntrinsic &RHSi = getIntrinsic(RHSI);
  205. if (std::tie(LHSi.TargetPrefix, LHSi.Name) <
  206. std::tie(RHSi.TargetPrefix, RHSi.Name))
  207. return true;
  208. if (std::tie(LHSi.TargetPrefix, LHSi.Name) >
  209. std::tie(RHSi.TargetPrefix, RHSi.Name))
  210. return false;
  211. } else if (Field.IsInstruction) {
  212. // This does not correctly compare the predefined instructions!
  213. Record *LHSr = cast<DefInit>(LHSI)->getDef();
  214. Record *RHSr = cast<DefInit>(RHSI)->getDef();
  215. bool LHSpseudo = LHSr->getValueAsBit("isPseudo");
  216. bool RHSpseudo = RHSr->getValueAsBit("isPseudo");
  217. if (LHSpseudo && !RHSpseudo)
  218. return true;
  219. if (!LHSpseudo && RHSpseudo)
  220. return false;
  221. int comp = LHSr->getName().compare(RHSr->getName());
  222. if (comp < 0)
  223. return true;
  224. if (comp > 0)
  225. return false;
  226. } else if (Field.Enum) {
  227. auto LHSr = cast<DefInit>(LHSI)->getDef();
  228. auto RHSr = cast<DefInit>(RHSI)->getDef();
  229. int64_t LHSv = Field.Enum->EntryMap[LHSr]->second;
  230. int64_t RHSv = Field.Enum->EntryMap[RHSr]->second;
  231. if (LHSv < RHSv)
  232. return true;
  233. if (LHSv > RHSv)
  234. return false;
  235. } else {
  236. std::string LHSs = primaryRepresentation(Index.Loc, Field, LHSI);
  237. std::string RHSs = primaryRepresentation(Index.Loc, Field, RHSI);
  238. if (isa<StringRecTy>(Field.RecType)) {
  239. LHSs = StringRef(LHSs).upper();
  240. RHSs = StringRef(RHSs).upper();
  241. }
  242. int comp = LHSs.compare(RHSs);
  243. if (comp < 0)
  244. return true;
  245. if (comp > 0)
  246. return false;
  247. }
  248. }
  249. return false;
  250. }
  251. void SearchableTableEmitter::emitIfdef(StringRef Guard, raw_ostream &OS) {
  252. OS << "#ifdef " << Guard << "\n";
  253. PreprocessorGuards.insert(std::string(Guard));
  254. }
  255. /// Emit a generic enum.
  256. void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
  257. raw_ostream &OS) {
  258. emitIfdef((Twine("GET_") + Enum.PreprocessorGuard + "_DECL").str(), OS);
  259. OS << "enum " << Enum.Name << " {\n";
  260. for (const auto &Entry : Enum.Entries)
  261. OS << " " << Entry->first << " = " << Entry->second << ",\n";
  262. OS << "};\n";
  263. OS << "#endif\n\n";
  264. }
  265. void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
  266. const SearchIndex &Index,
  267. bool IsPrimary,
  268. raw_ostream &OS) {
  269. OS << "\n";
  270. emitLookupDeclaration(Table, Index, OS);
  271. OS << " {\n";
  272. std::vector<Record *> IndexRowsStorage;
  273. ArrayRef<Record *> IndexRows;
  274. StringRef IndexTypeName;
  275. StringRef IndexName;
  276. if (IsPrimary) {
  277. IndexTypeName = Table.CppTypeName;
  278. IndexName = Table.Name;
  279. IndexRows = Table.Entries;
  280. } else {
  281. OS << " struct IndexType {\n";
  282. for (const auto &Field : Index.Fields) {
  283. OS << " "
  284. << searchableFieldType(Table, Index, Field, TypeInStaticStruct) << " "
  285. << Field.Name << ";\n";
  286. }
  287. OS << " unsigned _index;\n";
  288. OS << " };\n";
  289. OS << " static const struct IndexType Index[] = {\n";
  290. std::vector<std::pair<Record *, unsigned>> Entries;
  291. Entries.reserve(Table.Entries.size());
  292. for (unsigned i = 0; i < Table.Entries.size(); ++i)
  293. Entries.emplace_back(Table.Entries[i], i);
  294. llvm::stable_sort(Entries, [&](const std::pair<Record *, unsigned> &LHS,
  295. const std::pair<Record *, unsigned> &RHS) {
  296. return compareBy(LHS.first, RHS.first, Index);
  297. });
  298. IndexRowsStorage.reserve(Entries.size());
  299. for (const auto &Entry : Entries) {
  300. IndexRowsStorage.push_back(Entry.first);
  301. OS << " { ";
  302. ListSeparator LS;
  303. for (const auto &Field : Index.Fields) {
  304. std::string Repr = primaryRepresentation(
  305. Index.Loc, Field, Entry.first->getValueInit(Field.Name));
  306. if (isa<StringRecTy>(Field.RecType))
  307. Repr = StringRef(Repr).upper();
  308. OS << LS << Repr;
  309. }
  310. OS << ", " << Entry.second << " },\n";
  311. }
  312. OS << " };\n\n";
  313. IndexTypeName = "IndexType";
  314. IndexName = "Index";
  315. IndexRows = IndexRowsStorage;
  316. }
  317. bool IsContiguous = false;
  318. if (Index.Fields.size() == 1 &&
  319. (Index.Fields[0].Enum || isa<BitsRecTy>(Index.Fields[0].RecType))) {
  320. IsContiguous = true;
  321. for (unsigned i = 0; i < IndexRows.size(); ++i) {
  322. if (getNumericKey(Index, IndexRows[i]) != i) {
  323. IsContiguous = false;
  324. break;
  325. }
  326. }
  327. }
  328. if (IsContiguous) {
  329. OS << " auto Table = ArrayRef(" << IndexName << ");\n";
  330. OS << " size_t Idx = " << Index.Fields[0].Name << ";\n";
  331. OS << " return Idx >= Table.size() ? nullptr : ";
  332. if (IsPrimary)
  333. OS << "&Table[Idx]";
  334. else
  335. OS << "&" << Table.Name << "[Table[Idx]._index]";
  336. OS << ";\n";
  337. OS << "}\n";
  338. return;
  339. }
  340. if (Index.EarlyOut) {
  341. const GenericField &Field = Index.Fields[0];
  342. std::string FirstRepr = primaryRepresentation(
  343. Index.Loc, Field, IndexRows[0]->getValueInit(Field.Name));
  344. std::string LastRepr = primaryRepresentation(
  345. Index.Loc, Field, IndexRows.back()->getValueInit(Field.Name));
  346. OS << " if ((" << Field.Name << " < " << FirstRepr << ") ||\n";
  347. OS << " (" << Field.Name << " > " << LastRepr << "))\n";
  348. OS << " return nullptr;\n\n";
  349. }
  350. OS << " struct KeyType {\n";
  351. for (const auto &Field : Index.Fields) {
  352. OS << " " << searchableFieldType(Table, Index, Field, TypeInTempStruct)
  353. << " " << Field.Name << ";\n";
  354. }
  355. OS << " };\n";
  356. OS << " KeyType Key = {";
  357. ListSeparator LS;
  358. for (const auto &Field : Index.Fields) {
  359. OS << LS << Field.Name;
  360. if (isa<StringRecTy>(Field.RecType)) {
  361. OS << ".upper()";
  362. if (IsPrimary)
  363. PrintFatalError(Index.Loc,
  364. Twine("In table '") + Table.Name +
  365. "', use a secondary lookup method for "
  366. "case-insensitive comparison of field '" +
  367. Field.Name + "'");
  368. }
  369. }
  370. OS << "};\n";
  371. OS << " auto Table = ArrayRef(" << IndexName << ");\n";
  372. OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n";
  373. OS << " [](const " << IndexTypeName << " &LHS, const KeyType &RHS) {\n";
  374. for (const auto &Field : Index.Fields) {
  375. if (isa<StringRecTy>(Field.RecType)) {
  376. OS << " int Cmp" << Field.Name << " = StringRef(LHS." << Field.Name
  377. << ").compare(RHS." << Field.Name << ");\n";
  378. OS << " if (Cmp" << Field.Name << " < 0) return true;\n";
  379. OS << " if (Cmp" << Field.Name << " > 0) return false;\n";
  380. } else if (Field.Enum) {
  381. // Explicitly cast to unsigned, because the signedness of enums is
  382. // compiler-dependent.
  383. OS << " if ((unsigned)LHS." << Field.Name << " < (unsigned)RHS."
  384. << Field.Name << ")\n";
  385. OS << " return true;\n";
  386. OS << " if ((unsigned)LHS." << Field.Name << " > (unsigned)RHS."
  387. << Field.Name << ")\n";
  388. OS << " return false;\n";
  389. } else {
  390. OS << " if (LHS." << Field.Name << " < RHS." << Field.Name << ")\n";
  391. OS << " return true;\n";
  392. OS << " if (LHS." << Field.Name << " > RHS." << Field.Name << ")\n";
  393. OS << " return false;\n";
  394. }
  395. }
  396. OS << " return false;\n";
  397. OS << " });\n\n";
  398. OS << " if (Idx == Table.end()";
  399. for (const auto &Field : Index.Fields)
  400. OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name;
  401. OS << ")\n return nullptr;\n";
  402. if (IsPrimary)
  403. OS << " return &*Idx;\n";
  404. else
  405. OS << " return &" << Table.Name << "[Idx->_index];\n";
  406. OS << "}\n";
  407. }
  408. void SearchableTableEmitter::emitLookupDeclaration(const GenericTable &Table,
  409. const SearchIndex &Index,
  410. raw_ostream &OS) {
  411. OS << "const " << Table.CppTypeName << " *" << Index.Name << "(";
  412. ListSeparator LS;
  413. for (const auto &Field : Index.Fields)
  414. OS << LS << searchableFieldType(Table, Index, Field, TypeInArgument) << " "
  415. << Field.Name;
  416. OS << ")";
  417. }
  418. void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
  419. raw_ostream &OS) {
  420. emitIfdef((Twine("GET_") + Table.PreprocessorGuard + "_DECL").str(), OS);
  421. // Emit the declarations for the functions that will perform lookup.
  422. if (Table.PrimaryKey) {
  423. emitLookupDeclaration(Table, *Table.PrimaryKey, OS);
  424. OS << ";\n";
  425. }
  426. for (const auto &Index : Table.Indices) {
  427. emitLookupDeclaration(Table, *Index, OS);
  428. OS << ";\n";
  429. }
  430. OS << "#endif\n\n";
  431. emitIfdef((Twine("GET_") + Table.PreprocessorGuard + "_IMPL").str(), OS);
  432. // The primary data table contains all the fields defined for this map.
  433. OS << "constexpr " << Table.CppTypeName << " " << Table.Name << "[] = {\n";
  434. for (unsigned i = 0; i < Table.Entries.size(); ++i) {
  435. Record *Entry = Table.Entries[i];
  436. OS << " { ";
  437. ListSeparator LS;
  438. for (const auto &Field : Table.Fields)
  439. OS << LS
  440. << primaryRepresentation(Table.Locs[0], Field,
  441. Entry->getValueInit(Field.Name));
  442. OS << " }, // " << i << "\n";
  443. }
  444. OS << " };\n";
  445. // Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
  446. // search can be performed by "Thing".
  447. if (Table.PrimaryKey)
  448. emitLookupFunction(Table, *Table.PrimaryKey, true, OS);
  449. for (const auto &Index : Table.Indices)
  450. emitLookupFunction(Table, *Index, false, OS);
  451. OS << "#endif\n\n";
  452. }
  453. bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
  454. if (auto Type = dyn_cast<StringInit>(TypeOf)) {
  455. if (Type->getValue() == "code") {
  456. Field.IsCode = true;
  457. return true;
  458. } else {
  459. if (Record *TypeRec = Records.getDef(Type->getValue())) {
  460. if (TypeRec->isSubClassOf("GenericEnum")) {
  461. Field.Enum = EnumMap[TypeRec];
  462. Field.RecType = RecordRecTy::get(Field.Enum->Class);
  463. return true;
  464. }
  465. }
  466. }
  467. }
  468. return false;
  469. }
  470. std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
  471. GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name,
  472. const std::vector<StringRef> &Key, bool EarlyOut) {
  473. auto Index = std::make_unique<SearchIndex>();
  474. Index->Name = std::string(Name);
  475. Index->Loc = KeyRecVal->getLoc();
  476. Index->EarlyOut = EarlyOut;
  477. for (const auto &FieldName : Key) {
  478. const GenericField *Field = Table.getFieldByName(FieldName);
  479. if (!Field)
  480. PrintFatalError(
  481. KeyRecVal,
  482. Twine("In table '") + Table.Name +
  483. "', 'PrimaryKey' or 'Key' refers to nonexistent field '" +
  484. FieldName + "'");
  485. Index->Fields.push_back(*Field);
  486. }
  487. if (EarlyOut && isa<StringRecTy>(Index->Fields[0].RecType)) {
  488. PrintFatalError(
  489. KeyRecVal, Twine("In lookup method '") + Name + "', early-out is not " +
  490. "supported for a first key field of type string");
  491. }
  492. return Index;
  493. }
  494. void SearchableTableEmitter::collectEnumEntries(
  495. GenericEnum &Enum, StringRef NameField, StringRef ValueField,
  496. const std::vector<Record *> &Items) {
  497. for (auto *EntryRec : Items) {
  498. StringRef Name;
  499. if (NameField.empty())
  500. Name = EntryRec->getName();
  501. else
  502. Name = EntryRec->getValueAsString(NameField);
  503. int64_t Value = 0;
  504. if (!ValueField.empty())
  505. Value = getInt(EntryRec, ValueField);
  506. Enum.Entries.push_back(std::make_unique<GenericEnum::Entry>(Name, Value));
  507. Enum.EntryMap.insert(std::make_pair(EntryRec, Enum.Entries.back().get()));
  508. }
  509. if (ValueField.empty()) {
  510. llvm::stable_sort(Enum.Entries,
  511. [](const std::unique_ptr<GenericEnum::Entry> &LHS,
  512. const std::unique_ptr<GenericEnum::Entry> &RHS) {
  513. return LHS->first < RHS->first;
  514. });
  515. for (size_t i = 0; i < Enum.Entries.size(); ++i)
  516. Enum.Entries[i]->second = i;
  517. }
  518. }
  519. void SearchableTableEmitter::collectTableEntries(
  520. GenericTable &Table, const std::vector<Record *> &Items) {
  521. if (Items.empty())
  522. PrintFatalError(Table.Locs,
  523. Twine("Table '") + Table.Name + "' has no entries");
  524. for (auto *EntryRec : Items) {
  525. for (auto &Field : Table.Fields) {
  526. auto TI = dyn_cast<TypedInit>(EntryRec->getValueInit(Field.Name));
  527. if (!TI || !TI->isComplete()) {
  528. PrintFatalError(EntryRec, Twine("Record '") + EntryRec->getName() +
  529. "' for table '" + Table.Name +
  530. "' is missing field '" + Field.Name +
  531. "'");
  532. }
  533. if (!Field.RecType) {
  534. Field.RecType = TI->getType();
  535. } else {
  536. RecTy *Ty = resolveTypes(Field.RecType, TI->getType());
  537. if (!Ty)
  538. PrintFatalError(EntryRec->getValue(Field.Name),
  539. Twine("Field '") + Field.Name + "' of table '" +
  540. Table.Name + "' entry has incompatible type: " +
  541. TI->getType()->getAsString() + " vs. " +
  542. Field.RecType->getAsString());
  543. Field.RecType = Ty;
  544. }
  545. }
  546. Table.Entries.push_back(EntryRec); // Add record to table's record list.
  547. }
  548. Record *IntrinsicClass = Records.getClass("Intrinsic");
  549. Record *InstructionClass = Records.getClass("Instruction");
  550. for (auto &Field : Table.Fields) {
  551. if (!Field.RecType)
  552. PrintFatalError(Twine("Cannot determine type of field '") + Field.Name +
  553. "' in table '" + Table.Name + "'. Maybe it is not used?");
  554. if (auto RecordTy = dyn_cast<RecordRecTy>(Field.RecType)) {
  555. if (IntrinsicClass && RecordTy->isSubClassOf(IntrinsicClass))
  556. Field.IsIntrinsic = true;
  557. else if (InstructionClass && RecordTy->isSubClassOf(InstructionClass))
  558. Field.IsInstruction = true;
  559. }
  560. }
  561. SearchIndex Idx;
  562. std::copy(Table.Fields.begin(), Table.Fields.end(),
  563. std::back_inserter(Idx.Fields));
  564. llvm::sort(Table.Entries, [&](Record *LHS, Record *RHS) {
  565. return compareBy(LHS, RHS, Idx);
  566. });
  567. }
  568. void SearchableTableEmitter::run(raw_ostream &OS) {
  569. // Emit tables in a deterministic order to avoid needless rebuilds.
  570. SmallVector<std::unique_ptr<GenericTable>, 4> Tables;
  571. DenseMap<Record *, GenericTable *> TableMap;
  572. // Collect all definitions first.
  573. for (auto *EnumRec : Records.getAllDerivedDefinitions("GenericEnum")) {
  574. StringRef NameField;
  575. if (!EnumRec->isValueUnset("NameField"))
  576. NameField = EnumRec->getValueAsString("NameField");
  577. StringRef ValueField;
  578. if (!EnumRec->isValueUnset("ValueField"))
  579. ValueField = EnumRec->getValueAsString("ValueField");
  580. auto Enum = std::make_unique<GenericEnum>();
  581. Enum->Name = std::string(EnumRec->getName());
  582. Enum->PreprocessorGuard = std::string(EnumRec->getName());
  583. StringRef FilterClass = EnumRec->getValueAsString("FilterClass");
  584. Enum->Class = Records.getClass(FilterClass);
  585. if (!Enum->Class)
  586. PrintFatalError(EnumRec->getValue("FilterClass"),
  587. Twine("Enum FilterClass '") + FilterClass +
  588. "' does not exist");
  589. collectEnumEntries(*Enum, NameField, ValueField,
  590. Records.getAllDerivedDefinitions(FilterClass));
  591. EnumMap.insert(std::make_pair(EnumRec, Enum.get()));
  592. Enums.emplace_back(std::move(Enum));
  593. }
  594. for (auto *TableRec : Records.getAllDerivedDefinitions("GenericTable")) {
  595. auto Table = std::make_unique<GenericTable>();
  596. Table->Name = std::string(TableRec->getName());
  597. Table->Locs = TableRec->getLoc();
  598. Table->PreprocessorGuard = std::string(TableRec->getName());
  599. Table->CppTypeName = std::string(TableRec->getValueAsString("CppTypeName"));
  600. std::vector<StringRef> Fields = TableRec->getValueAsListOfStrings("Fields");
  601. for (const auto &FieldName : Fields) {
  602. Table->Fields.emplace_back(FieldName); // Construct a GenericField.
  603. if (auto TypeOfRecordVal = TableRec->getValue(("TypeOf_" + FieldName).str())) {
  604. if (!parseFieldType(Table->Fields.back(), TypeOfRecordVal->getValue())) {
  605. PrintError(TypeOfRecordVal,
  606. Twine("Table '") + Table->Name +
  607. "' has invalid 'TypeOf_" + FieldName +
  608. "': " + TypeOfRecordVal->getValue()->getAsString());
  609. PrintFatalNote("The 'TypeOf_xxx' field must be a string naming a "
  610. "GenericEnum record, or \"code\"");
  611. }
  612. }
  613. }
  614. StringRef FilterClass = TableRec->getValueAsString("FilterClass");
  615. if (!Records.getClass(FilterClass))
  616. PrintFatalError(TableRec->getValue("FilterClass"),
  617. Twine("Table FilterClass '") +
  618. FilterClass + "' does not exist");
  619. collectTableEntries(*Table, Records.getAllDerivedDefinitions(FilterClass));
  620. if (!TableRec->isValueUnset("PrimaryKey")) {
  621. Table->PrimaryKey =
  622. parseSearchIndex(*Table, TableRec->getValue("PrimaryKey"),
  623. TableRec->getValueAsString("PrimaryKeyName"),
  624. TableRec->getValueAsListOfStrings("PrimaryKey"),
  625. TableRec->getValueAsBit("PrimaryKeyEarlyOut"));
  626. llvm::stable_sort(Table->Entries, [&](Record *LHS, Record *RHS) {
  627. return compareBy(LHS, RHS, *Table->PrimaryKey);
  628. });
  629. }
  630. TableMap.insert(std::make_pair(TableRec, Table.get()));
  631. Tables.emplace_back(std::move(Table));
  632. }
  633. for (Record *IndexRec : Records.getAllDerivedDefinitions("SearchIndex")) {
  634. Record *TableRec = IndexRec->getValueAsDef("Table");
  635. auto It = TableMap.find(TableRec);
  636. if (It == TableMap.end())
  637. PrintFatalError(IndexRec->getValue("Table"),
  638. Twine("SearchIndex '") + IndexRec->getName() +
  639. "' refers to nonexistent table '" +
  640. TableRec->getName());
  641. GenericTable &Table = *It->second;
  642. Table.Indices.push_back(
  643. parseSearchIndex(Table, IndexRec->getValue("Key"), IndexRec->getName(),
  644. IndexRec->getValueAsListOfStrings("Key"),
  645. IndexRec->getValueAsBit("EarlyOut")));
  646. }
  647. // Translate legacy tables.
  648. Record *SearchableTable = Records.getClass("SearchableTable");
  649. for (auto &NameRec : Records.getClasses()) {
  650. Record *Class = NameRec.second.get();
  651. if (Class->getSuperClasses().size() != 1 ||
  652. !Class->isSubClassOf(SearchableTable))
  653. continue;
  654. StringRef TableName = Class->getName();
  655. std::vector<Record *> Items = Records.getAllDerivedDefinitions(TableName);
  656. if (!Class->isValueUnset("EnumNameField")) {
  657. StringRef NameField = Class->getValueAsString("EnumNameField");
  658. StringRef ValueField;
  659. if (!Class->isValueUnset("EnumValueField"))
  660. ValueField = Class->getValueAsString("EnumValueField");
  661. auto Enum = std::make_unique<GenericEnum>();
  662. Enum->Name = (Twine(Class->getName()) + "Values").str();
  663. Enum->PreprocessorGuard = Class->getName().upper();
  664. Enum->Class = Class;
  665. collectEnumEntries(*Enum, NameField, ValueField, Items);
  666. Enums.emplace_back(std::move(Enum));
  667. }
  668. auto Table = std::make_unique<GenericTable>();
  669. Table->Name = (Twine(Class->getName()) + "sList").str();
  670. Table->Locs = Class->getLoc();
  671. Table->PreprocessorGuard = Class->getName().upper();
  672. Table->CppTypeName = std::string(Class->getName());
  673. for (const RecordVal &Field : Class->getValues()) {
  674. std::string FieldName = std::string(Field.getName());
  675. // Skip uninteresting fields: either special to us, or injected
  676. // template parameters (if they contain a ':').
  677. if (FieldName.find(':') != std::string::npos ||
  678. FieldName == "SearchableFields" || FieldName == "EnumNameField" ||
  679. FieldName == "EnumValueField")
  680. continue;
  681. Table->Fields.emplace_back(FieldName);
  682. }
  683. collectTableEntries(*Table, Items);
  684. for (const auto &Field :
  685. Class->getValueAsListOfStrings("SearchableFields")) {
  686. std::string Name =
  687. (Twine("lookup") + Table->CppTypeName + "By" + Field).str();
  688. Table->Indices.push_back(parseSearchIndex(*Table, Class->getValue(Field),
  689. Name, {Field}, false));
  690. }
  691. Tables.emplace_back(std::move(Table));
  692. }
  693. // Emit everything.
  694. for (const auto &Enum : Enums)
  695. emitGenericEnum(*Enum, OS);
  696. for (const auto &Table : Tables)
  697. emitGenericTable(*Table, OS);
  698. // Put all #undefs last, to allow multiple sections guarded by the same
  699. // define.
  700. for (const auto &Guard : PreprocessorGuards)
  701. OS << "#undef " << Guard << "\n";
  702. }
  703. namespace llvm {
  704. void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS) {
  705. SearchableTableEmitter(RK).run(OS);
  706. }
  707. } // End llvm namespace.