Skip to content

Commit 74e85c8

Browse files
committed
[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.
1 parent 33a059f commit 74e85c8

File tree

8 files changed

+49
-12
lines changed

8 files changed

+49
-12
lines changed

include/swift/SIL/SILGlobalVariable.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ class SILGlobalVariable
5151

5252
/// The SIL module that the global variable belongs to.
5353
SILModule &Module;
54-
54+
55+
/// The module that defines this global variable. This member should only be
56+
/// when a global variable is deserialized to be emitted into another module.
57+
ModuleDecl *ParentModule = nullptr;
58+
5559
/// The mangled name of the variable, which will be propagated to the
5660
/// binary. A pointer into the module's lookup table.
5761
StringRef Name;
@@ -120,6 +124,15 @@ class SILGlobalVariable
120124

121125
SILModule &getModule() const { return Module; }
122126

127+
/// Returns the module that defines this function.
128+
ModuleDecl *getParentModule() const;
129+
130+
/// Sets \c ParentModule as fallback if \c DeclCtxt is not available to
131+
/// provide the parent module.
132+
void setParentModule(ModuleDecl *module) {
133+
ParentModule = module;
134+
}
135+
123136
SILType getLoweredType() const { return LoweredType; }
124137
CanSILFunctionType getLoweredFunctionType() const {
125138
return LoweredType.castTo<SILFunctionType>();

lib/SIL/IR/SILGlobalVariable.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ SILGlobalVariable *SILGlobalVariable::create(SILModule &M, SILLinkage linkage,
4343
return var;
4444
}
4545

46+
ModuleDecl *SILGlobalVariable::getParentModule() const {
47+
return ParentModule ? ParentModule : getModule().getSwiftModule();
48+
}
49+
4650
static bool isGlobalLet(SILModule &mod, VarDecl *decl, SILType type) {
4751
if (!decl)
4852
return false;
@@ -92,11 +96,22 @@ bool SILGlobalVariable::isPossiblyUsedExternally() const {
9296
}
9397

9498
bool SILGlobalVariable::hasNonUniqueDefinition() const {
95-
auto decl = getDecl();
96-
if (!decl)
99+
// Non-uniqueness is a property of the Embedded linkage model.
100+
auto &ctx = getModule().getASTContext();
101+
if (!ctx.LangOpts.hasFeature(Feature::Embedded))
97102
return false;
98103

99-
return SILDeclRef::declHasNonUniqueDefinition(decl);
104+
// If this is for a declaration, ask it.
105+
if (auto decl = getDecl()) {
106+
return SILDeclRef::declHasNonUniqueDefinition(decl);
107+
}
108+
109+
// If this variable is from a different module than the one we are emitting
110+
// code for, then it must have a non-unique definition.
111+
if (getParentModule() != getModule().getSwiftModule())
112+
return true;
113+
114+
return false;
100115
}
101116

102117
bool SILGlobalVariable::shouldBePreservedForDebugger() const {

lib/SILGen/SILGenGlobalVariable.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,6 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
231231
auto onceSILTy
232232
= SILType::getPrimitiveObjectType(onceTy->getCanonicalType());
233233

234-
// TODO: include the module in the onceToken's name mangling.
235-
// Then we can make it fragile.
236234
auto onceToken = SILGlobalVariable::create(M, SILLinkage::Private,
237235
IsNotSerialized,
238236
onceTokenBuffer, onceSILTy);

lib/Serialization/DeserializeSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4078,9 +4078,11 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
40784078

40794079
TypeID TyID;
40804080
DeclID dID;
4081+
ModuleID parentModuleID;
40814082
unsigned rawLinkage, serializedKind, IsDeclaration, IsLet, IsUsed;
40824083
SILGlobalVarLayout::readRecord(scratch, rawLinkage, serializedKind,
4083-
IsDeclaration, IsLet, IsUsed, TyID, dID);
4084+
IsDeclaration, IsLet, IsUsed, TyID, dID,
4085+
parentModuleID);
40844086
if (TyID == 0) {
40854087
LLVM_DEBUG(llvm::dbgs() << "SILGlobalVariable typeID is 0.\n");
40864088
return nullptr;
@@ -4115,6 +4117,9 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
41154117
globalVarOrOffset.set(v, true /*isFullyDeserialized*/);
41164118
v->setDeclaration(IsDeclaration);
41174119

4120+
if (parentModuleID)
4121+
v->setParentModule(MF->getModule(parentModuleID));
4122+
41184123
if (Callback)
41194124
Callback->didDeserialize(MF->getAssociatedModule(), v);
41204125

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 959; // Removed assign_by_wrapper SILGen instruction
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 960; // SILGlobalVariable parent module
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/SILFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ namespace sil_block {
296296
BCFixed<1>, // Is this a let variable.
297297
BCFixed<1>, // Is this marked as "used".
298298
TypeIDField,
299-
DeclIDField
299+
DeclIDField,
300+
ModuleIDField // Parent ModuleDecl *
300301
>;
301302

302303
using DifferentiabilityWitnessLayout = BCRecordLayout<

lib/Serialization/SerializeSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3114,14 +3114,19 @@ void SILSerializer::writeSILGlobalVar(const SILGlobalVariable &g) {
31143114
GlobalVarOffset.push_back(Out.GetCurrentBitNo());
31153115
TypeID TyID = S.addTypeRef(g.getLoweredType().getRawASTType());
31163116
DeclID dID = S.addDeclRef(g.getDecl());
3117+
3118+
ModuleID parentModuleID;
3119+
if (auto *parentModule = g.getParentModule())
3120+
parentModuleID = S.addModuleRef(parentModule);
3121+
31173122
SILGlobalVarLayout::emitRecord(Out, ScratchRecord,
31183123
SILAbbrCodes[SILGlobalVarLayout::Code],
31193124
toStableSILLinkage(g.getLinkage()),
31203125
(unsigned)g.getSerializedKind(),
31213126
(unsigned)!g.isDefinition(),
31223127
(unsigned)g.isLet(),
31233128
(unsigned)g.markedAsUsed(),
3124-
TyID, dID);
3129+
TyID, dID, parentModuleID);
31253130

31263131
// Don't emit the initializer instructions if not marked as "serialized".
31273132
if (!g.isAnySerialized())

test/embedded/linkage-mergeable4.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %{python} %utils/split_file.py -o %t %s
33

4-
// 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
5-
// 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
4+
// 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
5+
// 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
66
// RUN: %target-embedded-link %target-clang-resource-dir-opt %t/MainA.o %t/MainB.o %t/MyModule.o -o %t/a.out
77
// RUN: %target-run %t/a.out | %FileCheck %s
88

0 commit comments

Comments
 (0)