@@ -68,6 +68,7 @@ struct SearchIndex {
6868 SMLoc Loc; // Source location of PrimaryKey or Key field definition.
6969 SmallVector<GenericField, 1 > Fields;
7070 bool EarlyOut = false ;
71+ bool ReturnRange = false ;
7172};
7273
7374struct GenericTable {
@@ -198,7 +199,8 @@ class SearchableTableEmitter {
198199 bool parseFieldType (GenericField &Field, Init *II);
199200 std::unique_ptr<SearchIndex>
200201 parseSearchIndex (GenericTable &Table, const RecordVal *RecVal, StringRef Name,
201- const std::vector<StringRef> &Key, bool EarlyOut);
202+ const std::vector<StringRef> &Key, bool EarlyOut,
203+ bool ReturnRange);
202204 void collectEnumEntries (GenericEnum &Enum, StringRef NameField,
203205 StringRef ValueField,
204206 const std::vector<Record *> &Items);
@@ -426,16 +428,25 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
426428 OS << " return nullptr;\n\n " ;
427429 }
428430
429- OS << " struct KeyType {\n " ;
430- for (const auto &Field : Index.Fields ) {
431- OS << " " << searchableFieldType (Table, Index, Field, TypeInTempStruct)
432- << " " << Field.Name << " ;\n " ;
431+ bool ShouldReturnRange = Index.ReturnRange ;
432+ if (ShouldReturnRange)
433+ OS << " " << IndexTypeName << " Key;\n " ;
434+ else {
435+ OS << " struct KeyType {\n " ;
436+ for (const auto &Field : Index.Fields ) {
437+ OS << " " << searchableFieldType (Table, Index, Field, TypeInTempStruct)
438+ << " " << Field.Name << " ;\n " ;
439+ }
440+ OS << " };\n " ;
441+ OS << " KeyType Key = {" ;
433442 }
434- OS << " };\n " ;
435- OS << " KeyType Key = {" ;
443+
436444 ListSeparator LS;
437445 for (const auto &Field : Index.Fields ) {
438- OS << LS << Field.Name ;
446+ if (ShouldReturnRange)
447+ OS << " Key." << Field.Name << " = " << Field.Name ;
448+ else
449+ OS << LS << Field.Name ;
439450 if (isa<StringRecTy>(Field.RecType )) {
440451 OS << " .upper()" ;
441452 if (IsPrimary)
@@ -445,12 +456,21 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
445456 " case-insensitive comparison of field '" +
446457 Field.Name + " '" );
447458 }
459+ if (ShouldReturnRange)
460+ OS << " ;\n " ;
448461 }
449- OS << " };\n " ;
462+ if (!ShouldReturnRange)
463+ OS << " };\n " ;
450464
451465 OS << " auto Table = ArrayRef(" << IndexName << " );\n " ;
452- OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n " ;
453- OS << " [](const " << IndexTypeName << " &LHS, const KeyType &RHS) {\n " ;
466+ if (ShouldReturnRange) {
467+ OS << " auto It = std::equal_range(Table.begin(), Table.end(), Key,\n " ;
468+ OS << " [](const " << IndexTypeName << " &LHS, const " << IndexTypeName
469+ << " &RHS) {\n " ;
470+ } else {
471+ OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n " ;
472+ OS << " [](const " << IndexTypeName << " &LHS, const KeyType &RHS) {\n " ;
473+ }
454474
455475 for (const auto &Field : Index.Fields ) {
456476 if (isa<StringRecTy>(Field.RecType )) {
@@ -478,25 +498,33 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
478498 OS << " return false;\n " ;
479499 OS << " });\n\n " ;
480500
481- OS << " if (Idx == Table.end() " ;
482-
483- for (const auto &Field : Index.Fields )
484- OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name ;
485- OS << " ) \n return nullptr; \n " ;
501+ if (!ShouldReturnRange) {
502+ OS << " if (Idx == Table.end() " ;
503+ for (const auto &Field : Index.Fields )
504+ OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name ;
505+ }
486506
487- if (IsPrimary)
507+ if (ShouldReturnRange)
508+ OS << " return llvm::make_range(It.first, It.second);\n " ;
509+ else if (IsPrimary) {
510+ OS << " )\n return nullptr;\n\n " ;
488511 OS << " return &*Idx;\n " ;
489- else
512+ } else {
513+ OS << " )\n return nullptr;\n\n " ;
490514 OS << " return &" << Table.Name << " [Idx->_index];\n " ;
515+ }
491516
492517 OS << " }\n " ;
493518}
494519
495520void SearchableTableEmitter::emitLookupDeclaration (const GenericTable &Table,
496521 const SearchIndex &Index,
497522 raw_ostream &OS) {
498- OS << " const " << Table.CppTypeName << " *" << Index.Name << " (" ;
499-
523+ if (Index.ReturnRange )
524+ OS << " llvm::iterator_range<const " << Table.CppTypeName << " *> " ;
525+ else
526+ OS << " const " << Table.CppTypeName << " *" ;
527+ OS << Index.Name << " (" ;
500528 ListSeparator LS;
501529 for (const auto &Field : Index.Fields )
502530 OS << LS << searchableFieldType (Table, Index, Field, TypeInArgument) << " "
@@ -510,11 +538,12 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
510538
511539 // Emit the declarations for the functions that will perform lookup.
512540 if (Table.PrimaryKey ) {
513- emitLookupDeclaration (Table, *Table.PrimaryKey , OS);
541+ auto &Index = Table.PrimaryKey ;
542+ emitLookupDeclaration (Table, *Index, OS);
514543 OS << " ;\n " ;
515544 }
516545 for (const auto &Index : Table.Indices ) {
517- emitLookupDeclaration (Table, *Index, OS);
546+ emitLookupDeclaration (Table, *Index, OS);
518547 OS << " ;\n " ;
519548 }
520549
@@ -540,10 +569,12 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
540569
541570 // Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542571 // search can be performed by "Thing".
543- if (Table.PrimaryKey )
544- emitLookupFunction (Table, *Table.PrimaryKey , true , OS);
572+ if (Table.PrimaryKey ) {
573+ auto &Index = Table.PrimaryKey ;
574+ emitLookupFunction (Table, *Index, /* IsPrimary=*/ true , OS);
575+ }
545576 for (const auto &Index : Table.Indices )
546- emitLookupFunction (Table, *Index, false , OS);
577+ emitLookupFunction (Table, *Index, /* IsPrimary= */ false , OS);
547578
548579 OS << " #endif\n\n " ;
549580}
@@ -569,11 +600,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569600
570601std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571602 GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name,
572- const std::vector<StringRef> &Key, bool EarlyOut) {
603+ const std::vector<StringRef> &Key, bool EarlyOut, bool ReturnRange ) {
573604 auto Index = std::make_unique<SearchIndex>();
574605 Index->Name = std::string (Name);
575606 Index->Loc = KeyRecVal->getLoc ();
576607 Index->EarlyOut = EarlyOut;
608+ Index->ReturnRange = ReturnRange;
577609
578610 for (const auto &FieldName : Key) {
579611 const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +801,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769801 parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770802 TableRec->getValueAsString (" PrimaryKeyName" ),
771803 TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
804+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
805+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773806
774807 llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775808 return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -793,7 +826,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
793826 Table.Indices .push_back (
794827 parseSearchIndex (Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
795828 IndexRec->getValueAsListOfStrings (" Key" ),
796- IndexRec->getValueAsBit (" EarlyOut" )));
829+ IndexRec->getValueAsBit (" EarlyOut" ),
830+ IndexRec->getValueAsBit (" ReturnRange" )));
797831 }
798832
799833 // Translate legacy tables.
@@ -848,7 +882,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
848882 std::string Name =
849883 (Twine (" lookup" ) + Table->CppTypeName + " By" + Field).str ();
850884 Table->Indices .push_back (parseSearchIndex (*Table, Class->getValue (Field),
851- Name, {Field}, false ));
885+ Name, {Field}, false , false ));
852886 }
853887
854888 Tables.emplace_back (std::move (Table));
0 commit comments