@@ -1174,6 +1174,21 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
1174
1174
return true ;
1175
1175
}
1176
1176
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
+
1177
1192
void IRGenerator::emitGlobalTopLevel (
1178
1193
const std::vector<std::string> &linkerDirectives) {
1179
1194
if (PrimaryIGM->getSILModule ().getOptions ().StopOptimizationAfterSerialization ) {
@@ -1207,6 +1222,9 @@ void IRGenerator::emitGlobalTopLevel(
1207
1222
createLinkerDirectiveVariable (*PrimaryIGM, directive);
1208
1223
}
1209
1224
for (SILGlobalVariable &v : PrimaryIGM->getSILModule ().getSILGlobals ()) {
1225
+ if (isLazilyEmittedGlobalVariable (v, PrimaryIGM->getSILModule ()))
1226
+ continue ;
1227
+
1210
1228
Decl *decl = v.getDecl ();
1211
1229
CurrentIGMPtr IGM = getGenModule (decl ? decl->getDeclContext () : nullptr );
1212
1230
IGM->emitSILGlobalVariable (&v);
@@ -1368,6 +1386,7 @@ void IRGenerator::emitLazyDefinitions() {
1368
1386
!LazyExtensionDescriptors.empty () ||
1369
1387
!LazyFieldDescriptors.empty () ||
1370
1388
!LazyFunctionDefinitions.empty () || !LazyWitnessTables.empty () ||
1389
+ !LazyGlobalVariables.empty () ||
1371
1390
!LazyCanonicalSpecializedMetadataAccessors.empty () ||
1372
1391
!LazyMetadataAccessors.empty () ||
1373
1392
!LazyClassMetadata.empty () ||
@@ -1456,6 +1475,13 @@ void IRGenerator::emitLazyDefinitions() {
1456
1475
IGM->emitSILFunction (f);
1457
1476
}
1458
1477
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
+
1459
1485
while (!LazyCanonicalSpecializedMetadataAccessors.empty ()) {
1460
1486
CanType theType =
1461
1487
LazyCanonicalSpecializedMetadataAccessors.pop_back_val ();
@@ -1529,6 +1555,26 @@ void IRGenerator::addLazyFunction(SILFunction *f) {
1529
1555
DefaultIGMForFunction.insert (std::make_pair (f, CurrentIGM));
1530
1556
}
1531
1557
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
+
1532
1578
bool IRGenerator::hasLazyMetadata (TypeDecl *type) {
1533
1579
assert (isa<NominalTypeDecl>(type) ||
1534
1580
isa<OpaqueTypeDecl>(type));
@@ -2714,6 +2760,9 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
2714
2760
auto alignment =
2715
2761
Alignment (getClangASTContext ().getDeclAlign (clangDecl).getQuantity ());
2716
2762
return Address (addr, ti.getStorageType (), alignment);
2763
+ } else if (!forDefinition &&
2764
+ isLazilyEmittedGlobalVariable (*var, getSILModule ())) {
2765
+ IRGen.addLazyGlobalVariable (var);
2717
2766
}
2718
2767
2719
2768
ResilienceExpansion expansion = getResilienceExpansionForLayout (var);
@@ -2726,7 +2775,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
2726
2775
2727
2776
if (var->isInitializedObject ()) {
2728
2777
assert (ti.isFixedSize (expansion));
2729
- StructLayout *Layout = StaticObjectLayouts[var].get ();
2778
+ StructLayout *Layout = StaticObjectLayouts[var].layout . get ();
2730
2779
if (!Layout) {
2731
2780
// Create the layout (includes the llvm type) for the statically
2732
2781
// initialized object and store it for later.
@@ -2737,7 +2786,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
2737
2786
}
2738
2787
Layout = getClassLayoutWithTailElems (*this ,
2739
2788
var->getLoweredType (), TailTypes);
2740
- StaticObjectLayouts[var] = std::unique_ptr<StructLayout>(Layout);
2789
+ StaticObjectLayouts[var] = { std::unique_ptr<StructLayout>(Layout), nullptr } ;
2741
2790
}
2742
2791
storageType = Layout->getType ();
2743
2792
fixedSize = Layout->getSize ();
@@ -2853,7 +2902,7 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
2853
2902
llvm::Type *storageType,
2854
2903
Alignment alignment) {
2855
2904
if (var->isInitializedObject ()) {
2856
- StructLayout *layout = StaticObjectLayouts[var].get ();
2905
+ StructLayout *layout = StaticObjectLayouts[var].layout . get ();
2857
2906
ObjectInst *oi = cast<ObjectInst>(var->getStaticInitializerValue ());
2858
2907
llvm::Constant *initVal = emitConstantObject (*this , oi, layout);
2859
2908
if (!canMakeStaticObjectReadOnly (var->getLoweredType ())) {
@@ -2863,13 +2912,18 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
2863
2912
// swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
2864
2913
// HeapObject object;
2865
2914
// };
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
+
2873
2927
auto *zero = llvm::ConstantAggregateZero::get (containerTy->getElementType (0 ));
2874
2928
initVal = llvm::ConstantStruct::get (containerTy, {zero , initVal});
2875
2929
}
0 commit comments