@@ -869,6 +869,7 @@ void ASTWriter::WriteBlockInfoBlock() {
869
869
RECORD(WEAK_UNDECLARED_IDENTIFIERS);
870
870
RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
871
871
RECORD(UPDATE_VISIBLE);
872
+ RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);
872
873
RECORD(DECL_UPDATE_OFFSETS);
873
874
RECORD(DECL_UPDATES);
874
875
RECORD(CUDA_SPECIAL_DECL_REFS);
@@ -3026,10 +3027,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
3026
3027
Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);
3027
3028
}
3028
3029
3029
- // Emit the initializers, if any.
3030
+ // Emit the reachable initializers.
3031
+ // The initializer may only be unreachable in reduced BMI.
3030
3032
RecordData Inits;
3031
3033
for (Decl *D : Context->getModuleInitializers(Mod))
3032
- Inits.push_back(GetDeclRef(D));
3034
+ if (wasDeclEmitted(D))
3035
+ Inits.push_back(GetDeclRef(D));
3033
3036
if (!Inits.empty())
3034
3037
Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);
3035
3038
@@ -3208,6 +3211,9 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
3208
3211
uint64_t Offset = Stream.GetCurrentBitNo();
3209
3212
SmallVector<uint32_t, 128> KindDeclPairs;
3210
3213
for (const auto *D : DC->decls()) {
3214
+ if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))
3215
+ continue;
3216
+
3211
3217
KindDeclPairs.push_back(D->getKind());
3212
3218
KindDeclPairs.push_back(GetDeclRef(D));
3213
3219
}
@@ -3862,8 +3868,14 @@ class ASTDeclContextNameLookupTrait {
3862
3868
data_type getData(const Coll &Decls) {
3863
3869
unsigned Start = DeclIDs.size();
3864
3870
for (NamedDecl *D : Decls) {
3865
- DeclIDs.push_back(
3866
- Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D)));
3871
+ NamedDecl *DeclForLocalLookup =
3872
+ getDeclForLocalLookup(Writer.getLangOpts(), D);
3873
+
3874
+ if (Writer.getDoneWritingDeclsAndTypes() &&
3875
+ !Writer.wasDeclEmitted(DeclForLocalLookup))
3876
+ continue;
3877
+
3878
+ DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup));
3867
3879
}
3868
3880
return std::make_pair(Start, DeclIDs.size());
3869
3881
}
@@ -3972,11 +3984,20 @@ bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
3972
3984
DC->hasNeedToReconcileExternalVisibleStorage();
3973
3985
}
3974
3986
3975
- bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
3976
- DeclContext *DC) {
3977
- for (auto *D : Result.getLookupResult())
3978
- if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile())
3979
- return false;
3987
+ bool ASTWriter::isLookupResultEntirelyExternalOrUnreachable(
3988
+ StoredDeclsList &Result, DeclContext *DC) {
3989
+ for (auto *D : Result.getLookupResult()) {
3990
+ auto *LocalD = getDeclForLocalLookup(getLangOpts(), D);
3991
+ if (LocalD->isFromASTFile())
3992
+ continue;
3993
+
3994
+ // We can only be sure whether the local declaration is reachable
3995
+ // after we done writing the declarations and types.
3996
+ if (DoneWritingDeclsAndTypes && !wasDeclEmitted(LocalD))
3997
+ continue;
3998
+
3999
+ return false;
4000
+ }
3980
4001
3981
4002
return true;
3982
4003
}
@@ -4014,8 +4035,17 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
4014
4035
// don't need to write an entry for the name at all. If we can't
4015
4036
// write out a lookup set without performing more deserialization,
4016
4037
// just skip this entry.
4017
- if (isLookupResultExternal(Result, DC) &&
4018
- isLookupResultEntirelyExternal(Result, DC))
4038
+ //
4039
+ // Also in reduced BMI, we'd like to avoid writing unreachable
4040
+ // declarations in GMF, so we need to avoid writing declarations
4041
+ // that entirely external or unreachable.
4042
+ //
4043
+ // FIMXE: It looks sufficient to test
4044
+ // isLookupResultEntirelyExternalOrUnreachable here. But due to bug we have
4045
+ // to test isLookupResultExternal here. See
4046
+ // https://github.com/llvm/llvm-project/issues/61065 for details.
4047
+ if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) &&
4048
+ isLookupResultEntirelyExternalOrUnreachable(Result, DC))
4019
4049
continue;
4020
4050
4021
4051
// We also skip empty results. If any of the results could be external and
@@ -4206,9 +4236,15 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
4206
4236
continue;
4207
4237
}
4208
4238
4209
- for (NamedDecl *ND : Result)
4210
- if (!ND->isFromASTFile())
4211
- GetDeclRef(ND);
4239
+ for (NamedDecl *ND : Result) {
4240
+ if (ND->isFromASTFile())
4241
+ continue;
4242
+
4243
+ if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND))
4244
+ continue;
4245
+
4246
+ GetDeclRef(ND);
4247
+ }
4212
4248
}
4213
4249
4214
4250
return 0;
@@ -4976,9 +5012,18 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
4976
5012
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
4977
5013
4978
5014
// Force all top level declarations to be emitted.
4979
- for (const auto *D : TU->noload_decls())
4980
- if (!D->isFromASTFile())
4981
- GetDeclRef(D);
5015
+ //
5016
+ // We start emitting top level declarations from the module purview to
5017
+ // implement the eliding unreachable declaration feature.
5018
+ for (const auto *D : TU->noload_decls()) {
5019
+ if (D->isFromASTFile())
5020
+ continue;
5021
+
5022
+ if (GeneratingReducedBMI && D->isFromExplicitGlobalModule())
5023
+ continue;
5024
+
5025
+ GetDeclRef(D);
5026
+ }
4982
5027
4983
5028
// If the translation unit has an anonymous namespace, and we don't already
4984
5029
// have an update block for it, write it as an update block.
@@ -5288,24 +5333,59 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
5288
5333
WriteDecl(Context, DOT.getDecl());
5289
5334
}
5290
5335
} while (!DeclUpdates.empty());
5291
- Stream.ExitBlock();
5292
5336
5293
5337
DoneWritingDeclsAndTypes = true;
5294
5338
5339
+ // DelayedNamespace is only meaningful in reduced BMI.
5340
+ // See the comments of DelayedNamespace for details.
5341
+ assert(DelayedNamespace.empty() || GeneratingReducedBMI);
5342
+ RecordData DelayedNamespaceRecord;
5343
+ for (NamespaceDecl *NS : DelayedNamespace) {
5344
+ uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS);
5345
+ uint64_t VisibleOffset = WriteDeclContextVisibleBlock(Context, NS);
5346
+
5347
+ // Write the offset relative to current block.
5348
+ if (LexicalOffset)
5349
+ LexicalOffset -= DeclTypesBlockStartOffset;
5350
+
5351
+ if (VisibleOffset)
5352
+ VisibleOffset -= DeclTypesBlockStartOffset;
5353
+
5354
+ DelayedNamespaceRecord.push_back(getDeclID(NS));
5355
+ DelayedNamespaceRecord.push_back(LexicalOffset);
5356
+ DelayedNamespaceRecord.push_back(VisibleOffset);
5357
+ }
5358
+
5359
+ // The process of writing lexical and visible block for delayed namespace
5360
+ // shouldn't introduce any new decls, types or update to emit.
5361
+ assert(DeclTypesToEmit.empty());
5362
+ assert(DeclUpdates.empty());
5363
+
5364
+ Stream.ExitBlock();
5365
+
5295
5366
// These things can only be done once we've written out decls and types.
5296
5367
WriteTypeDeclOffsets();
5297
5368
if (!DeclUpdatesOffsetsRecord.empty())
5298
5369
Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
5299
5370
5371
+ if (!DelayedNamespaceRecord.empty())
5372
+ Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD,
5373
+ DelayedNamespaceRecord);
5374
+
5300
5375
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5301
5376
// Create a lexical update block containing all of the declarations in the
5302
5377
// translation unit that do not come from other AST files.
5303
5378
SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
5304
5379
for (const auto *D : TU->noload_decls()) {
5305
- if (!D->isFromASTFile()) {
5306
- NewGlobalKindDeclPairs.push_back(D->getKind());
5307
- NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
5308
- }
5380
+ if (D->isFromASTFile())
5381
+ continue;
5382
+
5383
+ // In reduced BMI, skip unreached declarations.
5384
+ if (!wasDeclEmitted(D))
5385
+ continue;
5386
+
5387
+ NewGlobalKindDeclPairs.push_back(D->getKind());
5388
+ NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
5309
5389
}
5310
5390
5311
5391
auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
@@ -5814,6 +5894,21 @@ DeclID ASTWriter::getDeclID(const Decl *D) {
5814
5894
return DeclIDs[D];
5815
5895
}
5816
5896
5897
+ bool ASTWriter::wasDeclEmitted(const Decl *D) const {
5898
+ assert(D);
5899
+
5900
+ assert(DoneWritingDeclsAndTypes &&
5901
+ "wasDeclEmitted should only be called after writing declarations");
5902
+
5903
+ if (D->isFromASTFile())
5904
+ return true;
5905
+
5906
+ bool Emitted = DeclIDs.contains(D);
5907
+ assert((Emitted || GeneratingReducedBMI) &&
5908
+ "The declaration can only be omitted in reduced BMI.");
5909
+ return Emitted;
5910
+ }
5911
+
5817
5912
void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) {
5818
5913
assert(ID);
5819
5914
assert(D);
0 commit comments