diff --git a/include/swift/SIL/SILGlobalVariable.h b/include/swift/SIL/SILGlobalVariable.h index acc01dda5a650..84ddda77883e0 100644 --- a/include/swift/SIL/SILGlobalVariable.h +++ b/include/swift/SIL/SILGlobalVariable.h @@ -52,9 +52,11 @@ class SILGlobalVariable /// 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; + /// Either the declaration context of the global variable or the parent + /// module in which the global variable resides. + /// + /// The latter is only used for a deserialized global variable. + llvm::PointerUnion DeclCtxOrParentModule; /// The mangled name of the variable, which will be propagated to the /// binary. A pointer into the module's lookup table. @@ -131,13 +133,21 @@ class SILGlobalVariable SILModule &getModule() const { return Module; } - /// Returns the module that defines this function. + /// Returns the module that defines this global variable. ModuleDecl *getParentModule() const; - /// Sets \c ParentModule as fallback if \c DeclCtxt is not available to - /// provide the parent module. + /// Get the declaration context of this global variable, if it has one. + DeclContext *getDeclContext() const; + + /// Sets the parent module for a deserialized global variable. void setParentModule(ModuleDecl *module) { - ParentModule = module; + DeclCtxOrParentModule = module; + } + + /// Sets the declaration context for a global variable that's not anchored to + /// a declaration. + void setDeclContext(DeclContext *declCtx) { + DeclCtxOrParentModule = declCtx; } SILType getLoweredType() const { return LoweredType; } diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index d36385a56f6fd..88c5ab46897ad 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1561,8 +1561,8 @@ void IRGenerator::addLazyGlobalVariable(SILGlobalVariable *v) { assert(!FinishedEmittingLazyDefinitions); LazyGlobalVariables.push_back(v); - if (auto decl = v->getDecl()) { - if (decl->getDeclContext()->getParentSourceFile()) + if (auto dc = v->getDeclContext()) { + if (dc->getParentSourceFile()) return; } diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 9d7512025d90c..15c8d8d72cdfb 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -2333,9 +2333,8 @@ IRGenModule *IRGenerator::getGenModule(SILGlobalVariable *v) { if (found != DefaultIGMForGlobalVariable.end()) return found->second; - if (auto decl = v->getDecl()) { - return getGenModule(decl->getDeclContext()); - } + if (auto *dc = v->getDeclContext()) + return getGenModule(dc); return getPrimaryIGM(); } diff --git a/lib/SIL/IR/SILGlobalVariable.cpp b/lib/SIL/IR/SILGlobalVariable.cpp index 8b8b5b1260b0c..2349b7702efd6 100644 --- a/lib/SIL/IR/SILGlobalVariable.cpp +++ b/lib/SIL/IR/SILGlobalVariable.cpp @@ -44,7 +44,23 @@ SILGlobalVariable *SILGlobalVariable::create(SILModule &M, SILLinkage linkage, } ModuleDecl *SILGlobalVariable::getParentModule() const { - return ParentModule ? ParentModule : getModule().getSwiftModule(); + if (auto parentModule = DeclCtxOrParentModule.dyn_cast()) + return parentModule; + + if (auto declContext = DeclCtxOrParentModule.dyn_cast()) + return declContext->getParentModule(); + + return getModule().getSwiftModule(); +} + +DeclContext *SILGlobalVariable::getDeclContext() const { + if (auto var = getDecl()) + return var->getDeclContext(); + + if (auto declContext = DeclCtxOrParentModule.dyn_cast()) + return declContext; + + return nullptr; } static bool isGlobalLet(SILModule &mod, VarDecl *decl, SILType type) { diff --git a/lib/SILGen/SILGenGlobalVariable.cpp b/lib/SILGen/SILGenGlobalVariable.cpp index 337a503bf3c7a..d1af47fcd48e7 100644 --- a/lib/SILGen/SILGenGlobalVariable.cpp +++ b/lib/SILGen/SILGenGlobalVariable.cpp @@ -243,6 +243,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd, IsNotSerialized, onceTokenBuffer, onceSILTy); onceToken->setDeclaration(false); + onceToken->setDeclContext(pd->getDeclContext()); // Emit the initialization code into a function. Mangle::ASTMangler FuncMangler(pd->getASTContext()); diff --git a/test/IRGen/multithread_global_var.swift b/test/IRGen/multithread_global_var.swift new file mode 100644 index 0000000000000..45853cccfdf28 --- /dev/null +++ b/test/IRGen/multithread_global_var.swift @@ -0,0 +1,24 @@ +// RUN: %empty-directory(%t/src) +// RUN: split-file %s %t/src + +// 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 +// RUN: %FileCheck --check-prefix=CHECK-A %s <%t/A.ll +// RUN: %FileCheck --check-prefix=CHECK-B %s <%t/B.ll + +//--- A.swift + +public func f() -> String { "hello" } + +public func g() -> Bool { + f() == X.introduction +} + +// CHECK-A: @"$s4test1XV12introduction_Wz" = external hidden global + +//--- B.swift + +public struct X { + public static var introduction: String = f().uppercased() +} + +// CHECK-B: @"$s4test1XV12introduction_Wz" = weak_odr hidden global