SearchableTableEmitter.cpp 29 KB

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