Skip to content

Commit dbc30dc

Browse files
committed
[IRGen] Cache the layout of the LLVM struct type for statically-initialized objects
Lazy emission of SIL global variables caused us to go through the creation of two different LLVM struct types for the same initialization, tripping an assertion in LLVM. Cache it along with other information about the static-initialized object rather than rebuilding it. Also fix the lazy_globals test to account for the laziness, generalizing it to also run on arm64 so I won't miss it locally.
1 parent 4009814 commit dbc30dc

File tree

3 files changed

+24
-19
lines changed

3 files changed

+24
-19
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,11 +1176,6 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
11761176

11771177
// Eagerly emit global variables that are externally visible.
11781178
static bool isLazilyEmittedGlobalVariable(SILGlobalVariable &v, SILModule &m) {
1179-
// FIXME: Eagerly emit statically-initialized objects due to an issue I
1180-
// have yet to debug.
1181-
if (v.isInitializedObject())
1182-
return false;
1183-
11841179
if (v.isPossiblyUsedExternally()) {
11851180
// Under the embedded linkage model, if it has a non-unique definition,
11861181
// treat it lazily.
@@ -2780,7 +2775,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
27802775

27812776
if (var->isInitializedObject()) {
27822777
assert(ti.isFixedSize(expansion));
2783-
StructLayout *Layout = StaticObjectLayouts[var].get();
2778+
StructLayout *Layout = StaticObjectLayouts[var].layout.get();
27842779
if (!Layout) {
27852780
// Create the layout (includes the llvm type) for the statically
27862781
// initialized object and store it for later.
@@ -2791,7 +2786,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
27912786
}
27922787
Layout = getClassLayoutWithTailElems(*this,
27932788
var->getLoweredType(), TailTypes);
2794-
StaticObjectLayouts[var] = std::unique_ptr<StructLayout>(Layout);
2789+
StaticObjectLayouts[var] = {std::unique_ptr<StructLayout>(Layout), nullptr};
27952790
}
27962791
storageType = Layout->getType();
27972792
fixedSize = Layout->getSize();
@@ -2907,7 +2902,7 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
29072902
llvm::Type *storageType,
29082903
Alignment alignment) {
29092904
if (var->isInitializedObject()) {
2910-
StructLayout *layout = StaticObjectLayouts[var].get();
2905+
StructLayout *layout = StaticObjectLayouts[var].layout.get();
29112906
ObjectInst *oi = cast<ObjectInst>(var->getStaticInitializerValue());
29122907
llvm::Constant *initVal = emitConstantObject(*this, oi, layout);
29132908
if (!canMakeStaticObjectReadOnly(var->getLoweredType())) {
@@ -2917,13 +2912,18 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
29172912
// swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
29182913
// HeapObject object;
29192914
// };
2920-
std::string typeName = storageType->getStructName().str() + 'c';
2921-
assert(alignment >= getPointerAlignment());
2922-
unsigned numTokens = alignment.getValue() /
2923-
getPointerAlignment().getValue();
2924-
auto *containerTy = llvm::StructType::create(getLLVMContext(),
2925-
{llvm::ArrayType::get(OnceTy, numTokens), initVal->getType()},
2926-
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+
29272927
auto *zero = llvm::ConstantAggregateZero::get(containerTy->getElementType(0));
29282928
initVal = llvm::ConstantStruct::get(containerTy, {zero , initVal});
29292929
}

lib/IRGen/IRGenModule.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1426,8 +1426,14 @@ class IRGenModule {
14261426
friend struct ::llvm::DenseMapInfo<swift::irgen::IRGenModule::FixedLayoutKey>;
14271427
llvm::DenseMap<FixedLayoutKey, llvm::Constant *> PrivateFixedLayouts;
14281428

1429+
/// Captures a static object layout.
1430+
struct StaticObjectLayout {
1431+
std::unique_ptr<StructLayout> layout;
1432+
llvm::StructType *containerTy = nullptr;
1433+
};
1434+
14291435
/// A cache for layouts of statically initialized objects.
1430-
llvm::DenseMap<SILGlobalVariable *, std::unique_ptr<StructLayout>>
1436+
llvm::DenseMap<SILGlobalVariable *, StaticObjectLayout>
14311437
StaticObjectLayouts;
14321438

14331439
/// A mapping from order numbers to the LLVM functions which we

test/IRGen/lazy_globals.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// RUN: %target-swift-frontend -parse-as-library -emit-ir -primary-file %s | %FileCheck %s
22

3-
// REQUIRES: CPU=x86_64
3+
// REQUIRES: CPU=x86_64 || CPU=arm64
44

5-
// CHECK: @"[[T:.*]]Wz" = internal global i64 0, align 8
65
// CHECK: @"$s12lazy_globals1xSivp" = hidden global %TSi zeroinitializer, align 8
76
// CHECK: @"$s12lazy_globals1ySivp" = hidden global %TSi zeroinitializer, align 8
87
// CHECK: @"$s12lazy_globals1zSivp" = hidden global %TSi zeroinitializer, align 8
8+
// CHECK: @"[[T:.*]]Wz" = internal global i64 0, align 8
99

1010
// CHECK: define internal void @"[[T]]WZ"(ptr %0) {{.*}} {
1111
// CHECK: entry:
@@ -39,4 +39,3 @@ var (x, y, z) = (1, 2, 3)
3939
// CHECK: ret i64 [[V]]
4040
// CHECK: }
4141
func getX() -> Int { return x }
42-

0 commit comments

Comments
 (0)