SearchableTableEmitter.cpp 29 KB

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