mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Serialization: Fix a couple of issues with serializing context params of generic SILFunctions.
- Parameterize maybeReadGenericParams' BitstreamCursor so that we can read from the correct cursor when trying to read the generic params of a SILFunction. - Only serialize the context generic params for SILFunctions for which we're serializing a complete definition. This fixes issues with us getting the wrong archetypes forward-declared from references in other modules. In this version of the patch, we adjust the deserialization point for the generic param list to correctly come before we check if the SILFunction block is empty, and we add a kludge to keep the JIT from crapping itself when it sees the same transparent definition in multiple REPL lines' modules <rdar://problem/16094902>. The previous commit solves a problem this exposed at r14050 in inout deshadowing that caused memory corruption when transparent functions were imported. This should now be safe to commit. Swift SVN r14109
This commit is contained in:
@@ -560,7 +560,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
|
||||
|
||||
static std::pair<llvm::GlobalValue::LinkageTypes,
|
||||
llvm::GlobalValue::VisibilityTypes>
|
||||
getIRLinkage(SILLinkage linkage, ForDefinition_t isDefinition) {
|
||||
getIRLinkage(IRGenModule &IGM,
|
||||
SILLinkage linkage, ForDefinition_t isDefinition) {
|
||||
switch (linkage) {
|
||||
#define RESULT(LINKAGE, VISIBILITY) \
|
||||
{ llvm::GlobalValue::LINKAGE##Linkage, \
|
||||
@@ -571,10 +572,22 @@ getIRLinkage(SILLinkage linkage, ForDefinition_t isDefinition) {
|
||||
case SILLinkage::Hidden: return RESULT(External, Hidden);
|
||||
case SILLinkage::Private: return RESULT(Internal, Default);
|
||||
case SILLinkage::PublicExternal:
|
||||
if (isDefinition) return RESULT(AvailableExternally, Default);
|
||||
if (isDefinition) {
|
||||
// FIXME: Work around problems linking available_externally symbols in the
|
||||
// REPL. <rdar://problem/16094902>
|
||||
if (IGM.Opts.UseJIT)
|
||||
return RESULT(LinkOnceODR, Default);
|
||||
return RESULT(AvailableExternally, Default);
|
||||
}
|
||||
return RESULT(External, Default);
|
||||
case SILLinkage::HiddenExternal:
|
||||
if (isDefinition) return RESULT(AvailableExternally, Hidden);
|
||||
if (isDefinition) {
|
||||
// FIXME: Work around problems linking available_externally symbols in the
|
||||
// REPL. <rdar://problem/16094902>
|
||||
if (IGM.Opts.UseJIT)
|
||||
return RESULT(LinkOnceODR, Hidden);
|
||||
return RESULT(AvailableExternally, Hidden);
|
||||
}
|
||||
return RESULT(External, Hidden);
|
||||
}
|
||||
llvm_unreachable("bad SIL linkage");
|
||||
@@ -582,11 +595,13 @@ getIRLinkage(SILLinkage linkage, ForDefinition_t isDefinition) {
|
||||
|
||||
/// Given that we're going to define a global value but already have a
|
||||
/// forward-declaration of it, update its linkage.
|
||||
static void updateLinkageForDefinition(llvm::GlobalValue *global,
|
||||
static void updateLinkageForDefinition(IRGenModule &IGM,
|
||||
llvm::GlobalValue *global,
|
||||
const LinkEntity &entity) {
|
||||
// TODO: there are probably cases where we can avoid redoing the
|
||||
// entire linkage computation.
|
||||
auto linkage = getIRLinkage(entity.getLinkage(ForDefinition), ForDefinition);
|
||||
auto linkage = getIRLinkage(IGM,
|
||||
entity.getLinkage(ForDefinition), ForDefinition);
|
||||
global->setLinkage(linkage.first);
|
||||
global->setVisibility(linkage.second);
|
||||
}
|
||||
@@ -598,7 +613,7 @@ LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
|
||||
entity.mangle(result.Name);
|
||||
|
||||
llvm::tie(result.Linkage, result.Visibility) =
|
||||
getIRLinkage(entity.getLinkage(isDefinition), isDefinition);
|
||||
getIRLinkage(IGM, entity.getLinkage(isDefinition), isDefinition);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -789,7 +804,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
|
||||
// FIXME: We should integrate this into the LinkEntity cache more cleanly.
|
||||
auto gvar = Module.getGlobalVariable(var->getName(), /*allowInternal*/ true);
|
||||
if (gvar) {
|
||||
if (forDefinition) updateLinkageForDefinition(gvar, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(*this, gvar, entity);
|
||||
return Address(gvar, Alignment(gvar->getAlignment()));
|
||||
}
|
||||
|
||||
@@ -820,7 +835,7 @@ Address IRGenModule::getAddrOfGlobalVariable(VarDecl *var,
|
||||
llvm::GlobalVariable *&entry = GlobalVars[entity];
|
||||
if (entry) {
|
||||
llvm::GlobalVariable *gv = cast<llvm::GlobalVariable>(entry);
|
||||
if (forDefinition) updateLinkageForDefinition(gv, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(*this, gv, entity);
|
||||
return Address(gv, Alignment(gv->getAlignment()));
|
||||
}
|
||||
|
||||
@@ -869,7 +884,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(SILFunction *f,
|
||||
// FIXME: We should integrate this into the LinkEntity cache more cleanly.
|
||||
llvm::Function *fn = Module.getFunction(f->getName());
|
||||
if (fn) {
|
||||
if (forDefinition) updateLinkageForDefinition(fn, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(*this, fn, entity);
|
||||
return fn;
|
||||
}
|
||||
|
||||
@@ -904,7 +919,7 @@ llvm::Function *IRGenModule::getAddrOfFunction(FunctionRef fn,
|
||||
// Check whether we've cached this.
|
||||
llvm::Function *&entry = GlobalFuncs[entity];
|
||||
if (entry) {
|
||||
if (forDefinition) updateLinkageForDefinition(entry, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -946,7 +961,7 @@ static llvm::Constant *getAddrOfLLVMVariable(IRGenModule &IGM,
|
||||
// forward declaration.
|
||||
if (definitionType) {
|
||||
assert(entry->getType() == pointerToDefaultType);
|
||||
updateLinkageForDefinition(entry, entity);
|
||||
updateLinkageForDefinition(IGM, entry, entity);
|
||||
|
||||
// If the type is right, we're done.
|
||||
if (definitionType == defaultType)
|
||||
@@ -1172,7 +1187,7 @@ IRGenModule::getAddrOfBridgeToBlockConverter(SILType blockType,
|
||||
// Check whether we've cached this.
|
||||
llvm::Function *&entry = GlobalFuncs[entity];
|
||||
if (entry) {
|
||||
if (forDefinition) updateLinkageForDefinition(entry, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -1229,7 +1244,7 @@ llvm::Function *IRGenModule::getAddrOfValueWitness(CanType abstractType,
|
||||
|
||||
llvm::Function *&entry = GlobalFuncs[entity];
|
||||
if (entry) {
|
||||
if (forDefinition) updateLinkageForDefinition(entry, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -1266,7 +1281,7 @@ static Address getAddrOfSimpleVariable(IRGenModule &IGM,
|
||||
llvm::GlobalVariable *&entry = cache[entity];
|
||||
if (entry) {
|
||||
assert(alignment == Alignment(entry->getAlignment()));
|
||||
if (forDefinition) updateLinkageForDefinition(entry, entity);
|
||||
if (forDefinition) updateLinkageForDefinition(IGM, entry, entity);
|
||||
return Address(entry, alignment);
|
||||
}
|
||||
|
||||
|
||||
@@ -616,7 +616,8 @@ Optional<Substitution> ModuleFile::maybeReadSubstitution(
|
||||
|
||||
GenericParamList *
|
||||
ModuleFile::maybeGetOrReadGenericParams(serialization::DeclID genericContextID,
|
||||
DeclContext *DC) {
|
||||
DeclContext *DC,
|
||||
llvm::BitstreamCursor &Cursor) {
|
||||
if (genericContextID) {
|
||||
Decl *genericContext = getDecl(genericContextID);
|
||||
assert(genericContext && "loading PolymorphicFunctionType before its decl");
|
||||
@@ -635,24 +636,25 @@ ModuleFile::maybeGetOrReadGenericParams(serialization::DeclID genericContextID,
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
return maybeReadGenericParams(DC);
|
||||
return maybeReadGenericParams(DC, Cursor);
|
||||
}
|
||||
}
|
||||
|
||||
GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
|
||||
GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC,
|
||||
llvm::BitstreamCursor &Cursor) {
|
||||
using namespace decls_block;
|
||||
|
||||
assert(DC && "need a context for the decls in the list");
|
||||
|
||||
BCOffsetRAII lastRecordOffset(DeclTypeCursor);
|
||||
BCOffsetRAII lastRecordOffset(Cursor);
|
||||
SmallVector<uint64_t, 8> scratch;
|
||||
StringRef blobData;
|
||||
|
||||
auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
|
||||
auto next = Cursor.advance(AF_DontPopBlockAtEnd);
|
||||
if (next.Kind != llvm::BitstreamEntry::Record)
|
||||
return nullptr;
|
||||
|
||||
unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData);
|
||||
unsigned kind = Cursor.readRecord(next.ID, scratch, &blobData);
|
||||
|
||||
if (kind != GENERIC_PARAM_LIST)
|
||||
return nullptr;
|
||||
@@ -670,12 +672,12 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
|
||||
lastRecordOffset.reset();
|
||||
bool shouldContinue = true;
|
||||
|
||||
auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
|
||||
auto entry = Cursor.advance(AF_DontPopBlockAtEnd);
|
||||
if (entry.Kind != llvm::BitstreamEntry::Record)
|
||||
break;
|
||||
|
||||
scratch.clear();
|
||||
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch,
|
||||
unsigned recordID = Cursor.readRecord(entry.ID, scratch,
|
||||
&blobData);
|
||||
switch (recordID) {
|
||||
case GENERIC_PARAM: {
|
||||
@@ -1368,7 +1370,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
if (declOrOffset.isComplete())
|
||||
break;
|
||||
|
||||
auto genericParams = maybeReadGenericParams(DC);
|
||||
auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
|
||||
|
||||
auto theStruct = new (ctx) StructDecl(SourceLoc(), getIdentifier(nameID),
|
||||
SourceLoc(), { }, genericParams, DC);
|
||||
@@ -1423,7 +1425,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
if (declOrOffset.isComplete())
|
||||
break;
|
||||
|
||||
auto genericParams = maybeReadGenericParams(parent);
|
||||
auto genericParams = maybeReadGenericParams(parent, DeclTypeCursor);
|
||||
|
||||
auto ctor = new (ctx) ConstructorDecl(ctx.Id_init, SourceLoc(),
|
||||
/*argParams=*/nullptr, nullptr,
|
||||
@@ -1586,7 +1588,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
// Read generic params before reading the type, because the type may
|
||||
// reference generic parameters, and we want them to have a dummy
|
||||
// DeclContext for now.
|
||||
GenericParamList *genericParams = maybeReadGenericParams(DC);
|
||||
GenericParamList *genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
|
||||
|
||||
auto StaticSpelling = getActualStaticSpellingKind(RawStaticSpelling);
|
||||
if (!StaticSpelling.hasValue()) {
|
||||
@@ -1729,7 +1731,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
DidRecord = nullptr;
|
||||
}
|
||||
|
||||
if (auto genericParams = maybeReadGenericParams(DC)) {
|
||||
if (auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor)) {
|
||||
proto->setGenericParams(genericParams);
|
||||
SmallVector<GenericTypeParamType *, 4> paramTypes;
|
||||
for (auto &genericParam : *proto->getGenericParams()) {
|
||||
@@ -1837,7 +1839,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
if (declOrOffset.isComplete())
|
||||
break;
|
||||
|
||||
auto genericParams = maybeReadGenericParams(DC);
|
||||
auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
|
||||
|
||||
auto theClass = new (ctx) ClassDecl(SourceLoc(), getIdentifier(nameID),
|
||||
SourceLoc(), { }, genericParams, DC);
|
||||
@@ -1907,7 +1909,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
|
||||
if (declOrOffset.isComplete())
|
||||
break;
|
||||
|
||||
auto genericParams = maybeReadGenericParams(DC);
|
||||
auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor);
|
||||
|
||||
auto theEnum = new (ctx) EnumDecl(SourceLoc(), getIdentifier(nameID),
|
||||
SourceLoc(), { }, genericParams, DC);
|
||||
@@ -2608,7 +2610,7 @@ Type ModuleFile::getType(TypeID TID) {
|
||||
}
|
||||
|
||||
GenericParamList *paramList =
|
||||
maybeGetOrReadGenericParams(genericContextID, FileContext);
|
||||
maybeGetOrReadGenericParams(genericContextID, FileContext, DeclTypeCursor);
|
||||
assert(paramList && "missing generic params for polymorphic function");
|
||||
|
||||
auto Info = PolymorphicFunctionType::ExtInfo(callingConvention.getValue(),
|
||||
|
||||
@@ -352,10 +352,6 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
|
||||
unsigned rawLinkage, isTransparent;
|
||||
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, funcTyID);
|
||||
|
||||
// FIXME: DeclContext for generic params?!
|
||||
GenericParamList *contextParams
|
||||
= MF->maybeReadGenericParams(MF->getAssociatedModule());
|
||||
|
||||
if (funcTyID == 0) {
|
||||
DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n");
|
||||
return nullptr;
|
||||
@@ -395,7 +391,7 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
|
||||
} else {
|
||||
fn = SILFunction::create(SILMod, linkage.getValue(), name.str(),
|
||||
ty.castTo<SILFunctionType>(),
|
||||
contextParams, loc);
|
||||
nullptr, loc);
|
||||
fn->setTransparent(IsTransparent_t(isTransparent == 1));
|
||||
|
||||
if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), fn);
|
||||
@@ -407,10 +403,16 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
|
||||
fn->setBare(IsBare);
|
||||
if (!fn->hasLocation()) fn->setLocation(loc);
|
||||
|
||||
GenericParamList *contextParams = nullptr;
|
||||
if (!declarationOnly)
|
||||
contextParams = MF->maybeReadGenericParams(MF->getAssociatedModule(),
|
||||
SILCursor);
|
||||
|
||||
// If the next entry is the end of the block, then this function has
|
||||
// no contents.
|
||||
entry = SILCursor.advance(AF_DontPopBlockAtEnd);
|
||||
if (entry.Kind == llvm::BitstreamEntry::EndBlock) {
|
||||
assert(!contextParams && "context params without body?!");
|
||||
cacheEntry.set(fn, /*fully deserialized*/ true);
|
||||
return fn;
|
||||
}
|
||||
@@ -426,6 +428,12 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
|
||||
cacheEntry.set(fn, /*fully deserialized*/ true);
|
||||
|
||||
scratch.clear();
|
||||
|
||||
assert(!fn->getContextGenericParams()
|
||||
&& "function already has context generic params?!");
|
||||
if (contextParams)
|
||||
fn->setContextGenericParams(contextParams);
|
||||
|
||||
kind = SILCursor.readRecord(entry.ID, scratch);
|
||||
|
||||
SILBasicBlock *CurrentBB = nullptr;
|
||||
|
||||
@@ -275,7 +275,8 @@ private:
|
||||
llvm::BitstreamCursor &Cursor);
|
||||
|
||||
GenericParamList *maybeGetOrReadGenericParams(serialization::DeclID contextID,
|
||||
DeclContext *DC);
|
||||
DeclContext *DC,
|
||||
llvm::BitstreamCursor &Cursor);
|
||||
|
||||
/// Reads a set of requirements from \c DeclTypeCursor.
|
||||
void readGenericRequirements(SmallVectorImpl<Requirement> &requirements);
|
||||
@@ -455,7 +456,8 @@ public:
|
||||
///
|
||||
/// If the record at the cursor is not a generic param list, returns null
|
||||
/// without moving the cursor.
|
||||
GenericParamList *maybeReadGenericParams(DeclContext *DC);
|
||||
GenericParamList *maybeReadGenericParams(DeclContext *DC,
|
||||
llvm::BitstreamCursor &Cursor);
|
||||
|
||||
virtual ArrayRef<Decl *> loadAllMembers(const Decl *D,
|
||||
uint64_t contextData) override;
|
||||
|
||||
@@ -202,9 +202,12 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
|
||||
if (DeclOnly)
|
||||
return;
|
||||
|
||||
// Write the body's context archetypes, unless we don't actually have a body.
|
||||
if (!F.isExternalDeclaration()) {
|
||||
if (auto gp = F.getContextGenericParams()) {
|
||||
S.writeGenericParams(gp, SILAbbrCodes);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign a unique ID to each basic block of the SILFunction.
|
||||
unsigned BasicID = 0;
|
||||
|
||||
Reference in New Issue
Block a user