|
17 | 17 | #include "Common/CodeGenTarget.h"
|
18 | 18 | #include "llvm/ADT/ArrayRef.h"
|
19 | 19 | #include "llvm/ADT/DenseMap.h"
|
| 20 | +#include "llvm/ADT/MapVector.h" |
20 | 21 | #include "llvm/ADT/STLExtras.h"
|
21 | 22 | #include "llvm/ADT/StringExtras.h"
|
22 | 23 | #include "llvm/TableGen/Error.h"
|
@@ -44,13 +45,23 @@ static int64_t getInt(const Record *R, StringRef Field) {
|
44 | 45 |
|
45 | 46 | namespace {
|
46 | 47 | struct GenericEnum {
|
47 |
| - using Entry = std::pair<StringRef, int64_t>; |
| 48 | + struct Entry { |
| 49 | + StringRef Name; |
| 50 | + int64_t Value; |
| 51 | + Entry(StringRef N, int64_t V) : Name(N), Value(V) {} |
| 52 | + }; |
48 | 53 |
|
49 | 54 | std::string Name;
|
50 | 55 | const Record *Class = nullptr;
|
51 | 56 | std::string PreprocessorGuard;
|
52 |
| - std::vector<std::unique_ptr<Entry>> Entries; |
53 |
| - DenseMap<const Record *, Entry *> EntryMap; |
| 57 | + MapVector<const Record *, Entry> Entries; |
| 58 | + |
| 59 | + const Entry *getEntry(const Record *Def) const { |
| 60 | + auto II = Entries.find(Def); |
| 61 | + if (II == Entries.end()) |
| 62 | + return nullptr; |
| 63 | + return &II->second; |
| 64 | + } |
54 | 65 | };
|
55 | 66 |
|
56 | 67 | struct GenericField {
|
@@ -129,11 +140,12 @@ class SearchableTableEmitter {
|
129 | 140 | else if (Field.IsInstruction)
|
130 | 141 | return I->getAsString();
|
131 | 142 | else if (Field.Enum) {
|
132 |
| - auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()]; |
| 143 | + const GenericEnum::Entry *Entry = |
| 144 | + Field.Enum->getEntry(cast<DefInit>(I)->getDef()); |
133 | 145 | if (!Entry)
|
134 | 146 | PrintFatalError(Loc,
|
135 | 147 | Twine("Entry for field '") + Field.Name + "' is null");
|
136 |
| - return Entry->first.str(); |
| 148 | + return Entry->Name.str(); |
137 | 149 | }
|
138 | 150 | PrintFatalError(Loc, Twine("invalid field type for field '") + Field.Name +
|
139 | 151 | "'; expected: bit, bits, string, or code");
|
@@ -221,7 +233,7 @@ int64_t SearchableTableEmitter::getNumericKey(const SearchIndex &Index,
|
221 | 233 | }
|
222 | 234 | if (Field.Enum) {
|
223 | 235 | const Record *EnumEntry = Rec->getValueAsDef(Field.Name);
|
224 |
| - return Field.Enum->EntryMap[EnumEntry]->second; |
| 236 | + return Field.Enum->getEntry(EnumEntry)->Value; |
225 | 237 | }
|
226 | 238 | assert(isa<BitsRecTy>(Field.RecType) && "unexpected field type");
|
227 | 239 |
|
@@ -272,8 +284,8 @@ bool SearchableTableEmitter::compareBy(const Record *LHS, const Record *RHS,
|
272 | 284 | } else if (Field.Enum) {
|
273 | 285 | auto LHSr = cast<DefInit>(LHSI)->getDef();
|
274 | 286 | auto RHSr = cast<DefInit>(RHSI)->getDef();
|
275 |
| - int64_t LHSv = Field.Enum->EntryMap[LHSr]->second; |
276 |
| - int64_t RHSv = Field.Enum->EntryMap[RHSr]->second; |
| 287 | + int64_t LHSv = Field.Enum->getEntry(LHSr)->Value; |
| 288 | + int64_t RHSv = Field.Enum->getEntry(RHSr)->Value; |
277 | 289 | if (LHSv < RHSv)
|
278 | 290 | return true;
|
279 | 291 | if (LHSv > RHSv)
|
@@ -308,8 +320,9 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
|
308 | 320 | emitIfdef((Twine("GET_") + Enum.PreprocessorGuard + "_DECL").str(), OS);
|
309 | 321 |
|
310 | 322 | OS << "enum " << Enum.Name << " {\n";
|
311 |
| - for (const auto &Entry : Enum.Entries) |
312 |
| - OS << " " << Entry->first << " = " << Entry->second << ",\n"; |
| 323 | + for (const auto &[Name, Value] : |
| 324 | + make_second_range(Enum.Entries.getArrayRef())) |
| 325 | + OS << " " << Name << " = " << Value << ",\n"; |
313 | 326 | OS << "};\n";
|
314 | 327 |
|
315 | 328 | OS << "#endif\n\n";
|
@@ -625,30 +638,28 @@ std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
|
625 | 638 | void SearchableTableEmitter::collectEnumEntries(
|
626 | 639 | GenericEnum &Enum, StringRef NameField, StringRef ValueField,
|
627 | 640 | ArrayRef<const Record *> Items) {
|
| 641 | + Enum.Entries.reserve(Items.size()); |
628 | 642 | for (const Record *EntryRec : Items) {
|
629 |
| - StringRef Name; |
630 |
| - if (NameField.empty()) |
631 |
| - Name = EntryRec->getName(); |
632 |
| - else |
633 |
| - Name = EntryRec->getValueAsString(NameField); |
634 |
| - |
635 |
| - int64_t Value = 0; |
636 |
| - if (!ValueField.empty()) |
637 |
| - Value = getInt(EntryRec, ValueField); |
638 |
| - |
639 |
| - Enum.Entries.push_back(std::make_unique<GenericEnum::Entry>(Name, Value)); |
640 |
| - Enum.EntryMap.try_emplace(EntryRec, Enum.Entries.back().get()); |
| 643 | + StringRef Name = NameField.empty() ? EntryRec->getName() |
| 644 | + : EntryRec->getValueAsString(NameField); |
| 645 | + int64_t Value = ValueField.empty() ? 0 : getInt(EntryRec, ValueField); |
| 646 | + Enum.Entries.try_emplace(EntryRec, Name, Value); |
641 | 647 | }
|
642 | 648 |
|
| 649 | + // If no values are provided for enums, assign values in the order of sorted |
| 650 | + // enum names. |
643 | 651 | if (ValueField.empty()) {
|
644 |
| - llvm::stable_sort(Enum.Entries, |
645 |
| - [](const std::unique_ptr<GenericEnum::Entry> &LHS, |
646 |
| - const std::unique_ptr<GenericEnum::Entry> &RHS) { |
647 |
| - return LHS->first < RHS->first; |
648 |
| - }); |
649 |
| - |
650 |
| - for (size_t i = 0; i < Enum.Entries.size(); ++i) |
651 |
| - Enum.Entries[i]->second = i; |
| 652 | + // Copy the map entries for sorting and clear the map. |
| 653 | + auto SavedEntries = Enum.Entries.takeVector(); |
| 654 | + using MapVectorEntryTy = std::pair<const Record *, GenericEnum::Entry>; |
| 655 | + llvm::stable_sort(SavedEntries, [](const MapVectorEntryTy &LHS, |
| 656 | + const MapVectorEntryTy &RHS) { |
| 657 | + return LHS.second.Name < RHS.second.Name; |
| 658 | + }); |
| 659 | + |
| 660 | + // Repopulate entries using the new sorted order. |
| 661 | + for (auto [Idx, Entry] : enumerate(SavedEntries)) |
| 662 | + Enum.Entries.try_emplace(Entry.first, Entry.second.Name, Idx); |
652 | 663 | }
|
653 | 664 | }
|
654 | 665 |
|
|
0 commit comments