Skip to content

Commit f565dd3

Browse files
committed
[Serialization] Introduce OnDiskHashTable for specializations
Following up for #83108 This follows the suggestion literally from #76774 (comment) which introduces OnDiskHashTable for specializations based on D41416. Note that I didn't polish this patch to reduce the diff from D41416 to it easier to review. I'll make the polishing patch later. So that we can focus what we're doing in this patch and focus on the style in the next patch.
1 parent 0d8de51 commit f565dd3

15 files changed

+856
-13
lines changed

clang/include/clang/AST/ExternalASTSource.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
152152
virtual bool
153153
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
154154

155+
/// Load all the external specializations for the Decl \param D if \param
156+
/// OnlyPartial is false. Otherwise, load all the external **partial**
157+
/// specializations for the \param D.
158+
virtual void LoadExternalSpecializations(const Decl *D, bool OnlyPartial);
159+
160+
/// Load all the specializations for the Decl \param D with the same template
161+
/// args specified by \param TemplateArgs.
162+
virtual void
163+
LoadExternalSpecializations(const Decl *D,
164+
ArrayRef<TemplateArgument> TemplateArgs);
165+
155166
/// Ensures that the table of all visible declarations inside this
156167
/// context is up to date.
157168
///

clang/include/clang/Sema/MultiplexExternalSemaSource.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
9797
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
9898
DeclarationName Name) override;
9999

100+
void LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
101+
102+
void
103+
LoadExternalSpecializations(const Decl *D,
104+
ArrayRef<TemplateArgument> TemplateArgs) override;
105+
100106
/// Ensures that the table of all visible declarations inside this
101107
/// context is up to date.
102108
void completeVisibleDeclsMap(const DeclContext *DC) override;

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,9 @@ enum ASTRecordTypes {
734734
/// Record code for Sema's vector of functions/blocks with effects to
735735
/// be verified.
736736
DECLS_WITH_EFFECTS_TO_VERIFY = 72,
737+
738+
/// Record code for updated specialization
739+
UPDATE_SPECIALIZATION = 73,
737740
};
738741

739742
/// Record types used within a source manager block.
@@ -1500,6 +1503,9 @@ enum DeclCode {
15001503
/// A HLSLBufferDecl record.
15011504
DECL_HLSL_BUFFER,
15021505

1506+
// A decls specilization record.
1507+
DECL_SPECIALIZATIONS,
1508+
15031509
/// An ImplicitConceptSpecializationDecl record.
15041510
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
15051511

clang/include/clang/Serialization/ASTReader.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ class ASTIdentifierLookupTrait;
353353
/// The on-disk hash table(s) used for DeclContext name lookup.
354354
struct DeclContextLookupTable;
355355

356+
/// The on-disk hash table(s) used for specialization decls.
357+
struct LazySpecializationInfoLookupTable;
358+
356359
} // namespace reader
357360

358361
} // namespace serialization
@@ -631,20 +634,29 @@ class ASTReader
631634
llvm::DenseMap<const DeclContext *,
632635
serialization::reader::DeclContextLookupTable> Lookups;
633636

637+
/// Map from decls to specialized decls.
638+
llvm::DenseMap<const Decl *,
639+
serialization::reader::LazySpecializationInfoLookupTable>
640+
SpecializationsLookups;
641+
634642
// Updates for visible decls can occur for other contexts than just the
635643
// TU, and when we read those update records, the actual context may not
636644
// be available yet, so have this pending map using the ID as a key. It
637-
// will be realized when the context is actually loaded.
638-
struct PendingVisibleUpdate {
645+
// will be realized when the data is actually loaded.
646+
struct UpdateData {
639647
ModuleFile *Mod;
640648
const unsigned char *Data;
641649
};
642-
using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>;
650+
using DeclContextVisibleUpdates = SmallVector<UpdateData, 1>;
643651

644652
/// Updates to the visible declarations of declaration contexts that
645653
/// haven't been loaded yet.
646654
llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates;
647655

656+
using SpecializationsUpdate = SmallVector<UpdateData, 1>;
657+
llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>
658+
PendingSpecializationsUpdates;
659+
648660
/// The set of C++ or Objective-C classes that have forward
649661
/// declarations that have not yet been linked to their definitions.
650662
llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
@@ -677,6 +689,11 @@ class ASTReader
677689
llvm::BitstreamCursor &Cursor,
678690
uint64_t Offset, GlobalDeclID ID);
679691

692+
bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor,
693+
uint64_t Offset, Decl *D);
694+
void AddSpecializations(const Decl *D, const unsigned char *Data,
695+
ModuleFile &M);
696+
680697
/// A vector containing identifiers that have already been
681698
/// loaded.
682699
///
@@ -1379,6 +1396,11 @@ class ASTReader
13791396
const serialization::reader::DeclContextLookupTable *
13801397
getLoadedLookupTables(DeclContext *Primary) const;
13811398

1399+
/// Get the loaded specializations lookup tables for \p D,
1400+
/// if any.
1401+
serialization::reader::LazySpecializationInfoLookupTable *
1402+
getLoadedSpecializationsLookupTables(const Decl *D);
1403+
13821404
private:
13831405
struct ImportedModule {
13841406
ModuleFile *Mod;
@@ -2036,6 +2058,12 @@ class ASTReader
20362058
unsigned BlockID,
20372059
uint64_t *StartOfBlockOffset = nullptr);
20382060

2061+
void LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
2062+
2063+
void
2064+
LoadExternalSpecializations(const Decl *D,
2065+
ArrayRef<TemplateArgument> TemplateArgs) override;
2066+
20392067
/// Finds all the visible declarations with a given name.
20402068
/// The current implementation of this method just loads the entire
20412069
/// lookup table as unmaterialized references.

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,12 @@ class ASTWriter : public ASTDeserializationListener,
426426
/// Only meaningful for reduced BMI.
427427
DeclUpdateMap DeclUpdatesFromGMF;
428428

429+
/// Mapping from decl templates and its new specialization in the
430+
/// current TU.
431+
using SpecializationUpdateMap =
432+
llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>;
433+
SpecializationUpdateMap SpecializationsUpdates;
434+
429435
using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
430436

431437
/// Map of first declarations from a chained PCH that point to the
@@ -577,6 +583,12 @@ class ASTWriter : public ASTDeserializationListener,
577583

578584
bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
579585

586+
void GenerateSpecializationInfoLookupTable(
587+
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
588+
llvm::SmallVectorImpl<char> &LookupTable);
589+
uint64_t WriteSpecializationInfoLookupTable(
590+
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations);
591+
580592
void GenerateNameLookupTable(const DeclContext *DC,
581593
llvm::SmallVectorImpl<char> &LookupTable);
582594
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context,
@@ -592,6 +604,7 @@ class ASTWriter : public ASTDeserializationListener,
592604
void WriteDeclAndTypes(ASTContext &Context);
593605
void PrepareWritingSpecialDecls(Sema &SemaRef);
594606
void WriteSpecialDeclRecords(Sema &SemaRef);
607+
void WriteSpecializationsUpdates();
595608
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
596609
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
597610
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
@@ -619,6 +632,8 @@ class ASTWriter : public ASTDeserializationListener,
619632
unsigned DeclEnumAbbrev = 0;
620633
unsigned DeclObjCIvarAbbrev = 0;
621634
unsigned DeclCXXMethodAbbrev = 0;
635+
unsigned DeclSpecializationsAbbrev = 0;
636+
622637
unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0;
623638
unsigned DeclTemplateCXXMethodAbbrev = 0;
624639
unsigned DeclMemberSpecializedCXXMethodAbbrev = 0;

clang/lib/AST/DeclTemplate.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,14 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
344344

345345
void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
346346
bool OnlyPartial /*=false*/) const {
347+
auto *ExternalSource = getASTContext().getExternalSource();
348+
if (!ExternalSource)
349+
return;
350+
351+
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
352+
OnlyPartial);
353+
return;
354+
347355
// Grab the most recent declaration to ensure we've loaded any lazy
348356
// redeclarations of this template.
349357
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
@@ -363,6 +371,8 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
363371

364372
Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
365373
LazySpecializationInfo &LazySpecInfo) const {
374+
llvm_unreachable("We don't use LazySpecializationInfo any more");
375+
366376
GlobalDeclID ID = LazySpecInfo.DeclID;
367377
assert(ID.isValid() && "Loading already loaded specialization!");
368378
// Note that we loaded the specialization.
@@ -373,6 +383,13 @@ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
373383

374384
void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
375385
ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
386+
auto *ExternalSource = getASTContext().getExternalSource();
387+
if (!ExternalSource)
388+
return;
389+
390+
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(), Args);
391+
return;
392+
376393
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
377394
if (auto *Specs = CommonBasePtr->LazySpecializations) {
378395
unsigned Hash = TemplateArgumentList::ComputeODRHash(Args);

clang/lib/AST/ExternalASTSource.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
9898
return false;
9999
}
100100

101+
void ExternalASTSource::LoadExternalSpecializations(const Decl *D, bool) {}
102+
103+
void ExternalASTSource::LoadExternalSpecializations(
104+
const Decl *D, ArrayRef<TemplateArgument>) {}
105+
101106
void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {}
102107

103108
void ExternalASTSource::FindExternalLexicalDecls(

clang/lib/Sema/MultiplexExternalSemaSource.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
115115
return AnyDeclsFound;
116116
}
117117

118+
void MultiplexExternalSemaSource::LoadExternalSpecializations(
119+
const Decl *D, bool OnlyPartial) {
120+
for (size_t i = 0; i < Sources.size(); ++i)
121+
Sources[i]->LoadExternalSpecializations(D, OnlyPartial);
122+
}
123+
124+
void MultiplexExternalSemaSource::LoadExternalSpecializations(
125+
const Decl *D, ArrayRef<TemplateArgument> TemplateArgs) {
126+
for (size_t i = 0; i < Sources.size(); ++i)
127+
Sources[i]->LoadExternalSpecializations(D, TemplateArgs);
128+
}
129+
118130
void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){
119131
for(size_t i = 0; i < Sources.size(); ++i)
120132
Sources[i]->completeVisibleDeclsMap(DC);

0 commit comments

Comments
 (0)