mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[SIL] Track the parent module of a SIL global variable through serialization
As with SIL functions, track the parent module where a SIL global variable was originally defined so that we can determine whether we are outside of its original module for linkage purposes. Use this to make sure we emit via a weak definition when emitting to a module other than the originating module. Fixes rdar://160153163.
This commit is contained in:
@@ -51,7 +51,11 @@ private:
|
||||
|
||||
/// The SIL module that the global variable belongs to.
|
||||
SILModule &Module;
|
||||
|
||||
|
||||
/// The module that defines this global variable. This member should only be
|
||||
/// when a global variable is deserialized to be emitted into another module.
|
||||
ModuleDecl *ParentModule = nullptr;
|
||||
|
||||
/// The mangled name of the variable, which will be propagated to the
|
||||
/// binary. A pointer into the module's lookup table.
|
||||
StringRef Name;
|
||||
@@ -120,6 +124,15 @@ public:
|
||||
|
||||
SILModule &getModule() const { return Module; }
|
||||
|
||||
/// Returns the module that defines this function.
|
||||
ModuleDecl *getParentModule() const;
|
||||
|
||||
/// Sets \c ParentModule as fallback if \c DeclCtxt is not available to
|
||||
/// provide the parent module.
|
||||
void setParentModule(ModuleDecl *module) {
|
||||
ParentModule = module;
|
||||
}
|
||||
|
||||
SILType getLoweredType() const { return LoweredType; }
|
||||
CanSILFunctionType getLoweredFunctionType() const {
|
||||
return LoweredType.castTo<SILFunctionType>();
|
||||
|
||||
@@ -43,6 +43,10 @@ SILGlobalVariable *SILGlobalVariable::create(SILModule &M, SILLinkage linkage,
|
||||
return var;
|
||||
}
|
||||
|
||||
ModuleDecl *SILGlobalVariable::getParentModule() const {
|
||||
return ParentModule ? ParentModule : getModule().getSwiftModule();
|
||||
}
|
||||
|
||||
static bool isGlobalLet(SILModule &mod, VarDecl *decl, SILType type) {
|
||||
if (!decl)
|
||||
return false;
|
||||
@@ -92,11 +96,22 @@ bool SILGlobalVariable::isPossiblyUsedExternally() const {
|
||||
}
|
||||
|
||||
bool SILGlobalVariable::hasNonUniqueDefinition() const {
|
||||
auto decl = getDecl();
|
||||
if (!decl)
|
||||
// Non-uniqueness is a property of the Embedded linkage model.
|
||||
auto &ctx = getModule().getASTContext();
|
||||
if (!ctx.LangOpts.hasFeature(Feature::Embedded))
|
||||
return false;
|
||||
|
||||
return SILDeclRef::declHasNonUniqueDefinition(decl);
|
||||
// If this is for a declaration, ask it.
|
||||
if (auto decl = getDecl()) {
|
||||
return SILDeclRef::declHasNonUniqueDefinition(decl);
|
||||
}
|
||||
|
||||
// If this variable is from a different module than the one we are emitting
|
||||
// code for, then it must have a non-unique definition.
|
||||
if (getParentModule() != getModule().getSwiftModule())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SILGlobalVariable::shouldBePreservedForDebugger() const {
|
||||
|
||||
@@ -231,8 +231,6 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
|
||||
auto onceSILTy
|
||||
= SILType::getPrimitiveObjectType(onceTy->getCanonicalType());
|
||||
|
||||
// TODO: include the module in the onceToken's name mangling.
|
||||
// Then we can make it fragile.
|
||||
auto onceToken = SILGlobalVariable::create(M, SILLinkage::Private,
|
||||
IsNotSerialized,
|
||||
onceTokenBuffer, onceSILTy);
|
||||
|
||||
@@ -4078,9 +4078,11 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
|
||||
|
||||
TypeID TyID;
|
||||
DeclID dID;
|
||||
ModuleID parentModuleID;
|
||||
unsigned rawLinkage, serializedKind, IsDeclaration, IsLet, IsUsed;
|
||||
SILGlobalVarLayout::readRecord(scratch, rawLinkage, serializedKind,
|
||||
IsDeclaration, IsLet, IsUsed, TyID, dID);
|
||||
IsDeclaration, IsLet, IsUsed, TyID, dID,
|
||||
parentModuleID);
|
||||
if (TyID == 0) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "SILGlobalVariable typeID is 0.\n");
|
||||
return nullptr;
|
||||
@@ -4115,6 +4117,9 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
|
||||
globalVarOrOffset.set(v, true /*isFullyDeserialized*/);
|
||||
v->setDeclaration(IsDeclaration);
|
||||
|
||||
if (parentModuleID)
|
||||
v->setParentModule(MF->getModule(parentModuleID));
|
||||
|
||||
if (Callback)
|
||||
Callback->didDeserialize(MF->getAssociatedModule(), v);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
|
||||
/// 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.
|
||||
/// Don't worry about adhering to the 80-column limit for this line.
|
||||
const uint16_t SWIFTMODULE_VERSION_MINOR = 959; // Removed assign_by_wrapper SILGen instruction
|
||||
const uint16_t SWIFTMODULE_VERSION_MINOR = 960; // SILGlobalVariable parent module
|
||||
|
||||
/// A standard hash seed used for all string hashes in a serialized module.
|
||||
///
|
||||
|
||||
@@ -296,7 +296,8 @@ namespace sil_block {
|
||||
BCFixed<1>, // Is this a let variable.
|
||||
BCFixed<1>, // Is this marked as "used".
|
||||
TypeIDField,
|
||||
DeclIDField
|
||||
DeclIDField,
|
||||
ModuleIDField // Parent ModuleDecl *
|
||||
>;
|
||||
|
||||
using DifferentiabilityWitnessLayout = BCRecordLayout<
|
||||
|
||||
@@ -3114,6 +3114,11 @@ void SILSerializer::writeSILGlobalVar(const SILGlobalVariable &g) {
|
||||
GlobalVarOffset.push_back(Out.GetCurrentBitNo());
|
||||
TypeID TyID = S.addTypeRef(g.getLoweredType().getRawASTType());
|
||||
DeclID dID = S.addDeclRef(g.getDecl());
|
||||
|
||||
ModuleID parentModuleID;
|
||||
if (auto *parentModule = g.getParentModule())
|
||||
parentModuleID = S.addModuleRef(parentModule);
|
||||
|
||||
SILGlobalVarLayout::emitRecord(Out, ScratchRecord,
|
||||
SILAbbrCodes[SILGlobalVarLayout::Code],
|
||||
toStableSILLinkage(g.getLinkage()),
|
||||
@@ -3121,7 +3126,7 @@ void SILSerializer::writeSILGlobalVar(const SILGlobalVariable &g) {
|
||||
(unsigned)!g.isDefinition(),
|
||||
(unsigned)g.isLet(),
|
||||
(unsigned)g.markedAsUsed(),
|
||||
TyID, dID);
|
||||
TyID, dID, parentModuleID);
|
||||
|
||||
// Don't emit the initializer instructions if not marked as "serialized".
|
||||
if (!g.isAnySerialized())
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %{python} %utils/split_file.py -o %t %s
|
||||
|
||||
// RUN: %target-swift-frontend -mergeable-symbols -num-threads 2 -O -c -emit-module -o %t/MyModule.o %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library
|
||||
// RUN: %target-swift-frontend -mergeable-symbols -num-threads 2 -O -c -o %t/MainA.o -o %t/MainB.o %t/MainA.swift %t/MainB.swift -I %t -enable-experimental-feature Embedded -parse-as-library
|
||||
// RUN: %target-swift-frontend -num-threads 2 -O -c -emit-module -o %t/MyModule.o %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library
|
||||
// RUN: %target-swift-frontend -num-threads 2 -O -c -o %t/MainA.o -o %t/MainB.o %t/MainA.swift %t/MainB.swift -I %t -enable-experimental-feature Embedded -parse-as-library
|
||||
// RUN: %target-embedded-link %target-clang-resource-dir-opt %t/MainA.o %t/MainB.o %t/MyModule.o -o %t/a.out
|
||||
// RUN: %target-run %t/a.out | %FileCheck %s
|
||||
|
||||
|
||||
Reference in New Issue
Block a user