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