Skip to content

Commit bce3fa0

Browse files
committed
[IRGen] Correctly assign lazily-emitted global variables in multi-threaded IRGen
With multi-threaded IRGen, the global variables associated with "once" initialization tokens were not getting colocated with their actual global variables, which caused the initialization code to get split across different files. This issue manifest as autolinking errors in some projects. Fixes rdar://162400654.
1 parent f606979 commit bce3fa0

File tree

6 files changed

+63
-13
lines changed

6 files changed

+63
-13
lines changed

include/swift/SIL/SILGlobalVariable.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ class SILGlobalVariable
5252
/// The SIL module that the global variable belongs to.
5353
SILModule &Module;
5454

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;
55+
/// Either the declaration context of the global variable or the parent
56+
/// module in which the global variable resides.
57+
///
58+
/// The latter is only used for a deserialized global variable.
59+
llvm::PointerUnion<DeclContext *, ModuleDecl *> DeclCtxOrParentModule;
5860

5961
/// The mangled name of the variable, which will be propagated to the
6062
/// binary. A pointer into the module's lookup table.
@@ -131,13 +133,21 @@ class SILGlobalVariable
131133

132134
SILModule &getModule() const { return Module; }
133135

134-
/// Returns the module that defines this function.
136+
/// Returns the module that defines this global variable.
135137
ModuleDecl *getParentModule() const;
136138

137-
/// Sets \c ParentModule as fallback if \c DeclCtxt is not available to
138-
/// provide the parent module.
139+
/// Get the declaration context of this global variable, if it has one.
140+
DeclContext *getDeclContext() const;
141+
142+
/// Sets the parent module for a deserialized global variable.
139143
void setParentModule(ModuleDecl *module) {
140-
ParentModule = module;
144+
DeclCtxOrParentModule = module;
145+
}
146+
147+
/// Sets the declaration context for a global variable that's not anchored to
148+
/// a declaration.
149+
void setDeclContext(DeclContext *declCtx) {
150+
DeclCtxOrParentModule = declCtx;
141151
}
142152

143153
SILType getLoweredType() const { return LoweredType; }

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,8 +1561,8 @@ void IRGenerator::addLazyGlobalVariable(SILGlobalVariable *v) {
15611561
assert(!FinishedEmittingLazyDefinitions);
15621562
LazyGlobalVariables.push_back(v);
15631563

1564-
if (auto decl = v->getDecl()) {
1565-
if (decl->getDeclContext()->getParentSourceFile())
1564+
if (auto dc = v->getDeclContext()) {
1565+
if (dc->getParentSourceFile())
15661566
return;
15671567
}
15681568

lib/IRGen/IRGenModule.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,9 +2333,8 @@ IRGenModule *IRGenerator::getGenModule(SILGlobalVariable *v) {
23332333
if (found != DefaultIGMForGlobalVariable.end())
23342334
return found->second;
23352335

2336-
if (auto decl = v->getDecl()) {
2337-
return getGenModule(decl->getDeclContext());
2338-
}
2336+
if (auto *dc = v->getDeclContext())
2337+
return getGenModule(dc);
23392338

23402339
return getPrimaryIGM();
23412340
}

lib/SIL/IR/SILGlobalVariable.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,23 @@ SILGlobalVariable *SILGlobalVariable::create(SILModule &M, SILLinkage linkage,
4444
}
4545

4646
ModuleDecl *SILGlobalVariable::getParentModule() const {
47-
return ParentModule ? ParentModule : getModule().getSwiftModule();
47+
if (auto parentModule = DeclCtxOrParentModule.dyn_cast<ModuleDecl *>())
48+
return parentModule;
49+
50+
if (auto declContext = DeclCtxOrParentModule.dyn_cast<DeclContext *>())
51+
return declContext->getParentModule();
52+
53+
return getModule().getSwiftModule();
54+
}
55+
56+
DeclContext *SILGlobalVariable::getDeclContext() const {
57+
if (auto var = getDecl())
58+
return var->getDeclContext();
59+
60+
if (auto declContext = DeclCtxOrParentModule.dyn_cast<DeclContext *>())
61+
return declContext;
62+
63+
return nullptr;
4864
}
4965

5066
static bool isGlobalLet(SILModule &mod, VarDecl *decl, SILType type) {

lib/SILGen/SILGenGlobalVariable.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd,
243243
IsNotSerialized,
244244
onceTokenBuffer, onceSILTy);
245245
onceToken->setDeclaration(false);
246+
onceToken->setDeclContext(pd->getDeclContext());
246247

247248
// Emit the initialization code into a function.
248249
Mangle::ASTMangler FuncMangler(pd->getASTContext());
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
// RUN: %target-swift-frontend %t/src/A.swift %t/src/B.swift -emit-ir -o %t/A.ll -o %t/B.ll -num-threads 2 -O -g -module-name test
5+
// RUN: %FileCheck --check-prefix=CHECK-A %s <%t/A.ll
6+
// RUN: %FileCheck --check-prefix=CHECK-B %s <%t/B.ll
7+
8+
//--- A.swift
9+
10+
public func f() -> String { "hello" }
11+
12+
public func g() -> Bool {
13+
f() == X.introduction
14+
}
15+
16+
// CHECK-A: @"$s4test1XV12introduction_Wz" = external hidden global
17+
18+
//--- B.swift
19+
20+
public struct X {
21+
public static var introduction: String = f().uppercased()
22+
}
23+
24+
// CHECK-B: @"$s4test1XV12introduction_Wz" = weak_odr hidden global

0 commit comments

Comments
 (0)