@@ -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);
@@ -426,16 +428,25 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
426
428
OS << " return nullptr;\n\n " ;
427
429
}
428
430
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 = {" ;
433
442
}
434
- OS << " };\n " ;
435
- OS << " KeyType Key = {" ;
443
+
436
444
ListSeparator LS;
437
445
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 ;
439
450
if (isa<StringRecTy>(Field.RecType )) {
440
451
OS << " .upper()" ;
441
452
if (IsPrimary)
@@ -445,12 +456,21 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
445
456
" case-insensitive comparison of field '" +
446
457
Field.Name + " '" );
447
458
}
459
+ if (ShouldReturnRange)
460
+ OS << " ;\n " ;
448
461
}
449
- OS << " };\n " ;
462
+ if (!ShouldReturnRange)
463
+ OS << " };\n " ;
450
464
451
465
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
+ }
454
474
455
475
for (const auto &Field : Index.Fields ) {
456
476
if (isa<StringRecTy>(Field.RecType )) {
@@ -478,25 +498,33 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
478
498
OS << " return false;\n " ;
479
499
OS << " });\n\n " ;
480
500
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
+ }
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) << " "
@@ -510,11 +538,12 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
510
538
511
539
// Emit the declarations for the functions that will perform lookup.
512
540
if (Table.PrimaryKey ) {
513
- emitLookupDeclaration (Table, *Table.PrimaryKey , OS);
541
+ auto &Index = Table.PrimaryKey ;
542
+ emitLookupDeclaration (Table, *Index, OS);
514
543
OS << " ;\n " ;
515
544
}
516
545
for (const auto &Index : Table.Indices ) {
517
- emitLookupDeclaration (Table, *Index, OS);
546
+ emitLookupDeclaration (Table, *Index, OS);
518
547
OS << " ;\n " ;
519
548
}
520
549
@@ -540,10 +569,12 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
540
569
541
570
// Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542
571
// 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
+ }
545
576
for (const auto &Index : Table.Indices )
546
- emitLookupFunction (Table, *Index, false , OS);
577
+ emitLookupFunction (Table, *Index, /* IsPrimary= */ false , OS);
547
578
548
579
OS << " #endif\n\n " ;
549
580
}
@@ -569,11 +600,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569
600
570
601
std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571
602
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 ) {
573
604
auto Index = std::make_unique<SearchIndex>();
574
605
Index->Name = std::string (Name);
575
606
Index->Loc = KeyRecVal->getLoc ();
576
607
Index->EarlyOut = EarlyOut;
608
+ Index->ReturnRange = ReturnRange;
577
609
578
610
for (const auto &FieldName : Key) {
579
611
const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +801,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769
801
parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770
802
TableRec->getValueAsString (" PrimaryKeyName" ),
771
803
TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772
- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
804
+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
805
+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773
806
774
807
llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775
808
return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -793,7 +826,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
793
826
Table.Indices .push_back (
794
827
parseSearchIndex (Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
795
828
IndexRec->getValueAsListOfStrings (" Key" ),
796
- IndexRec->getValueAsBit (" EarlyOut" )));
829
+ IndexRec->getValueAsBit (" EarlyOut" ),
830
+ IndexRec->getValueAsBit (" ReturnRange" )));
797
831
}
798
832
799
833
// Translate legacy tables.
@@ -848,7 +882,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
848
882
std::string Name =
849
883
(Twine (" lookup" ) + Table->CppTypeName + " By" + Field).str ();
850
884
Table->Indices .push_back (parseSearchIndex (*Table, Class->getValue (Field),
851
- Name, {Field}, false ));
885
+ Name, {Field}, false , false ));
852
886
}
853
887
854
888
Tables.emplace_back (std::move (Table));
0 commit comments