@@ -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);
@@ -320,6 +322,12 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
320
322
const SearchIndex &Index,
321
323
bool IsPrimary,
322
324
raw_ostream &OS) {
325
+ bool ShouldReturnRange = Index.ReturnRange ;
326
+ if (ShouldReturnRange && !IsPrimary)
327
+ PrintFatalError (Index.Loc ,
328
+ " Emitting different signature for returning a range of "
329
+ " results is only supported for Primary Key." );
330
+
323
331
OS << " \n " ;
324
332
emitLookupDeclaration (Table, Index, OS);
325
333
OS << " {\n " ;
@@ -448,55 +456,80 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
448
456
}
449
457
OS << " };\n " ;
450
458
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 " ;
459
+ OS << " struct Comp { \n " ;
460
+ OS << " bool operator()(const " << IndexTypeName
461
+ << " &LHS, const KeyType &RHS) const {\n " ;
454
462
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 " ;
463
+ auto emitComparator = [&]() {
464
+ for (const auto &Field : Index.Fields ) {
465
+ if (isa<StringRecTy>(Field.RecType )) {
466
+ OS << " int Cmp" << Field.Name << " = StringRef(LHS." << Field.Name
467
+ << " ).compare(RHS." << Field.Name << " );\n " ;
468
+ OS << " if (Cmp" << Field.Name << " < 0) return true;\n " ;
469
+ OS << " if (Cmp" << Field.Name << " > 0) return false;\n " ;
470
+ } else if (Field.Enum ) {
471
+ // Explicitly cast to unsigned, because the signedness of enums is
472
+ // compiler-dependent.
473
+ OS << " if ((unsigned)LHS." << Field.Name << " < (unsigned)RHS."
474
+ << Field.Name << " )\n " ;
475
+ OS << " return true;\n " ;
476
+ OS << " if ((unsigned)LHS." << Field.Name << " > (unsigned)RHS."
477
+ << Field.Name << " )\n " ;
478
+ OS << " return false;\n " ;
479
+ } else {
480
+ OS << " if (LHS." << Field.Name << " < RHS." << Field.Name
481
+ << " )\n " ;
482
+ OS << " return true;\n " ;
483
+ OS << " if (LHS." << Field.Name << " > RHS." << Field.Name
484
+ << " )\n " ;
485
+ OS << " return false;\n " ;
486
+ }
475
487
}
488
+ OS << " return false;\n " ;
489
+ OS << " }\n " ;
490
+ };
491
+ emitComparator ();
492
+ if (ShouldReturnRange) {
493
+ OS << " bool operator()(const KeyType &LHS, const " << IndexTypeName
494
+ << " &RHS) const {\n " ;
495
+ emitComparator ();
476
496
}
477
497
478
- OS << " return false;\n " ;
479
- OS << " });\n\n " ;
480
-
481
- OS << " if (Idx == Table.end()" ;
498
+ OS << " };\n " ;
499
+ OS << " auto Table = ArrayRef(" << IndexName << " );\n " ;
500
+ if (ShouldReturnRange)
501
+ OS << " auto It = std::equal_range(Table.begin(), Table.end(), Key, " ;
502
+ else
503
+ OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, " ;
504
+ OS << " Comp());\n " ;
482
505
483
- for (const auto &Field : Index.Fields )
484
- OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name ;
485
- OS << " )\n return nullptr;\n " ;
506
+ if (!ShouldReturnRange) {
507
+ OS << " if (Idx == Table.end()" ;
508
+ for (const auto &Field : Index.Fields )
509
+ OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name ;
510
+ }
486
511
487
- if (IsPrimary)
512
+ if (ShouldReturnRange)
513
+ OS << " return llvm::make_range(It.first, It.second);\n " ;
514
+ else if (IsPrimary) {
515
+ OS << " )\n return nullptr;\n\n " ;
488
516
OS << " return &*Idx;\n " ;
489
- else
517
+ } else {
518
+ OS << " )\n return nullptr;\n\n " ;
490
519
OS << " return &" << Table.Name << " [Idx->_index];\n " ;
520
+ }
491
521
492
522
OS << " }\n " ;
493
523
}
494
524
495
525
void SearchableTableEmitter::emitLookupDeclaration (const GenericTable &Table,
496
526
const SearchIndex &Index,
497
527
raw_ostream &OS) {
498
- OS << " const " << Table.CppTypeName << " *" << Index.Name << " (" ;
499
-
528
+ if (Index.ReturnRange )
529
+ OS << " llvm::iterator_range<const " << Table.CppTypeName << " *> " ;
530
+ else
531
+ OS << " const " << Table.CppTypeName << " *" ;
532
+ OS << Index.Name << " (" ;
500
533
ListSeparator LS;
501
534
for (const auto &Field : Index.Fields )
502
535
OS << LS << searchableFieldType (Table, Index, Field, TypeInArgument) << " "
@@ -541,9 +574,9 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
541
574
// Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542
575
// search can be performed by "Thing".
543
576
if (Table.PrimaryKey )
544
- emitLookupFunction (Table, *Table.PrimaryKey , true , OS);
577
+ emitLookupFunction (Table, *Table.PrimaryKey , /* IsPrimary= */ true , OS);
545
578
for (const auto &Index : Table.Indices )
546
- emitLookupFunction (Table, *Index, false , OS);
579
+ emitLookupFunction (Table, *Index, /* IsPrimary= */ false , OS);
547
580
548
581
OS << " #endif\n\n " ;
549
582
}
@@ -569,11 +602,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569
602
570
603
std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571
604
GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name,
572
- const std::vector<StringRef> &Key, bool EarlyOut) {
605
+ const std::vector<StringRef> &Key, bool EarlyOut, bool ReturnRange ) {
573
606
auto Index = std::make_unique<SearchIndex>();
574
607
Index->Name = std::string (Name);
575
608
Index->Loc = KeyRecVal->getLoc ();
576
609
Index->EarlyOut = EarlyOut;
610
+ Index->ReturnRange = ReturnRange;
577
611
578
612
for (const auto &FieldName : Key) {
579
613
const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +803,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769
803
parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770
804
TableRec->getValueAsString (" PrimaryKeyName" ),
771
805
TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772
- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
806
+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
807
+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773
808
774
809
llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775
810
return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -793,7 +828,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
793
828
Table.Indices .push_back (
794
829
parseSearchIndex (Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
795
830
IndexRec->getValueAsListOfStrings (" Key" ),
796
- IndexRec->getValueAsBit (" EarlyOut" )));
831
+ IndexRec->getValueAsBit (" EarlyOut" ),
832
+ IndexRec->getValueAsBit (" ReturnRange" )));
797
833
}
798
834
799
835
// Translate legacy tables.
@@ -848,7 +884,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
848
884
std::string Name =
849
885
(Twine (" lookup" ) + Table->CppTypeName + " By" + Field).str ();
850
886
Table->Indices .push_back (parseSearchIndex (*Table, Class->getValue (Field),
851
- Name, {Field}, false ));
887
+ Name, {Field}, false , false ));
852
888
}
853
889
854
890
Tables.emplace_back (std::move (Table));
0 commit comments