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