Skip to content

Commit 69cc9f4

Browse files
committed
[Serialization] Unique SIL generic environments when serializing.
Teach the serialization of SIL generic environments, which used to be a trailing record following the SIL function definition, to use the same uniqued "generic environment IDs" that are used for the AST generic environments. Many of them overlap anyway, and SIL functions tend to have AST generic environments anyway. This approach guarantees that the AST + SIL deserialization provide the same uniqueness of generic environments present prior to serialization.
1 parent 153ef7d commit 69cc9f4

File tree

9 files changed

+65
-76
lines changed

9 files changed

+65
-76
lines changed

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ OTHER(GENERIC_PARAM_LIST, 240)
164164
TRAILING_INFO(GENERIC_PARAM)
165165
TRAILING_INFO(GENERIC_REQUIREMENT)
166166
OTHER(GENERIC_ENVIRONMENT, 243)
167-
TRAILING_INFO(SIL_GENERIC_ENVIRONMENT)
167+
OTHER(SIL_GENERIC_ENVIRONMENT, 244)
168168

169169
OTHER(LOCAL_DISCRIMINATOR, 248)
170170
OTHER(PRIVATE_DISCRIMINATOR, 249)

include/swift/Serialization/ModuleFile.h

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,17 @@ class ModuleFile : public LazyMemberLoader {
529529
serialization::DeclID willSet,
530530
serialization::DeclID didSet);
531531

532+
/// Return the generic signature or environment at the current position in
533+
/// the given cursor.
534+
///
535+
/// \param cursor The cursor to read from.
536+
/// \param wantEnvironment Whether we always want to receive a generic
537+
/// environment vs. being able to handle the generic signature.
538+
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
539+
readGenericSignatureOrEnvironment(
540+
llvm::BitstreamCursor &cursor,
541+
bool wantEnvironment);
542+
532543
public:
533544
/// Loads a module from the given memory buffer.
534545
///
@@ -741,20 +752,6 @@ class ModuleFile : public LazyMemberLoader {
741752
/// is loaded instead.
742753
Module *getModule(ArrayRef<Identifier> name);
743754

744-
/// Return the generic signature or environment at the current position in
745-
/// the given cursor.
746-
///
747-
/// \param cursor The cursor to read from.
748-
/// \param wantEnvironment Whether we always want to receive a generic
749-
/// environment vs. being able to handle the generic signature.
750-
/// \param optRequirements If not \c None, use these generic requirements
751-
/// rather than deserializing requirements.
752-
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
753-
readGenericSignatureOrEnvironment(
754-
llvm::BitstreamCursor &cursor,
755-
bool wantEnvironment,
756-
Optional<ArrayRef<Requirement>> optRequirements);
757-
758755
/// Returns the generic signature or environment for the given ID,
759756
/// deserializing it if needed.
760757
///

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 302; // Last change: SIL box type substitutions
57+
const uint16_t VERSION_MINOR = 303; // Last change: SIL generic environments
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/Serialization/Deserialization.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -967,8 +967,7 @@ void ModuleFile::configureGenericEnvironment(
967967
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
968968
ModuleFile::readGenericSignatureOrEnvironment(
969969
llvm::BitstreamCursor &cursor,
970-
bool wantEnvironment,
971-
Optional<ArrayRef<Requirement>> optRequirements) {
970+
bool wantEnvironment) {
972971
using namespace decls_block;
973972

974973
SmallVector<uint64_t, 8> scratch;
@@ -1068,14 +1067,8 @@ ModuleFile::readGenericSignatureOrEnvironment(
10681067
}
10691068

10701069
// Read the generic requirements.
1071-
ArrayRef<Requirement> requirements;
1072-
SmallVector<Requirement, 4> requirementsVec;
1073-
if (optRequirements) {
1074-
requirements = *optRequirements;
1075-
} else {
1076-
readGenericRequirements(requirementsVec, cursor);
1077-
requirements = requirementsVec;
1078-
}
1070+
SmallVector<Requirement, 4> requirements;
1071+
readGenericRequirements(requirements, cursor);
10791072

10801073
// Construct the generic signature from the loaded parameters and
10811074
// requirements.
@@ -1113,15 +1106,20 @@ ModuleFile::getGenericSignatureOrEnvironment(
11131106
// Read the generic environment.
11141107
BCOffsetRAII restoreOffset(DeclTypeCursor);
11151108
DeclTypeCursor.JumpToBit(envOrOffset);
1109+
DeserializingEntityRAII deserializingEntity(*this);
11161110

11171111
auto result = readGenericSignatureOrEnvironment(DeclTypeCursor,
1118-
wantEnvironment,
1119-
None);
1112+
wantEnvironment);
11201113
if (result.isNull()) {
11211114
envOrOffset = nullptr;
11221115
return envOrOffset.get();
11231116
}
11241117

1118+
// If we've already deserialized this generic environment, return it.
1119+
if (envOrOffset.isComplete()) {
1120+
return envOrOffset.get();
1121+
}
1122+
11251123
if (auto signature = result.dyn_cast<GenericSignature *>()) {
11261124
assert(!wantEnvironment && "Reader should have produced the environment");
11271125
return signature;

lib/Serialization/DeserializeSIL.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -379,14 +379,15 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
379379

380380
DeclID clangNodeOwnerID;
381381
TypeID funcTyID;
382+
GenericEnvironmentID genericEnvID;
382383
unsigned rawLinkage, isTransparent, isFragile, isThunk, isGlobal,
383384
inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
384385
ArrayRef<uint64_t> SemanticsIDs;
385386
// TODO: read fragile
386387
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isFragile,
387388
isThunk, isGlobal, inlineStrategy, effect,
388389
numSpecAttrs, hasQualifiedOwnership, funcTyID,
389-
clangNodeOwnerID, SemanticsIDs);
390+
genericEnvID, clangNodeOwnerID, SemanticsIDs);
390391

391392
if (funcTyID == 0) {
392393
DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n");
@@ -491,15 +492,8 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
491492
}
492493

493494
GenericEnvironment *genericEnv = nullptr;
494-
if (!declarationOnly) {
495-
auto signature = fn->getLoweredFunctionType()->getGenericSignature();
496-
genericEnv = MF->readGenericSignatureOrEnvironment(
497-
SILCursor,
498-
/*wantEnvironment=*/true,
499-
signature ? signature->getRequirements()
500-
: ArrayRef<Requirement>())
501-
.get<GenericEnvironment *>();
502-
}
495+
if (!declarationOnly)
496+
genericEnv = MF->getGenericEnvironment(genericEnvID);
503497

504498
// If the next entry is the end of the block, then this function has
505499
// no contents.
@@ -2001,13 +1995,14 @@ bool SILDeserializer::hasSILFunction(StringRef Name,
20011995
// linkage to avoid re-reading it from the bitcode each time?
20021996
DeclID clangOwnerID;
20031997
TypeID funcTyID;
1998+
GenericEnvironmentID genericEnvID;
20041999
unsigned rawLinkage, isTransparent, isFragile, isThunk, isGlobal,
20052000
inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
20062001
ArrayRef<uint64_t> SemanticsIDs;
20072002
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isFragile,
20082003
isThunk, isGlobal, inlineStrategy, effect,
20092004
numSpecAttrs, hasQualifiedOwnership, funcTyID,
2010-
clangOwnerID, SemanticsIDs);
2005+
genericEnvID, clangOwnerID, SemanticsIDs);
20112006
auto linkage = fromStableSILLinkage(rawLinkage);
20122007
if (!linkage) {
20132008
DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ namespace sil_block {
247247
BCFixed<2>, // number of specialize attributes
248248
BCFixed<1>, // has qualified ownership
249249
TypeIDField, // SILFunctionType
250+
GenericEnvironmentIDField,
250251
DeclIDField, // ClangNode owner
251252
BCArray<IdentifierIDField> // Semantics Attribute
252253
// followed by specialize attributes

lib/Serialization/Serialization.cpp

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,6 @@ void Serializer::writeBlockInfoBlock() {
556556
decls_block::GENERIC_PARAM);
557557
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
558558
decls_block::GENERIC_REQUIREMENT);
559-
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
560-
decls_block::SIL_GENERIC_ENVIRONMENT);
561559

562560
BLOCK(SIL_INDEX_BLOCK);
563561
BLOCK_RECORD(sil_index_block, SIL_FUNC_NAMES);
@@ -1011,25 +1009,32 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams) {
10111009
return true;
10121010
}
10131011

1014-
void Serializer::writeGenericEnvironment(
1015-
const GenericEnvironment *env,
1016-
const std::array<unsigned, 256> &abbrCodes,
1017-
bool SILMode) {
1012+
void Serializer::writeGenericEnvironment(const GenericEnvironment *env) {
10181013
using namespace decls_block;
10191014

10201015
// Record the offset of this generic environment.
1021-
if (!SILMode) {
1022-
auto id = GenericEnvironmentIDs[env];
1023-
assert(id != 0 && "generic environment not referenced properly");
1024-
(void)id;
1016+
auto id = GenericEnvironmentIDs[env];
1017+
assert(id != 0 && "generic environment not referenced properly");
1018+
(void)id;
10251019

1026-
assert((id - 1) == GenericEnvironmentOffsets.size());
1027-
GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
1028-
}
1020+
assert((id - 1) == GenericEnvironmentOffsets.size());
1021+
GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
10291022

10301023
if (env == nullptr)
10311024
return;
10321025

1026+
// Determine whether we must use SIL mode, because one of the generic
1027+
// parameters has a declaration with module context.
1028+
bool SILMode = false;
1029+
for (auto *paramTy : env->getGenericParams()) {
1030+
if (auto *decl = paramTy->getDecl()) {
1031+
if (decl->getDeclContext()->isModuleScopeContext()) {
1032+
SILMode = true;
1033+
break;
1034+
}
1035+
}
1036+
}
1037+
10331038
// Record the generic parameters.
10341039
SmallVector<uint64_t, 4> rawParamIDs;
10351040
for (auto *paramTy : env->getGenericParams()) {
@@ -1050,20 +1055,17 @@ void Serializer::writeGenericEnvironment(
10501055
}
10511056

10521057
if (SILMode) {
1053-
assert(&abbrCodes != &DeclTypeAbbrCodes);
1054-
auto envAbbrCode = abbrCodes[SILGenericEnvironmentLayout::Code];
1058+
auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
10551059
SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
10561060
rawParamIDs);
1057-
return;
1061+
} else {
1062+
auto envAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
1063+
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
1064+
rawParamIDs);
10581065
}
10591066

1060-
assert(&abbrCodes == &DeclTypeAbbrCodes);
1061-
auto envAbbrCode = abbrCodes[GenericEnvironmentLayout::Code];
1062-
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
1063-
rawParamIDs);
1064-
10651067
writeGenericRequirements(env->getGenericSignature()->getRequirements(),
1066-
abbrCodes);
1068+
DeclTypeAbbrCodes);
10671069
}
10681070

10691071
void Serializer::writeSILLayout(SILLayout *layout) {
@@ -3437,6 +3439,7 @@ void Serializer::writeAllDeclsAndTypes() {
34373439
registerDeclTypeAbbr<GenericParamLayout>();
34383440
registerDeclTypeAbbr<GenericRequirementLayout>();
34393441
registerDeclTypeAbbr<GenericEnvironmentLayout>();
3442+
registerDeclTypeAbbr<SILGenericEnvironmentLayout>();
34403443

34413444
registerDeclTypeAbbr<ForeignErrorConventionLayout>();
34423445
registerDeclTypeAbbr<DeclContextLayout>();
@@ -3498,7 +3501,7 @@ void Serializer::writeAllDeclsAndTypes() {
34983501
while (!GenericEnvironmentsToWrite.empty()) {
34993502
auto next = GenericEnvironmentsToWrite.front();
35003503
GenericEnvironmentsToWrite.pop();
3501-
writeGenericEnvironment(next, DeclTypeAbbrCodes, /*SILMode=*/false);
3504+
writeGenericEnvironment(next);
35023505
}
35033506

35043507
while (!NormalConformancesToWrite.empty()) {

lib/Serialization/Serialization.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@ class Serializer {
338338
/// Writes the given type.
339339
void writeType(Type ty);
340340

341+
/// Writes a generic environment.
342+
void writeGenericEnvironment(const GenericEnvironment *env);
343+
341344
/// Registers the abbreviation for the given decl or type layout.
342345
template <typename Layout>
343346
void registerDeclTypeAbbr() {
@@ -471,11 +474,6 @@ class Serializer {
471474
void writeConformance(ProtocolConformance *conformance,
472475
const std::array<unsigned, 256> &abbrCodes,
473476
GenericEnvironment *genericEnv = nullptr);
474-
475-
/// Writes a generic environment.
476-
void writeGenericEnvironment(const GenericEnvironment *env,
477-
const std::array<unsigned, 256> &abbrCodes,
478-
bool SILMode);
479477
};
480478
} // end namespace serialization
481479
} // end namespace swift

lib/Serialization/SerializeSIL.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
348348
Linkage = addExternalToLinkage(Linkage);
349349
}
350350

351+
// If we have a body, we might have a generic environment.
352+
GenericEnvironmentID genericEnvID = 0;
353+
if (!F.isExternalDeclaration())
354+
genericEnvID = S.addGenericEnvironmentRef(F.getGenericEnvironment());
355+
351356
DeclID clangNodeOwnerID;
352357
if (F.hasClangNode())
353358
clangNodeOwnerID = S.addDeclRef(F.getClangNodeOwner());
@@ -359,7 +364,7 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
359364
(unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
360365
(unsigned)F.getInlineStrategy(), (unsigned)F.getEffectsKind(),
361366
(unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
362-
clangNodeOwnerID, SemanticsIDs);
367+
genericEnvID, clangNodeOwnerID, SemanticsIDs);
363368

364369
if (NoBody)
365370
return;
@@ -373,12 +378,6 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
373378
S.writeSubstitutions(subs, SILAbbrCodes);
374379
}
375380

376-
// Write the body's context archetypes, unless we don't actually have a body.
377-
if (!F.isExternalDeclaration()) {
378-
if (auto genericEnv = F.getGenericEnvironment())
379-
S.writeGenericEnvironment(genericEnv, SILAbbrCodes, true);
380-
}
381-
382381
// Assign a unique ID to each basic block of the SILFunction.
383382
unsigned BasicID = 0;
384383
BasicBlockMap.clear();
@@ -1918,8 +1917,6 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
19181917
registerSILAbbr<decls_block::NormalProtocolConformanceIdLayout>();
19191918
registerSILAbbr<decls_block::ProtocolConformanceXrefLayout>();
19201919
registerSILAbbr<decls_block::GenericRequirementLayout>();
1921-
registerSILAbbr<decls_block::GenericEnvironmentLayout>();
1922-
registerSILAbbr<decls_block::SILGenericEnvironmentLayout>();
19231920

19241921
for (const SILGlobalVariable &g : SILMod->getSILGlobals())
19251922
writeSILGlobalVar(g);

0 commit comments

Comments
 (0)