@@ -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);
@@ -448,55 +450,81 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
448450 }
449451 OS << " };\n " ;
450452
451- 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 " ;
453+ OS << " struct Comp { \n " ;
454+ OS << " bool operator()(const " << IndexTypeName
455+ << " &LHS, const KeyType &RHS) const {\n " ;
454456
455- for (const auto &Field : Index.Fields ) {
456- if (isa<StringRecTy>(Field.RecType )) {
457- OS << " int Cmp" << Field.Name << " = StringRef(LHS." << Field.Name
458- << " ).compare(RHS." << Field.Name << " );\n " ;
459- OS << " if (Cmp" << Field.Name << " < 0) return true;\n " ;
460- OS << " if (Cmp" << Field.Name << " > 0) return false;\n " ;
461- } else if (Field.Enum ) {
462- // Explicitly cast to unsigned, because the signedness of enums is
463- // compiler-dependent.
464- OS << " if ((unsigned)LHS." << Field.Name << " < (unsigned)RHS."
465- << Field.Name << " )\n " ;
466- OS << " return true;\n " ;
467- OS << " if ((unsigned)LHS." << Field.Name << " > (unsigned)RHS."
468- << Field.Name << " )\n " ;
469- OS << " return false;\n " ;
470- } else {
471- OS << " if (LHS." << Field.Name << " < RHS." << Field.Name << " )\n " ;
472- OS << " return true;\n " ;
473- OS << " if (LHS." << Field.Name << " > RHS." << Field.Name << " )\n " ;
474- OS << " return false;\n " ;
457+ auto emitComparator = [&]() {
458+ for (const auto &Field : Index.Fields ) {
459+ if (isa<StringRecTy>(Field.RecType )) {
460+ OS << " int Cmp" << Field.Name << " = StringRef(LHS." << Field.Name
461+ << " ).compare(RHS." << Field.Name << " );\n " ;
462+ OS << " if (Cmp" << Field.Name << " < 0) return true;\n " ;
463+ OS << " if (Cmp" << Field.Name << " > 0) return false;\n " ;
464+ } else if (Field.Enum ) {
465+ // Explicitly cast to unsigned, because the signedness of enums is
466+ // compiler-dependent.
467+ OS << " if ((unsigned)LHS." << Field.Name << " < (unsigned)RHS."
468+ << Field.Name << " )\n " ;
469+ OS << " return true;\n " ;
470+ OS << " if ((unsigned)LHS." << Field.Name << " > (unsigned)RHS."
471+ << Field.Name << " )\n " ;
472+ OS << " return false;\n " ;
473+ } else {
474+ OS << " if (LHS." << Field.Name << " < RHS." << Field.Name
475+ << " )\n " ;
476+ OS << " return true;\n " ;
477+ OS << " if (LHS." << Field.Name << " > RHS." << Field.Name
478+ << " )\n " ;
479+ OS << " return false;\n " ;
480+ }
475481 }
482+ OS << " return false;\n " ;
483+ OS << " }\n " ;
484+ };
485+ emitComparator ();
486+ bool ShouldReturnRange = Index.ReturnRange ;
487+ if (ShouldReturnRange) {
488+ OS << " bool operator()(const KeyType &LHS, const " << IndexTypeName
489+ << " &RHS) const {\n " ;
490+ emitComparator ();
476491 }
477492
478- OS << " return false;\n " ;
479- OS << " });\n\n " ;
480-
481- OS << " if (Idx == Table.end()" ;
493+ OS << " };\n " ;
494+ OS << " auto Table = ArrayRef(" << IndexName << " );\n " ;
495+ if (ShouldReturnRange)
496+ OS << " auto It = std::equal_range(Table.begin(), Table.end(), Key, " ;
497+ else
498+ OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, " ;
499+ OS << " Comp());\n " ;
482500
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) << " "
@@ -541,9 +569,9 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
541569 // Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542570 // search can be performed by "Thing".
543571 if (Table.PrimaryKey )
544- emitLookupFunction (Table, *Table.PrimaryKey , true , OS);
572+ emitLookupFunction (Table, *Table.PrimaryKey , /* IsPrimary= */ true , OS);
545573 for (const auto &Index : Table.Indices )
546- emitLookupFunction (Table, *Index, false , OS);
574+ emitLookupFunction (Table, *Index, /* IsPrimary= */ false , OS);
547575
548576 OS << " #endif\n\n " ;
549577}
@@ -569,11 +597,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569597
570598std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571599 GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name,
572- const std::vector<StringRef> &Key, bool EarlyOut) {
600+ const std::vector<StringRef> &Key, bool EarlyOut, bool ReturnRange ) {
573601 auto Index = std::make_unique<SearchIndex>();
574602 Index->Name = std::string (Name);
575603 Index->Loc = KeyRecVal->getLoc ();
576604 Index->EarlyOut = EarlyOut;
605+ Index->ReturnRange = ReturnRange;
577606
578607 for (const auto &FieldName : Key) {
579608 const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +798,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769798 parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770799 TableRec->getValueAsString (" PrimaryKeyName" ),
771800 TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
801+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
802+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773803
774804 llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775805 return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -790,10 +820,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
790820 TableRec->getName ());
791821
792822 GenericTable &Table = *It->second ;
793- Table.Indices .push_back (
794- parseSearchIndex ( Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
795- IndexRec->getValueAsListOfStrings (" Key" ),
796- IndexRec->getValueAsBit (" EarlyOut" )));
823+ Table.Indices .push_back (parseSearchIndex (
824+ Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
825+ IndexRec->getValueAsListOfStrings (" Key" ),
826+ IndexRec->getValueAsBit (" EarlyOut" ), /* ReturnRange */ false ));
797827 }
798828
799829 // Translate legacy tables.
@@ -847,8 +877,9 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
847877 Class->getValueAsListOfStrings (" SearchableFields" )) {
848878 std::string Name =
849879 (Twine (" lookup" ) + Table->CppTypeName + " By" + Field).str ();
850- Table->Indices .push_back (parseSearchIndex (*Table, Class->getValue (Field),
851- Name, {Field}, false ));
880+ Table->Indices .push_back (
881+ parseSearchIndex (*Table, Class->getValue (Field), Name, {Field},
882+ /* EarlyOut*/ false , /* ReturnRange*/ false ));
852883 }
853884
854885 Tables.emplace_back (std::move (Table));
0 commit comments