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