Skip to content

Commit 9a88b07

Browse files
committedFeb 28, 2024
[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 244e745 commit 9a88b07

15 files changed

+800
-12
lines changed
 

‎clang/include/clang/AST/ExternalASTSource.h

+11
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
150150
virtual bool
151151
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
152152

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

‎clang/include/clang/Sema/MultiplexExternalSemaSource.h

+6
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

+5
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ enum ASTRecordTypes {
698698
/// Record code for an unterminated \#pragma clang assume_nonnull begin
699699
/// recorded in a preamble.
700700
PP_ASSUME_NONNULL_LOC = 67,
701+
702+
UPDATE_SPECIALIZATION = 68,
701703
};
702704

703705
/// Record types used within a source manager block.
@@ -1523,6 +1525,9 @@ enum DeclCode {
15231525
/// A HLSLBufferDecl record.
15241526
DECL_HLSL_BUFFER,
15251527

1528+
// A decls specilization record.
1529+
DECL_SPECIALIZATIONS,
1530+
15261531
/// An ImplicitConceptSpecializationDecl record.
15271532
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
15281533

‎clang/include/clang/Serialization/ASTReader.h

+31-3
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ class ASTIdentifierLookupTrait;
340340
/// The on-disk hash table(s) used for DeclContext name lookup.
341341
struct DeclContextLookupTable;
342342

343+
/// The on-disk hash table(s) used for specialization decls.
344+
struct LazySpecializationInfoLookupTable;
345+
343346
} // namespace reader
344347

345348
} // namespace serialization
@@ -603,21 +606,30 @@ class ASTReader
603606
llvm::DenseMap<const DeclContext *,
604607
serialization::reader::DeclContextLookupTable> Lookups;
605608

609+
/// Map from decls to specialized decls.
610+
llvm::DenseMap<const Decl *,
611+
serialization::reader::LazySpecializationInfoLookupTable>
612+
SpecializationsLookups;
613+
606614
// Updates for visible decls can occur for other contexts than just the
607615
// TU, and when we read those update records, the actual context may not
608616
// be available yet, so have this pending map using the ID as a key. It
609-
// will be realized when the context is actually loaded.
610-
struct PendingVisibleUpdate {
617+
// will be realized when the data is actually loaded.
618+
struct UpdateData {
611619
ModuleFile *Mod;
612620
const unsigned char *Data;
613621
};
614-
using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>;
622+
using DeclContextVisibleUpdates = SmallVector<UpdateData, 1>;
615623

616624
/// Updates to the visible declarations of declaration contexts that
617625
/// haven't been loaded yet.
618626
llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
619627
PendingVisibleUpdates;
620628

629+
using SpecializationsUpdate = SmallVector<UpdateData, 1>;
630+
llvm::DenseMap<serialization::DeclID, SpecializationsUpdate>
631+
PendingSpecializationsUpdates;
632+
621633
/// The set of C++ or Objective-C classes that have forward
622634
/// declarations that have not yet been linked to their definitions.
623635
llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
@@ -644,6 +656,11 @@ class ASTReader
644656
llvm::BitstreamCursor &Cursor,
645657
uint64_t Offset, serialization::DeclID ID);
646658

659+
bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor,
660+
uint64_t Offset, Decl *D);
661+
void AddSpecializations(const Decl *D, const unsigned char *Data,
662+
ModuleFile &M);
663+
647664
/// A vector containing identifiers that have already been
648665
/// loaded.
649666
///
@@ -1348,6 +1365,11 @@ class ASTReader
13481365
const serialization::reader::DeclContextLookupTable *
13491366
getLoadedLookupTables(DeclContext *Primary) const;
13501367

1368+
/// Get the loaded specializations lookup tables for \p D,
1369+
/// if any.
1370+
serialization::reader::LazySpecializationInfoLookupTable *
1371+
getLoadedSpecializationsLookupTables(const Decl *D);
1372+
13511373
private:
13521374
struct ImportedModule {
13531375
ModuleFile *Mod;
@@ -1982,6 +2004,12 @@ class ASTReader
19822004
unsigned BlockID,
19832005
uint64_t *StartOfBlockOffset = nullptr);
19842006

2007+
void LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
2008+
2009+
void
2010+
LoadExternalSpecializations(const Decl *D,
2011+
ArrayRef<TemplateArgument> TemplateArgs) override;
2012+
19852013
/// Finds all the visible declarations with a given name.
19862014
/// The current implementation of this method just loads the entire
19872015
/// lookup table as unmaterialized references.

‎clang/include/clang/Serialization/ASTWriter.h

+14
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,10 @@ class ASTWriter : public ASTDeserializationListener,
385385
/// record containing modifications to them.
386386
DeclUpdateMap DeclUpdates;
387387

388+
using SpecializationUpdateMap =
389+
llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>;
390+
SpecializationUpdateMap SpecializationsUpdates;
391+
388392
using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
389393

390394
/// Map of first declarations from a chained PCH that point to the
@@ -527,6 +531,13 @@ class ASTWriter : public ASTDeserializationListener,
527531
bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
528532
bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC);
529533

534+
void GenerateSpecializationInfoLookupTable(
535+
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
536+
llvm::SmallVectorImpl<char> &LookupTable);
537+
uint64_t WriteSpecializationInfoLookupTable(
538+
const NamedDecl *D,
539+
llvm::SmallVectorImpl<const Decl *> &Specializations);
540+
530541
void GenerateNameLookupTable(const DeclContext *DC,
531542
llvm::SmallVectorImpl<char> &LookupTable);
532543
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
@@ -538,6 +549,7 @@ class ASTWriter : public ASTDeserializationListener,
538549
void WriteReferencedSelectorsPool(Sema &SemaRef);
539550
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
540551
bool IsModule);
552+
void WriteSpecializationsUpdates();
541553
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
542554
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
543555
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
@@ -564,6 +576,8 @@ class ASTWriter : public ASTDeserializationListener,
564576
unsigned DeclEnumAbbrev = 0;
565577
unsigned DeclObjCIvarAbbrev = 0;
566578
unsigned DeclCXXMethodAbbrev = 0;
579+
unsigned DeclSpecializationsAbbrev = 0;
580+
567581
unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0;
568582
unsigned DeclTemplateCXXMethodAbbrev = 0;
569583
unsigned DeclMemberSpecializedCXXMethodAbbrev = 0;

‎clang/lib/AST/DeclTemplate.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,14 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
335335

336336
void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
337337
bool OnlyPartial /*=false*/) const {
338+
auto *ExternalSource = getASTContext().getExternalSource();
339+
if (!ExternalSource)
340+
return;
341+
342+
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
343+
OnlyPartial);
344+
return;
345+
338346
// Grab the most recent declaration to ensure we've loaded any lazy
339347
// redeclarations of this template.
340348
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
@@ -353,6 +361,8 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
353361

354362
Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
355363
LazySpecializationInfo &LazySpecInfo) const {
364+
llvm_unreachable("We don't use LazySpecializationInfo any more");
365+
356366
uint32_t ID = LazySpecInfo.DeclID;
357367
assert(ID && "Loading already loaded specialization!");
358368
// Note that we loaded the specialization.
@@ -362,6 +372,13 @@ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
362372

363373
void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
364374
ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
375+
auto *ExternalSource = getASTContext().getExternalSource();
376+
if (!ExternalSource)
377+
return;
378+
379+
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(), Args);
380+
return;
381+
365382
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
366383
if (auto *Specs = CommonBasePtr->LazySpecializations) {
367384
unsigned Hash = TemplateArgumentList::ComputeODRHash(Args);

‎clang/lib/AST/ExternalASTSource.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
100100
return false;
101101
}
102102

103+
void ExternalASTSource::LoadExternalSpecializations(const Decl *D, bool) {}
104+
105+
void ExternalASTSource::LoadExternalSpecializations(
106+
const Decl *D, ArrayRef<TemplateArgument>) {}
107+
103108
void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {}
104109

105110
void ExternalASTSource::FindExternalLexicalDecls(

‎clang/lib/Sema/MultiplexExternalSemaSource.cpp

+12
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)