@@ -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);
@@ -328,8 +330,9 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
328
330
ArrayRef<Record *> IndexRows;
329
331
StringRef IndexTypeName;
330
332
StringRef IndexName;
333
+ bool ShouldReturnRange = Index.ReturnRange ;
331
334
332
- if (IsPrimary) {
335
+ if (IsPrimary || ShouldReturnRange ) {
333
336
IndexTypeName = Table.CppTypeName ;
334
337
IndexName = Table.Name ;
335
338
IndexRows = Table.Entries ;
@@ -426,31 +429,55 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
426
429
OS << " return nullptr;\n\n " ;
427
430
}
428
431
429
- OS << " struct KeyType {\n " ;
430
- for (const auto &Field : Index.Fields ) {
431
- OS << " " << searchableFieldType (Table, Index, Field, TypeInTempStruct)
432
- << " " << Field.Name << " ;\n " ;
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 ;
439
- if (isa<StringRecTy>(Field.RecType )) {
440
- OS << " .upper()" ;
441
- if (IsPrimary)
442
- PrintFatalError (Index.Loc ,
443
- Twine (" In table '" ) + Table.Name +
444
- " ', use a secondary lookup method for "
445
- " case-insensitive comparison of field '" +
446
- Field.Name + " '" );
446
+ if (ShouldReturnRange) {
447
+ OS << " Key." << Field.Name << " = " << Field.Name ;
448
+ if (isa<StringRecTy>(Field.RecType ))
449
+ OS << " .data()" ;
450
+ OS << " ;\n " ;
451
+ } else {
452
+ OS << LS << Field.Name ;
453
+ if (isa<StringRecTy>(Field.RecType )) {
454
+ OS << " .upper()" ;
455
+ if (IsPrimary)
456
+ PrintFatalError (Index.Loc ,
457
+ Twine (" In table '" ) + Table.Name +
458
+ " ', use a secondary lookup method for "
459
+ " case-insensitive comparison of field '" +
460
+ Field.Name + " '" );
461
+ }
447
462
}
448
463
}
449
- OS << " };\n " ;
450
464
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 " ;
465
+ if (!ShouldReturnRange)
466
+ OS << " };\n " ;
467
+
468
+ OS << " auto Table = ArrayRef(" << IndexName;
469
+ if (ShouldReturnRange) {
470
+ if (!IsPrimary)
471
+ OS << " for" << Index.Name ;
472
+ OS << " );\n " ;
473
+ OS << " auto It = std::equal_range(Table.begin(), Table.end(), Key,\n " ;
474
+ OS << " [](const " << IndexTypeName << " &LHS, const " << IndexTypeName
475
+ << " &RHS) {\n " ;
476
+ } else {
477
+ OS << " );\n " ;
478
+ OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Key,\n " ;
479
+ OS << " [](const " << IndexTypeName << " &LHS, const KeyType &RHS) {\n " ;
480
+ }
454
481
455
482
for (const auto &Field : Index.Fields ) {
456
483
if (isa<StringRecTy>(Field.RecType )) {
@@ -478,25 +505,33 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
478
505
OS << " return false;\n " ;
479
506
OS << " });\n\n " ;
480
507
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 " ;
508
+ if (!ShouldReturnRange) {
509
+ OS << " if (Idx == Table.end() " ;
510
+ for (const auto &Field : Index.Fields )
511
+ OS << " ||\n Key." << Field.Name << " != Idx->" << Field.Name ;
512
+ }
486
513
487
- if (IsPrimary)
514
+ if (ShouldReturnRange)
515
+ OS << " return llvm::make_range(It.first, It.second);\n " ;
516
+ else if (IsPrimary) {
517
+ OS << " )\n return nullptr;\n\n " ;
488
518
OS << " return &*Idx;\n " ;
489
- else
519
+ } else {
520
+ OS << " )\n return nullptr;\n\n " ;
490
521
OS << " return &" << Table.Name << " [Idx->_index];\n " ;
522
+ }
491
523
492
524
OS << " }\n " ;
493
525
}
494
526
495
527
void SearchableTableEmitter::emitLookupDeclaration (const GenericTable &Table,
496
528
const SearchIndex &Index,
497
529
raw_ostream &OS) {
498
- OS << " const " << Table.CppTypeName << " *" << Index.Name << " (" ;
499
-
530
+ if (Index.ReturnRange )
531
+ OS << " llvm::iterator_range<const " << Table.CppTypeName << " *>\n " ;
532
+ else
533
+ OS << " const " << Table.CppTypeName << " *" ;
534
+ OS << Index.Name << " (" ;
500
535
ListSeparator LS;
501
536
for (const auto &Field : Index.Fields )
502
537
OS << LS << searchableFieldType (Table, Index, Field, TypeInArgument) << " "
@@ -538,12 +573,41 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
538
573
}
539
574
OS << " };\n " ;
540
575
576
+ // Emit Table for all those indices which will return a range instead of a
577
+ // single record
578
+ for (const auto &Index : Table.Indices ) {
579
+ if (Index->ReturnRange ) {
580
+ std::vector<Record *> Entries;
581
+ Entries.reserve (Table.Entries .size ());
582
+ for (unsigned i = 0 ; i < Table.Entries .size (); ++i)
583
+ Entries.emplace_back (Table.Entries [i]);
584
+
585
+ llvm::stable_sort (Entries, [&](Record *LHS, Record *RHS) {
586
+ return compareBy (LHS, RHS, *Index);
587
+ });
588
+
589
+ OS << " constexpr " << Table.CppTypeName << " " << Table.Name << " for"
590
+ << Index->Name << " [] = {\n " ;
591
+ for (const auto &Entry : Entries) {
592
+ OS << " { " ;
593
+ ListSeparator LS;
594
+ for (const auto &Field : Table.Fields )
595
+ OS << LS
596
+ << primaryRepresentation (Table.Locs [0 ], Field,
597
+ Entry->getValueInit (Field.Name ));
598
+
599
+ OS << " },\n " ;
600
+ }
601
+ OS << " };\n " ;
602
+ }
603
+ }
604
+
541
605
// Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
542
606
// search can be performed by "Thing".
543
607
if (Table.PrimaryKey )
544
- emitLookupFunction (Table, *Table.PrimaryKey , true , OS);
608
+ emitLookupFunction (Table, *Table.PrimaryKey , /* IsPrimary= */ true , OS);
545
609
for (const auto &Index : Table.Indices )
546
- emitLookupFunction (Table, *Index, false , OS);
610
+ emitLookupFunction (Table, *Index, /* IsPrimary= */ false , OS);
547
611
548
612
OS << " #endif\n\n " ;
549
613
}
@@ -569,11 +633,12 @@ bool SearchableTableEmitter::parseFieldType(GenericField &Field, Init *TypeOf) {
569
633
570
634
std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex (
571
635
GenericTable &Table, const RecordVal *KeyRecVal, StringRef Name,
572
- const std::vector<StringRef> &Key, bool EarlyOut) {
636
+ const std::vector<StringRef> &Key, bool EarlyOut, bool ReturnRange ) {
573
637
auto Index = std::make_unique<SearchIndex>();
574
638
Index->Name = std::string (Name);
575
639
Index->Loc = KeyRecVal->getLoc ();
576
640
Index->EarlyOut = EarlyOut;
641
+ Index->ReturnRange = ReturnRange;
577
642
578
643
for (const auto &FieldName : Key) {
579
644
const GenericField *Field = Table.getFieldByName (FieldName);
@@ -769,7 +834,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
769
834
parseSearchIndex (*Table, TableRec->getValue (" PrimaryKey" ),
770
835
TableRec->getValueAsString (" PrimaryKeyName" ),
771
836
TableRec->getValueAsListOfStrings (" PrimaryKey" ),
772
- TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ));
837
+ TableRec->getValueAsBit (" PrimaryKeyEarlyOut" ),
838
+ TableRec->getValueAsBit (" PrimaryKeyReturnRange" ));
773
839
774
840
llvm::stable_sort (Table->Entries , [&](Record *LHS, Record *RHS) {
775
841
return compareBy (LHS, RHS, *Table->PrimaryKey );
@@ -793,7 +859,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
793
859
Table.Indices .push_back (
794
860
parseSearchIndex (Table, IndexRec->getValue (" Key" ), IndexRec->getName (),
795
861
IndexRec->getValueAsListOfStrings (" Key" ),
796
- IndexRec->getValueAsBit (" EarlyOut" )));
862
+ IndexRec->getValueAsBit (" EarlyOut" ),
863
+ IndexRec->getValueAsBit (" ReturnRange" )));
797
864
}
798
865
799
866
// Translate legacy tables.
@@ -848,7 +915,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
848
915
std::string Name =
849
916
(Twine (" lookup" ) + Table->CppTypeName + " By" + Field).str ();
850
917
Table->Indices .push_back (parseSearchIndex (*Table, Class->getValue (Field),
851
- Name, {Field}, false ));
918
+ Name, {Field}, false , false ));
852
919
}
853
920
854
921
Tables.emplace_back (std::move (Table));
0 commit comments