Skip to content

[Serialization] Unique SIL generic environments when serializing. #6609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/Serialization/DeclTypeRecordNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ OTHER(GENERIC_PARAM_LIST, 240)
TRAILING_INFO(GENERIC_PARAM)
TRAILING_INFO(GENERIC_REQUIREMENT)
OTHER(GENERIC_ENVIRONMENT, 243)
TRAILING_INFO(SIL_GENERIC_ENVIRONMENT)
OTHER(SIL_GENERIC_ENVIRONMENT, 244)

OTHER(LOCAL_DISCRIMINATOR, 248)
OTHER(PRIVATE_DISCRIMINATOR, 249)
Expand Down
25 changes: 11 additions & 14 deletions include/swift/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,17 @@ class ModuleFile : public LazyMemberLoader {
serialization::DeclID willSet,
serialization::DeclID didSet);

/// Return the generic signature or environment at the current position in
/// the given cursor.
///
/// \param cursor The cursor to read from.
/// \param wantEnvironment Whether we always want to receive a generic
/// environment vs. being able to handle the generic signature.
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
readGenericSignatureOrEnvironment(
llvm::BitstreamCursor &cursor,
bool wantEnvironment);

public:
/// Loads a module from the given memory buffer.
///
Expand Down Expand Up @@ -741,20 +752,6 @@ class ModuleFile : public LazyMemberLoader {
/// is loaded instead.
Module *getModule(ArrayRef<Identifier> name);

/// Return the generic signature or environment at the current position in
/// the given cursor.
///
/// \param cursor The cursor to read from.
/// \param wantEnvironment Whether we always want to receive a generic
/// environment vs. being able to handle the generic signature.
/// \param optRequirements If not \c None, use these generic requirements
/// rather than deserializing requirements.
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
readGenericSignatureOrEnvironment(
llvm::BitstreamCursor &cursor,
bool wantEnvironment,
Optional<ArrayRef<Requirement>> optRequirements);

/// Returns the generic signature or environment for the given ID,
/// deserializing it if needed.
///
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 302; // Last change: SIL box type substitutions
const uint16_t VERSION_MINOR = 303; // Last change: SIL generic environments

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down
1 change: 0 additions & 1 deletion lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,6 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,

// Add fix-it to insert '()', only if this is a metatype of
// non-existential type and has any initializers.
auto eTy = E->getType();
bool isExistential = false;
if (auto metaTy = E->getType()->getAs<MetatypeType>()) {
auto instanceTy = metaTy->getInstanceType();
Expand Down
22 changes: 10 additions & 12 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,8 +967,7 @@ void ModuleFile::configureGenericEnvironment(
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
ModuleFile::readGenericSignatureOrEnvironment(
llvm::BitstreamCursor &cursor,
bool wantEnvironment,
Optional<ArrayRef<Requirement>> optRequirements) {
bool wantEnvironment) {
using namespace decls_block;

SmallVector<uint64_t, 8> scratch;
Expand Down Expand Up @@ -1068,14 +1067,8 @@ ModuleFile::readGenericSignatureOrEnvironment(
}

// Read the generic requirements.
ArrayRef<Requirement> requirements;
SmallVector<Requirement, 4> requirementsVec;
if (optRequirements) {
requirements = *optRequirements;
} else {
readGenericRequirements(requirementsVec, cursor);
requirements = requirementsVec;
}
SmallVector<Requirement, 4> requirements;
readGenericRequirements(requirements, cursor);

// Construct the generic signature from the loaded parameters and
// requirements.
Expand Down Expand Up @@ -1113,15 +1106,20 @@ ModuleFile::getGenericSignatureOrEnvironment(
// Read the generic environment.
BCOffsetRAII restoreOffset(DeclTypeCursor);
DeclTypeCursor.JumpToBit(envOrOffset);
DeserializingEntityRAII deserializingEntity(*this);

auto result = readGenericSignatureOrEnvironment(DeclTypeCursor,
wantEnvironment,
None);
wantEnvironment);
if (result.isNull()) {
envOrOffset = nullptr;
return envOrOffset.get();
}

// If we've already deserialized this generic environment, return it.
if (envOrOffset.isComplete()) {
return envOrOffset.get();
}

if (auto signature = result.dyn_cast<GenericSignature *>()) {
assert(!wantEnvironment && "Reader should have produced the environment");
return signature;
Expand Down
17 changes: 6 additions & 11 deletions lib/Serialization/DeserializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,14 +379,15 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,

DeclID clangNodeOwnerID;
TypeID funcTyID;
GenericEnvironmentID genericEnvID;
unsigned rawLinkage, isTransparent, isFragile, isThunk, isGlobal,
inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
ArrayRef<uint64_t> SemanticsIDs;
// TODO: read fragile
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isFragile,
isThunk, isGlobal, inlineStrategy, effect,
numSpecAttrs, hasQualifiedOwnership, funcTyID,
clangNodeOwnerID, SemanticsIDs);
genericEnvID, clangNodeOwnerID, SemanticsIDs);

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

GenericEnvironment *genericEnv = nullptr;
if (!declarationOnly) {
auto signature = fn->getLoweredFunctionType()->getGenericSignature();
genericEnv = MF->readGenericSignatureOrEnvironment(
SILCursor,
/*wantEnvironment=*/true,
signature ? signature->getRequirements()
: ArrayRef<Requirement>())
.get<GenericEnvironment *>();
}
if (!declarationOnly)
genericEnv = MF->getGenericEnvironment(genericEnvID);

// If the next entry is the end of the block, then this function has
// no contents.
Expand Down Expand Up @@ -2001,13 +1995,14 @@ bool SILDeserializer::hasSILFunction(StringRef Name,
// linkage to avoid re-reading it from the bitcode each time?
DeclID clangOwnerID;
TypeID funcTyID;
GenericEnvironmentID genericEnvID;
unsigned rawLinkage, isTransparent, isFragile, isThunk, isGlobal,
inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
ArrayRef<uint64_t> SemanticsIDs;
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isFragile,
isThunk, isGlobal, inlineStrategy, effect,
numSpecAttrs, hasQualifiedOwnership, funcTyID,
clangOwnerID, SemanticsIDs);
genericEnvID, clangOwnerID, SemanticsIDs);
auto linkage = fromStableSILLinkage(rawLinkage);
if (!linkage) {
DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage
Expand Down
1 change: 1 addition & 0 deletions lib/Serialization/SILFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ namespace sil_block {
BCFixed<2>, // number of specialize attributes
BCFixed<1>, // has qualified ownership
TypeIDField, // SILFunctionType
GenericEnvironmentIDField,
DeclIDField, // ClangNode owner
BCArray<IdentifierIDField> // Semantics Attribute
// followed by specialize attributes
Expand Down
49 changes: 26 additions & 23 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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()) {
Expand All @@ -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) {
Expand Down Expand Up @@ -3437,6 +3439,7 @@ void Serializer::writeAllDeclsAndTypes() {
registerDeclTypeAbbr<GenericParamLayout>();
registerDeclTypeAbbr<GenericRequirementLayout>();
registerDeclTypeAbbr<GenericEnvironmentLayout>();
registerDeclTypeAbbr<SILGenericEnvironmentLayout>();

registerDeclTypeAbbr<ForeignErrorConventionLayout>();
registerDeclTypeAbbr<DeclContextLayout>();
Expand Down Expand Up @@ -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()) {
Expand Down
8 changes: 3 additions & 5 deletions lib/Serialization/Serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ class Serializer {
/// Writes the given type.
void writeType(Type ty);

/// Writes a generic environment.
void writeGenericEnvironment(const GenericEnvironment *env);

/// Registers the abbreviation for the given decl or type layout.
template <typename Layout>
void registerDeclTypeAbbr() {
Expand Down Expand Up @@ -471,11 +474,6 @@ class Serializer {
void writeConformance(ProtocolConformance *conformance,
const std::array<unsigned, 256> &abbrCodes,
GenericEnvironment *genericEnv = nullptr);

/// Writes a generic environment.
void writeGenericEnvironment(const GenericEnvironment *env,
const std::array<unsigned, 256> &abbrCodes,
bool SILMode);
};
} // end namespace serialization
} // end namespace swift
Expand Down
15 changes: 6 additions & 9 deletions lib/Serialization/SerializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
Linkage = addExternalToLinkage(Linkage);
}

// If we have a body, we might have a generic environment.
GenericEnvironmentID genericEnvID = 0;
if (!F.isExternalDeclaration())
genericEnvID = S.addGenericEnvironmentRef(F.getGenericEnvironment());

DeclID clangNodeOwnerID;
if (F.hasClangNode())
clangNodeOwnerID = S.addDeclRef(F.getClangNodeOwner());
Expand All @@ -359,7 +364,7 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
(unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
(unsigned)F.getInlineStrategy(), (unsigned)F.getEffectsKind(),
(unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
clangNodeOwnerID, SemanticsIDs);
genericEnvID, clangNodeOwnerID, SemanticsIDs);

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

// Write the body's context archetypes, unless we don't actually have a body.
if (!F.isExternalDeclaration()) {
if (auto genericEnv = F.getGenericEnvironment())
S.writeGenericEnvironment(genericEnv, SILAbbrCodes, true);
}

// Assign a unique ID to each basic block of the SILFunction.
unsigned BasicID = 0;
BasicBlockMap.clear();
Expand Down Expand Up @@ -1918,8 +1917,6 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
registerSILAbbr<decls_block::NormalProtocolConformanceIdLayout>();
registerSILAbbr<decls_block::ProtocolConformanceXrefLayout>();
registerSILAbbr<decls_block::GenericRequirementLayout>();
registerSILAbbr<decls_block::GenericEnvironmentLayout>();
registerSILAbbr<decls_block::SILGenericEnvironmentLayout>();

for (const SILGlobalVariable &g : SILMod->getSILGlobals())
writeSILGlobalVar(g);
Expand Down