@@ -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 {
@@ -190,15 +191,18 @@ class SearchableTableEmitter {
190
191
void emitGenericTable (const GenericTable &Table, raw_ostream &OS);
191
192
void emitGenericEnum (const GenericEnum &Enum, raw_ostream &OS);
192
193
void emitLookupDeclaration (const GenericTable &Table,
193
- const SearchIndex &Index, raw_ostream &OS);
194
+ const SearchIndex &Index, bool ShouldReturnRange,
195
+ raw_ostream &OS);
194
196
void emitLookupFunction (const GenericTable &Table, const SearchIndex &Index,
195
- bool IsPrimary, raw_ostream &OS);
197
+ bool IsPrimary, bool ShouldReturnRange,
198
+ raw_ostream &OS);
196
199
void emitIfdef (StringRef Guard, raw_ostream &OS);
197
200
198
201
bool parseFieldType (GenericField &Field, Init *II);
199
202
std::unique_ptr<SearchIndex>
200
203
parseSearchIndex (GenericTable &Table, const RecordVal *RecVal, StringRef Name,
201
- const std::vector<StringRef> &Key, bool EarlyOut);
204
+ const std::vector<StringRef> &Key, bool EarlyOut,
205
+ bool ReturnRange);
202
206
void collectEnumEntries (GenericEnum &Enum, StringRef NameField,
203
207
StringRef ValueField,
204
208
const std::vector<Record *> &Items);
@@ -319,9 +323,10 @@ void SearchableTableEmitter::emitGenericEnum(const GenericEnum &Enum,
319
323
void SearchableTableEmitter::emitLookupFunction (const GenericTable &Table,
320
324
const SearchIndex &Index,
321
325
bool IsPrimary,
326
+ bool ShouldReturnRange,
322
327
raw_ostream &OS) {
323
328
OS << " \n " ;
324
- emitLookupDeclaration (Table, Index, OS);
329
+ emitLookupDeclaration (Table, Index, ShouldReturnRange, OS);
325
330
OS << " {\n " ;
326
331
327
332
std::vector<Record *> IndexRowsStorage;
@@ -426,16 +431,24 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
426
431
OS << " return nullptr;\n\n " ;
427
432
}
428
433
429
- OS << " struct KeyType {\n " ;
430
- for (const auto &Field : Index.Fields ) {
431
- OS << " " << searchableFieldType (Table, Index, Field, TypeInTempStruct)
432
- << " " << Field.Name << " ;\n " ;
434
+ if (ShouldReturnRange)
435
+ OS << " " << IndexTypeName << " Key;\n " ;
436
+ else {
437
+ OS << " struct KeyType {\n " ;
438
+ for (const auto &Field : Index.Fields ) {
439
+ OS << " " << searchableFieldType (Table, Index, Field, TypeInTempStruct)
440
+ << " " << Field.Name << " ;\n " ;
441
+ }
442
+ OS << " };\n " ;
443
+ OS << " KeyType Key = {" ;
433
444
}
434
- OS << " };\n " ;
435
- OS << " KeyType Key = {" ;
445
+
436
446
ListSeparator LS;
437
447
for (const auto &Field : Index.Fields ) {
438
- OS << LS << Field.Name ;
448
+ if (ShouldReturnRange)
449
+ OS << " Key." << Field.Name << " = " << Field.Name ;
450
+ else
451
+ OS << LS << Field.Name ;
439
452
if (isa<StringRecTy>(Field.RecType )) {
440
453
OS << " .upper()" ;
441
454
if (IsPrimary)
@@ -445,12 +458,21 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
445
458
" case-insensitive comparison of field '" +
446
459
Field.Name + " '" );
447
460
}
461
+ if (ShouldReturnRange)
462
+ OS << " ;\n " ;
448
463
}
449
- OS << " };\n " ;
464
+ if (!ShouldReturnRange)
465
+ OS << " };\n " ;
450
466
451
467
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 " ;
468
+ if (ShouldReturnRange) {
469
+ OS << " auto It = std::equal_range(Table.begin(), Table.end(), Key,\n " ;
470
+ OS << " [](const " << IndexTypeName << " &LHS, const " << IndexTypeName
471
+ << " &RHS) {\n " ;
472
+ } else {
473
+ OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n " ;
474
+ OS << " [](const " << IndexTypeName << " &LHS, const KeyType &RHS) {\n " ;
475
+ }
454
476
455
477
for (const auto &Field : Index.Fields ) {
456
478
if (isa<StringRecTy>(Field.RecType )) {
@@ -478,25 +500,34 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
478
500
OS << " return false;\n " ;
479
501
OS << " });\n\n " ;
480
502
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 " ;
503
+ if (!ShouldReturnRange) {
504
+ OS << " if (Idx == Table.end() " ;
505
+ for (const auto &Field : Index.Fields )
506
+ OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name ;
507
+ }
486
508
487
- if (IsPrimary)
509
+ if (ShouldReturnRange)
510
+ OS << " return llvm::make_range(It.first, It.second);\n " ;
511
+ else if (IsPrimary) {
512
+ OS << " )\n return nullptr;\n\n " ;
488
513
OS << " return &*Idx;\n " ;
489
- else
514
+ } else {
515
+ OS << " )\n return nullptr;\n\n " ;
490
516
OS << " return &" << Table.Name << " [Idx->_index];\n " ;
517
+ }
491
518
492
519
OS << " }\n " ;
493
520
}
494
521
495
522
void SearchableTableEmitter::emitLookupDeclaration (const GenericTable &Table,
496
523
const SearchIndex &Index,
524
+ bool ShouldReturnRange,
497
525
raw_ostream &OS) {
498
- OS << " const " << Table.CppTypeName << " *" << Index.Name << " (" ;
499
-
526
+ if (ShouldReturnRange)
527
+ OS << " llvm::iterator_range<const " << Table.CppTypeName << " *>" ;
528
+ else
529
+ OS << " const " << Table.CppTypeName << " *" ;
530
+ OS << Index.Name << " (" ;
500
531
ListSeparator LS;
501
532
for (const auto &Field : Index.Fields )
502
533
OS << LS << searchableFieldType (Table, Index, Field, TypeInArgument) << " "
@@ -510,11 +541,12 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
510
541
511
542
// Emit the declarations for the functions that will perform lookup.
512
543
if (Table.PrimaryKey ) {
513
- emitLookupDeclaration (Table, *Table.PrimaryKey , OS);
544
+ auto &Index = Table.PrimaryKey ;
545
+ emitLookupDeclaration (Table, *Index, Index->ReturnRange , OS);
514
546
OS << " ;\n " ;
515
547
}
516
548
for (const auto &Index : Table.Indices ) {
517
- emitLookupDeclaration (Table, *Index, OS);
549
+ emitLookupDeclaration (Table, *Index, Index-> ReturnRange , OS);
518
550
OS << " ;\n " ;
519
551
}
520
552
@@ -540,10 +572,14 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
540
572
541
573
// Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542
574
// search can be performed by "Thing".
543
- if (Table.PrimaryKey )
544
- emitLookupFunction (Table, *Table.PrimaryKey , true , OS);
575
+ if (Table.PrimaryKey ) {
576
+ auto &Index = Table.PrimaryKey ;
577
+ emitLookupFunction (Table, *Index, /* IsPrimary=*/ true , Index->ReturnRange ,
578
+ OS);
579
+ }
545
580
for (const auto &Index : Table.Indices )
546
- emitLookupFunction (Table, *Index, false , OS);
581
+ emitLookupFunction (Table, *Index, /* IsPrimary=*/ false , Index->ReturnRange ,
582
+ OS);
547
583
548
584
OS << " #endif\n\n " ;
549
585
}
@@ -569,11 +605,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569
605
570
606
std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571
607
GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name,
572
- const std::vector<StringRef> &Key, bool EarlyOut) {
608
+ const std::vector<StringRef> &Key, bool EarlyOut, bool ReturnRange ) {
573
609
auto Index = std::make_unique<SearchIndex>();
574
610
Index->Name = std::string (Name);
575
611
Index->Loc = KeyRecVal->getLoc ();
576
612
Index->EarlyOut = EarlyOut;
613
+ Index->ReturnRange = ReturnRange;
577
614
578
615
for (const auto &FieldName : Key) {
579
616
const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +806,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769
806
parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770
807
TableRec->getValueAsString (" PrimaryKeyName" ),
771
808
TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772
- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
809
+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
810
+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773
811
774
812
llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775
813
return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -793,7 +831,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
793
831
Table.Indices .push_back (
794
832
parseSearchIndex (Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
795
833
IndexRec->getValueAsListOfStrings (" Key" ),
796
- IndexRec->getValueAsBit (" EarlyOut" )));
834
+ IndexRec->getValueAsBit (" EarlyOut" ),
835
+ IndexRec->getValueAsBit (" ReturnRange" )));
797
836
}
798
837
799
838
// Translate legacy tables.
@@ -848,7 +887,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
848
887
std::string Name =
849
888
(Twine (" lookup" ) + Table->CppTypeName + " By" + Field).str ();
850
889
Table->Indices .push_back (parseSearchIndex (*Table, Class->getValue (Field),
851
- Name, {Field}, false ));
890
+ Name, {Field}, false , false ));
852
891
}
853
892
854
893
Tables.emplace_back (std::move (Table));
0 commit comments