@@ -68,6 +68,7 @@ struct SearchIndex {
68
68
SMLoc Loc; // Source location of PrimaryKey or Key field definition.
69
69
SmallVector<GenericField, 1 > Fields;
70
70
bool EarlyOut = false ;
71
+ bool ReturnRange = false ;
71
72
};
72
73
73
74
struct GenericTable {
@@ -198,7 +199,8 @@ class SearchableTableEmitter {
198
199
bool parseFieldType (GenericField &Field, Init *II);
199
200
std::unique_ptr<SearchIndex>
200
201
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);
202
204
void collectEnumEntries (GenericEnum &Enum, StringRef NameField,
203
205
StringRef ValueField,
204
206
const std::vector<Record *> &Items);
@@ -448,55 +450,81 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
448
450
}
449
451
OS << " };\n " ;
450
452
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 " ;
454
456
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
+ }
475
481
}
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 ();
476
491
}
477
492
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 " ;
482
500
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
+ }
486
506
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 " ;
488
511
OS << " return &*Idx;\n " ;
489
- else
512
+ } else {
513
+ OS << " )\n return nullptr;\n\n " ;
490
514
OS << " return &" << Table.Name << " [Idx->_index];\n " ;
515
+ }
491
516
492
517
OS << " }\n " ;
493
518
}
494
519
495
520
void SearchableTableEmitter::emitLookupDeclaration (const GenericTable &Table,
496
521
const SearchIndex &Index,
497
522
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 << " (" ;
500
528
ListSeparator LS;
501
529
for (const auto &Field : Index.Fields )
502
530
OS << LS << searchableFieldType (Table, Index, Field, TypeInArgument) << " "
@@ -541,9 +569,9 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
541
569
// Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542
570
// search can be performed by "Thing".
543
571
if (Table.PrimaryKey )
544
- emitLookupFunction (Table, *Table.PrimaryKey , true , OS);
572
+ emitLookupFunction (Table, *Table.PrimaryKey , /* IsPrimary= */ true , OS);
545
573
for (const auto &Index : Table.Indices )
546
- emitLookupFunction (Table, *Index, false , OS);
574
+ emitLookupFunction (Table, *Index, /* IsPrimary= */ false , OS);
547
575
548
576
OS << " #endif\n\n " ;
549
577
}
@@ -569,11 +597,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569
597
570
598
std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571
599
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 ) {
573
601
auto Index = std::make_unique<SearchIndex>();
574
602
Index->Name = std::string (Name);
575
603
Index->Loc = KeyRecVal->getLoc ();
576
604
Index->EarlyOut = EarlyOut;
605
+ Index->ReturnRange = ReturnRange;
577
606
578
607
for (const auto &FieldName : Key) {
579
608
const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +798,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769
798
parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770
799
TableRec->getValueAsString (" PrimaryKeyName" ),
771
800
TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772
- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
801
+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
802
+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773
803
774
804
llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775
805
return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -790,10 +820,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
790
820
TableRec->getName ());
791
821
792
822
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 ));
797
827
}
798
828
799
829
// Translate legacy tables.
@@ -847,8 +877,9 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
847
877
Class->getValueAsListOfStrings (" SearchableFields" )) {
848
878
std::string Name =
849
879
(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 ));
852
883
}
853
884
854
885
Tables.emplace_back (std::move (Table));
0 commit comments