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