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