@@ -1174,6 +1174,21 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
11741174 return true ;
11751175}
11761176
1177+ // Eagerly emit global variables that are externally visible.
1178+ static bool isLazilyEmittedGlobalVariable (SILGlobalVariable &v, SILModule &m) {
1179+ if (v.isPossiblyUsedExternally ()) {
1180+ // Under the embedded linkage model, if it has a non-unique definition,
1181+ // treat it lazily.
1182+ if (v.hasNonUniqueDefinition () && !v.markedAsUsed ()) {
1183+ return true ;
1184+ }
1185+
1186+ return false ;
1187+ }
1188+
1189+ return true ;
1190+ }
1191+
11771192void IRGenerator::emitGlobalTopLevel (
11781193 const std::vector<std::string> &linkerDirectives) {
11791194 if (PrimaryIGM->getSILModule ().getOptions ().StopOptimizationAfterSerialization ) {
@@ -1207,6 +1222,9 @@ void IRGenerator::emitGlobalTopLevel(
12071222 createLinkerDirectiveVariable (*PrimaryIGM, directive);
12081223 }
12091224 for (SILGlobalVariable &v : PrimaryIGM->getSILModule ().getSILGlobals ()) {
1225+ if (isLazilyEmittedGlobalVariable (v, PrimaryIGM->getSILModule ()))
1226+ continue ;
1227+
12101228 Decl *decl = v.getDecl ();
12111229 CurrentIGMPtr IGM = getGenModule (decl ? decl->getDeclContext () : nullptr );
12121230 IGM->emitSILGlobalVariable (&v);
@@ -1368,6 +1386,7 @@ void IRGenerator::emitLazyDefinitions() {
13681386 !LazyExtensionDescriptors.empty () ||
13691387 !LazyFieldDescriptors.empty () ||
13701388 !LazyFunctionDefinitions.empty () || !LazyWitnessTables.empty () ||
1389+ !LazyGlobalVariables.empty () ||
13711390 !LazyCanonicalSpecializedMetadataAccessors.empty () ||
13721391 !LazyMetadataAccessors.empty () ||
13731392 !LazyClassMetadata.empty () ||
@@ -1456,6 +1475,13 @@ void IRGenerator::emitLazyDefinitions() {
14561475 IGM->emitSILFunction (f);
14571476 }
14581477
1478+ // Emit any lazy global variables we require.
1479+ while (!LazyGlobalVariables.empty ()) {
1480+ SILGlobalVariable *v = LazyGlobalVariables.pop_back_val ();
1481+ CurrentIGMPtr IGM = getGenModule (v);
1482+ IGM->emitSILGlobalVariable (v);
1483+ }
1484+
14591485 while (!LazyCanonicalSpecializedMetadataAccessors.empty ()) {
14601486 CanType theType =
14611487 LazyCanonicalSpecializedMetadataAccessors.pop_back_val ();
@@ -1529,6 +1555,26 @@ void IRGenerator::addLazyFunction(SILFunction *f) {
15291555 DefaultIGMForFunction.insert (std::make_pair (f, CurrentIGM));
15301556}
15311557
1558+ void IRGenerator::addLazyGlobalVariable (SILGlobalVariable *v) {
1559+ // Add it to the queue if it hasn't already been put there.
1560+ if (!LazilyEmittedGlobalVariables.insert (v).second )
1561+ return ;
1562+
1563+ assert (!FinishedEmittingLazyDefinitions);
1564+ LazyGlobalVariables.push_back (v);
1565+
1566+ if (auto decl = v->getDecl ()) {
1567+ if (decl->getDeclContext ()->getParentSourceFile ())
1568+ return ;
1569+ }
1570+
1571+ if (CurrentIGM == nullptr )
1572+ return ;
1573+
1574+ // Don't update the map if we already have an entry.
1575+ DefaultIGMForGlobalVariable.insert (std::make_pair (v, CurrentIGM));
1576+ }
1577+
15321578bool IRGenerator::hasLazyMetadata (TypeDecl *type) {
15331579 assert (isa<NominalTypeDecl>(type) ||
15341580 isa<OpaqueTypeDecl>(type));
@@ -2714,6 +2760,9 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
27142760 auto alignment =
27152761 Alignment (getClangASTContext ().getDeclAlign (clangDecl).getQuantity ());
27162762 return Address (addr, ti.getStorageType (), alignment);
2763+ } else if (!forDefinition &&
2764+ isLazilyEmittedGlobalVariable (*var, getSILModule ())) {
2765+ IRGen.addLazyGlobalVariable (var);
27172766 }
27182767
27192768 ResilienceExpansion expansion = getResilienceExpansionForLayout (var);
@@ -2726,7 +2775,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
27262775
27272776 if (var->isInitializedObject ()) {
27282777 assert (ti.isFixedSize (expansion));
2729- StructLayout *Layout = StaticObjectLayouts[var].get ();
2778+ StructLayout *Layout = StaticObjectLayouts[var].layout . get ();
27302779 if (!Layout) {
27312780 // Create the layout (includes the llvm type) for the statically
27322781 // initialized object and store it for later.
@@ -2737,7 +2786,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
27372786 }
27382787 Layout = getClassLayoutWithTailElems (*this ,
27392788 var->getLoweredType (), TailTypes);
2740- StaticObjectLayouts[var] = std::unique_ptr<StructLayout>(Layout);
2789+ StaticObjectLayouts[var] = { std::unique_ptr<StructLayout>(Layout), nullptr } ;
27412790 }
27422791 storageType = Layout->getType ();
27432792 fixedSize = Layout->getSize ();
@@ -2853,7 +2902,7 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
28532902 llvm::Type *storageType,
28542903 Alignment alignment) {
28552904 if (var->isInitializedObject ()) {
2856- StructLayout *layout = StaticObjectLayouts[var].get ();
2905+ StructLayout *layout = StaticObjectLayouts[var].layout . get ();
28572906 ObjectInst *oi = cast<ObjectInst>(var->getStaticInitializerValue ());
28582907 llvm::Constant *initVal = emitConstantObject (*this , oi, layout);
28592908 if (!canMakeStaticObjectReadOnly (var->getLoweredType ())) {
@@ -2863,13 +2912,18 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
28632912 // swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
28642913 // HeapObject object;
28652914 // };
2866- std::string typeName = storageType->getStructName ().str () + ' c' ;
2867- assert (alignment >= getPointerAlignment ());
2868- unsigned numTokens = alignment.getValue () /
2869- getPointerAlignment ().getValue ();
2870- auto *containerTy = llvm::StructType::create (getLLVMContext (),
2871- {llvm::ArrayType::get (OnceTy, numTokens), initVal->getType ()},
2872- typeName);
2915+ llvm::StructType *containerTy = StaticObjectLayouts[var].containerTy ;
2916+ if (!containerTy) {
2917+ std::string typeName = storageType->getStructName ().str () + ' c' ;
2918+ assert (alignment >= getPointerAlignment ());
2919+ unsigned numTokens = alignment.getValue () /
2920+ getPointerAlignment ().getValue ();
2921+ containerTy = llvm::StructType::create (getLLVMContext (),
2922+ {llvm::ArrayType::get (OnceTy, numTokens), initVal->getType ()},
2923+ typeName);
2924+ StaticObjectLayouts[var].containerTy = containerTy;
2925+ }
2926+
28732927 auto *zero = llvm::ConstantAggregateZero::get (containerTy->getElementType (0 ));
28742928 initVal = llvm::ConstantStruct::get (containerTy, {zero , initVal});
28752929 }
0 commit comments