mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -1176,11 +1176,6 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
|
||||
|
||||
// Eagerly emit global variables that are externally visible.
|
||||
static bool isLazilyEmittedGlobalVariable(SILGlobalVariable &v, SILModule &m) {
|
||||
// FIXME: Eagerly emit statically-initialized objects due to an issue I
|
||||
// have yet to debug.
|
||||
if (v.isInitializedObject())
|
||||
return false;
|
||||
|
||||
if (v.isPossiblyUsedExternally()) {
|
||||
// Under the embedded linkage model, if it has a non-unique definition,
|
||||
// treat it lazily.
|
||||
@@ -2780,7 +2775,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
|
||||
|
||||
if (var->isInitializedObject()) {
|
||||
assert(ti.isFixedSize(expansion));
|
||||
StructLayout *Layout = StaticObjectLayouts[var].get();
|
||||
StructLayout *Layout = StaticObjectLayouts[var].layout.get();
|
||||
if (!Layout) {
|
||||
// Create the layout (includes the llvm type) for the statically
|
||||
// initialized object and store it for later.
|
||||
@@ -2791,7 +2786,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
|
||||
}
|
||||
Layout = getClassLayoutWithTailElems(*this,
|
||||
var->getLoweredType(), TailTypes);
|
||||
StaticObjectLayouts[var] = std::unique_ptr<StructLayout>(Layout);
|
||||
StaticObjectLayouts[var] = {std::unique_ptr<StructLayout>(Layout), nullptr};
|
||||
}
|
||||
storageType = Layout->getType();
|
||||
fixedSize = Layout->getSize();
|
||||
@@ -2907,7 +2902,7 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
|
||||
llvm::Type *storageType,
|
||||
Alignment alignment) {
|
||||
if (var->isInitializedObject()) {
|
||||
StructLayout *layout = StaticObjectLayouts[var].get();
|
||||
StructLayout *layout = StaticObjectLayouts[var].layout.get();
|
||||
ObjectInst *oi = cast<ObjectInst>(var->getStaticInitializerValue());
|
||||
llvm::Constant *initVal = emitConstantObject(*this, oi, layout);
|
||||
if (!canMakeStaticObjectReadOnly(var->getLoweredType())) {
|
||||
@@ -2917,13 +2912,18 @@ llvm::Constant *IRGenModule::getGlobalInitValue(SILGlobalVariable *var,
|
||||
// swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
|
||||
// HeapObject object;
|
||||
// };
|
||||
std::string typeName = storageType->getStructName().str() + 'c';
|
||||
assert(alignment >= getPointerAlignment());
|
||||
unsigned numTokens = alignment.getValue() /
|
||||
getPointerAlignment().getValue();
|
||||
auto *containerTy = llvm::StructType::create(getLLVMContext(),
|
||||
{llvm::ArrayType::get(OnceTy, numTokens), initVal->getType()},
|
||||
typeName);
|
||||
llvm::StructType *containerTy = StaticObjectLayouts[var].containerTy;
|
||||
if (!containerTy) {
|
||||
std::string typeName = storageType->getStructName().str() + 'c';
|
||||
assert(alignment >= getPointerAlignment());
|
||||
unsigned numTokens = alignment.getValue() /
|
||||
getPointerAlignment().getValue();
|
||||
containerTy = llvm::StructType::create(getLLVMContext(),
|
||||
{llvm::ArrayType::get(OnceTy, numTokens), initVal->getType()},
|
||||
typeName);
|
||||
StaticObjectLayouts[var].containerTy = containerTy;
|
||||
}
|
||||
|
||||
auto *zero = llvm::ConstantAggregateZero::get(containerTy->getElementType(0));
|
||||
initVal = llvm::ConstantStruct::get(containerTy, {zero , initVal});
|
||||
}
|
||||
|
||||
@@ -1426,8 +1426,14 @@ private:
|
||||
friend struct ::llvm::DenseMapInfo<swift::irgen::IRGenModule::FixedLayoutKey>;
|
||||
llvm::DenseMap<FixedLayoutKey, llvm::Constant *> PrivateFixedLayouts;
|
||||
|
||||
/// Captures a static object layout.
|
||||
struct StaticObjectLayout {
|
||||
std::unique_ptr<StructLayout> layout;
|
||||
llvm::StructType *containerTy = nullptr;
|
||||
};
|
||||
|
||||
/// A cache for layouts of statically initialized objects.
|
||||
llvm::DenseMap<SILGlobalVariable *, std::unique_ptr<StructLayout>>
|
||||
llvm::DenseMap<SILGlobalVariable *, StaticObjectLayout>
|
||||
StaticObjectLayouts;
|
||||
|
||||
/// A mapping from order numbers to the LLVM functions which we
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// RUN: %target-swift-frontend -parse-as-library -emit-ir -primary-file %s | %FileCheck %s
|
||||
|
||||
// REQUIRES: CPU=x86_64
|
||||
// REQUIRES: CPU=x86_64 || CPU=arm64
|
||||
|
||||
// CHECK: @"[[T:.*]]Wz" = internal global i64 0, align 8
|
||||
// CHECK: @"$s12lazy_globals1xSivp" = hidden global %TSi zeroinitializer, align 8
|
||||
// CHECK: @"$s12lazy_globals1ySivp" = hidden global %TSi zeroinitializer, align 8
|
||||
// CHECK: @"$s12lazy_globals1zSivp" = hidden global %TSi zeroinitializer, align 8
|
||||
// CHECK: @"[[T:.*]]Wz" = internal global i64 0, align 8
|
||||
|
||||
// CHECK: define internal void @"[[T]]WZ"(ptr %0) {{.*}} {
|
||||
// CHECK: entry:
|
||||
@@ -39,4 +39,3 @@ var (x, y, z) = (1, 2, 3)
|
||||
// CHECK: ret i64 [[V]]
|
||||
// CHECK: }
|
||||
func getX() -> Int { return x }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user