diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 7b7145439f4..8603a5f8a68 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -560,7 +560,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const { static std::pair -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. + 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. + 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(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); } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 458804ffa33..9554f7f5f92 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -616,7 +616,8 @@ Optional 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 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 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 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 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 ForcedContext, DidRecord = nullptr; } - if (auto genericParams = maybeReadGenericParams(DC)) { + if (auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor)) { proto->setGenericParams(genericParams); SmallVector paramTypes; for (auto &genericParam : *proto->getGenericParams()) { @@ -1837,7 +1839,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional 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 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(), diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 7f57a5c8a5a..e49a25ab238 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -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; @@ -387,7 +383,7 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID, DEBUG(llvm::dbgs() << "SILFunction type mismatch.\n"); return nullptr; } - + // Don't override the transparency or linkage of a function with // an existing declaration. @@ -395,22 +391,28 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID, } else { fn = SILFunction::create(SILMod, linkage.getValue(), name.str(), ty.castTo(), - contextParams, loc); + nullptr, loc); fn->setTransparent(IsTransparent_t(isTransparent == 1)); if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), fn); } - + assert(fn->empty() && "SILFunction to be deserialized starts being empty."); 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; } @@ -420,12 +422,18 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID, cacheEntry.set(fn, /*fully deserialized*/ false); return fn; } - + // Set the cache entry now in order to properly handle both forward // declarations and deserialization errors. 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; diff --git a/lib/Serialization/ModuleFile.h b/lib/Serialization/ModuleFile.h index 62d03d34003..7c90609bae1 100644 --- a/lib/Serialization/ModuleFile.h +++ b/lib/Serialization/ModuleFile.h @@ -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 &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 loadAllMembers(const Decl *D, uint64_t contextData) override; diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 9891a601ec8..0f7d957bdcc 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -202,8 +202,11 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { if (DeclOnly) return; - if (auto gp = F.getContextGenericParams()) { - S.writeGenericParams(gp, SILAbbrCodes); + // 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.