Skip to content

Commit d5844e5

Browse files
committed
[DI] Process type wrapper _storage before any other initialization
`_storage` is special because it emits assignments to compiler synthesized stored property `$storage`, without that `self` cannot be fully initialized.
1 parent 8d39e52 commit d5844e5

File tree

3 files changed

+69
-20
lines changed

3 files changed

+69
-20
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -539,25 +539,8 @@ ConstructorDecl *DIMemoryObjectInfo::getActorInitSelf() const {
539539
}
540540

541541
VarDecl *DIMemoryObjectInfo::getAsTypeWrapperLocalStorageVar() const {
542-
if (!MemoryInst->isVar())
543-
return nullptr;
544-
545-
if (!isa<TupleType>(getASTType()))
546-
return nullptr;
547-
548-
auto *DC = MemoryInst->getFunction()->getDeclContext();
549-
if (!DC)
550-
return nullptr;
551-
552-
auto *ctor = dyn_cast_or_null<ConstructorDecl>(DC->getAsDecl());
553-
if (!ctor || ctor->isImplicit())
554-
return nullptr;
555-
556-
if (auto *var = getLoc().getAsASTNode<VarDecl>()) {
557-
auto &ctx = var->getASTContext();
558-
if (var->isImplicit() && var->getName() == ctx.Id_localStorageVar)
559-
return var;
560-
}
542+
if (isTypeWrapperLocalStorageVar(getFunction(), MemoryInst))
543+
return getLoc().getAsASTNode<VarDecl>();
561544

562545
return nullptr;
563546
}
@@ -2015,3 +1998,32 @@ void swift::ownership::collectDIElementUsesFrom(
20151998
collector.collectFrom(MemoryInfo.getUninitializedValue(),
20161999
/*collectDestroysOfContainer*/ true);
20172000
}
2001+
2002+
bool swift::ownership::canHaveTypeWrapperLocalStorageVar(SILFunction &F) {
2003+
auto *DC = F.getDeclContext();
2004+
if (!DC)
2005+
return false;
2006+
2007+
auto *ctor = dyn_cast_or_null<ConstructorDecl>(DC->getAsDecl());
2008+
if (!ctor || ctor->isImplicit() || !ctor->isDesignatedInit())
2009+
return false;
2010+
2011+
auto *parentType = ctor->getDeclContext()->getSelfNominalTypeDecl();
2012+
return parentType && parentType->hasTypeWrapper();
2013+
}
2014+
2015+
bool swift::ownership::isTypeWrapperLocalStorageVar(
2016+
SILFunction &F, MarkUninitializedInst *Inst) {
2017+
if (!Inst->isVar())
2018+
return false;
2019+
2020+
if (!canHaveTypeWrapperLocalStorageVar(F))
2021+
return false;
2022+
2023+
if (auto *var = Inst->getLoc().getAsASTNode<VarDecl>()) {
2024+
auto &ctx = var->getASTContext();
2025+
return var->isImplicit() && var->getName() == ctx.Id_localStorageVar;
2026+
}
2027+
2028+
return false;
2029+
}

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,15 @@ struct DIElementUseInfo {
357357
void collectDIElementUsesFrom(const DIMemoryObjectInfo &MemoryInfo,
358358
DIElementUseInfo &UseInfo);
359359

360+
/// Check whether given function is a user-defined initializer of a
361+
/// type wrapped type.
362+
bool canHaveTypeWrapperLocalStorageVar(SILFunction &F);
363+
364+
/// Check whether this instruction represents `_storage` variable
365+
/// injected by type-checker into user-defined designated initializer
366+
/// of a type wrapped type.
367+
bool isTypeWrapperLocalStorageVar(SILFunction &F, MarkUninitializedInst *Inst);
368+
360369
} // end namespace ownership
361370
} // end namespace swift
362371

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,6 @@ void LifetimeChecker::doIt() {
11601160
// Insert hop_to_executor instructions for actor initializers, if needed.
11611161
injectActorHops();
11621162

1163-
11641163
// If the memory object had any non-trivial stores that are init or assign
11651164
// based on the control flow path reaching them, then insert dynamic control
11661165
// logic and CFG diamonds to handle this.
@@ -3542,6 +3541,24 @@ static void processMemoryObject(MarkUninitializedInst *I,
35423541
LifetimeChecker(MemInfo, UseInfo, blockStates).doIt();
35433542
}
35443543

3544+
static MarkUninitializedInst *findLocalTypeWrapperStorageVar(SILFunction &F) {
3545+
if (!canHaveTypeWrapperLocalStorageVar(F))
3546+
return nullptr;
3547+
3548+
auto BB = F.getEntryBlock();
3549+
if (!BB)
3550+
return nullptr;
3551+
3552+
for (auto &I : *BB) {
3553+
SILInstruction *Inst = &I;
3554+
auto *MUI = dyn_cast<MarkUninitializedInst>(Inst);
3555+
if (MUI && isTypeWrapperLocalStorageVar(F, MUI))
3556+
return MUI;
3557+
}
3558+
3559+
return nullptr;
3560+
}
3561+
35453562
/// Check that all memory objects that require initialization before use are
35463563
/// properly set and transform the code as required for flow-sensitive
35473564
/// properties.
@@ -3552,6 +3569,17 @@ static bool checkDefiniteInitialization(SILFunction &Fn) {
35523569

35533570
BlockStates blockStates(&Fn);
35543571

3572+
// Special handling of _storage variable introduced by type wrapper.
3573+
// It has to be checked first because it injects initialization of
3574+
// `self.$storage`.
3575+
if (auto *storageVar = findLocalTypeWrapperStorageVar(Fn)) {
3576+
// Then process the memory object.
3577+
processMemoryObject(storageVar, blockStates);
3578+
storageVar->replaceAllUsesWith(storageVar->getOperand());
3579+
storageVar->eraseFromParent();
3580+
Changed = true;
3581+
}
3582+
35553583
for (auto &BB : Fn) {
35563584
for (auto I = BB.begin(), E = BB.end(); I != E;) {
35573585
SILInstruction *Inst = &*I;

0 commit comments

Comments
 (0)