[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.
This commit is contained in:
Doug Gregor
2017-01-05 18:24:55 -08:00
parent 153ef7dbcb
commit 69cc9f4b54
9 changed files with 65 additions and 76 deletions

View File

@@ -556,8 +556,6 @@ void Serializer::writeBlockInfoBlock() {
decls_block::GENERIC_PARAM);
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
decls_block::GENERIC_REQUIREMENT);
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
decls_block::SIL_GENERIC_ENVIRONMENT);
BLOCK(SIL_INDEX_BLOCK);
BLOCK_RECORD(sil_index_block, SIL_FUNC_NAMES);
@@ -1011,25 +1009,32 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams) {
return true;
}
void Serializer::writeGenericEnvironment(
const GenericEnvironment *env,
const std::array<unsigned, 256> &abbrCodes,
bool SILMode) {
void Serializer::writeGenericEnvironment(const GenericEnvironment *env) {
using namespace decls_block;
// Record the offset of this generic environment.
if (!SILMode) {
auto id = GenericEnvironmentIDs[env];
assert(id != 0 && "generic environment not referenced properly");
(void)id;
auto id = GenericEnvironmentIDs[env];
assert(id != 0 && "generic environment not referenced properly");
(void)id;
assert((id - 1) == GenericEnvironmentOffsets.size());
GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
}
assert((id - 1) == GenericEnvironmentOffsets.size());
GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
if (env == nullptr)
return;
// Determine whether we must use SIL mode, because one of the generic
// parameters has a declaration with module context.
bool SILMode = false;
for (auto *paramTy : env->getGenericParams()) {
if (auto *decl = paramTy->getDecl()) {
if (decl->getDeclContext()->isModuleScopeContext()) {
SILMode = true;
break;
}
}
}
// Record the generic parameters.
SmallVector<uint64_t, 4> rawParamIDs;
for (auto *paramTy : env->getGenericParams()) {
@@ -1050,20 +1055,17 @@ void Serializer::writeGenericEnvironment(
}
if (SILMode) {
assert(&abbrCodes != &DeclTypeAbbrCodes);
auto envAbbrCode = abbrCodes[SILGenericEnvironmentLayout::Code];
auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
rawParamIDs);
return;
} else {
auto envAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
rawParamIDs);
}
assert(&abbrCodes == &DeclTypeAbbrCodes);
auto envAbbrCode = abbrCodes[GenericEnvironmentLayout::Code];
GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
rawParamIDs);
writeGenericRequirements(env->getGenericSignature()->getRequirements(),
abbrCodes);
DeclTypeAbbrCodes);
}
void Serializer::writeSILLayout(SILLayout *layout) {
@@ -3437,6 +3439,7 @@ void Serializer::writeAllDeclsAndTypes() {
registerDeclTypeAbbr<GenericParamLayout>();
registerDeclTypeAbbr<GenericRequirementLayout>();
registerDeclTypeAbbr<GenericEnvironmentLayout>();
registerDeclTypeAbbr<SILGenericEnvironmentLayout>();
registerDeclTypeAbbr<ForeignErrorConventionLayout>();
registerDeclTypeAbbr<DeclContextLayout>();
@@ -3498,7 +3501,7 @@ void Serializer::writeAllDeclsAndTypes() {
while (!GenericEnvironmentsToWrite.empty()) {
auto next = GenericEnvironmentsToWrite.front();
GenericEnvironmentsToWrite.pop();
writeGenericEnvironment(next, DeclTypeAbbrCodes, /*SILMode=*/false);
writeGenericEnvironment(next);
}
while (!NormalConformancesToWrite.empty()) {