Skip to content

[DI] Add a way to find value of self in initializer context #61206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,25 @@ SILInstruction *DIMemoryObjectInfo::getFunctionEntryPoint() const {
return &*getFunction().begin()->begin();
}

static SingleValueInstruction *
getUninitializedValue(MarkUninitializedInst *MemoryInst) {
SILValue inst = MemoryInst;
if (auto *bbi = MemoryInst->getSingleUserOfType<BeginBorrowInst>()) {
inst = bbi;
}

if (SingleValueInstruction *svi =
inst->getSingleUserOfType<ProjectBoxInst>()) {
return svi;
}

return MemoryInst;
}

SingleValueInstruction *DIMemoryObjectInfo::getUninitializedValue() const {
return ::getUninitializedValue(MemoryInst);
}

/// Given a symbolic element number, return the type of the element.
static SILType getElementTypeRec(TypeExpansionContext context,
SILModule &Module, SILType T, unsigned EltNo,
Expand Down Expand Up @@ -478,6 +497,31 @@ bool DIMemoryObjectInfo::isElementLetProperty(unsigned Element) const {
return false;
}

SingleValueInstruction *DIMemoryObjectInfo::findUninitializedSelfValue() const {
// If the object is 'self', return its uninitialized value.
if (isAnyInitSelf())
return getUninitializedValue();

// Otherwise we need to scan entry block to find mark_uninitialized
// instruction that belongs to `self`.

auto *BB = getFunction().getEntryBlock();
if (!BB)
return nullptr;

for (auto &I : *BB) {
SILInstruction *Inst = &I;
if (auto *MUI = dyn_cast<MarkUninitializedInst>(Inst)) {
// If instruction is not a local variable, it could only
// be some kind of `self` (root, delegating, derived etc.)
// see \c MarkUninitializedInst::Kind for more details.
if (!MUI->isVar())
return ::getUninitializedValue(MUI);
}
}
return nullptr;
}

ConstructorDecl *DIMemoryObjectInfo::getActorInitSelf() const {
// is it 'self'?
if (!MemoryInst->isVar())
Expand Down
18 changes: 5 additions & 13 deletions lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,7 @@ class DIMemoryObjectInfo {
/// alloc_stack, this always just returns the actual mark_uninitialized
/// instruction. For alloc_box though it returns the project_box associated
/// with the memory info.
SingleValueInstruction *getUninitializedValue() const {
if (IsBox) {
SILValue inst = MemoryInst;
if (auto *bbi = MemoryInst->getSingleUserOfType<BeginBorrowInst>()) {
inst = bbi;
}
// TODO: consider just storing the ProjectBoxInst in this case.
SingleValueInstruction *svi = inst->getSingleUserOfType<ProjectBoxInst>();
assert(svi);
return svi;
}
return MemoryInst;
}
SingleValueInstruction *getUninitializedValue() const;

/// Return the number of elements, without the extra "super.init" tracker in
/// initializers of derived classes.
Expand All @@ -130,6 +118,10 @@ class DIMemoryObjectInfo {
/// Return true if this is 'self' in any kind of initializer.
bool isAnyInitSelf() const { return !MemoryInst->isVar(); }

/// Return uninitialized value of 'self' if current memory object
/// is located in an initializer (of any kind).
SingleValueInstruction *findUninitializedSelfValue() const;

/// True if the memory object is the 'self' argument of a struct initializer.
bool isStructInitSelf() const {
if (MemoryInst->isRootSelf() || MemoryInst->isCrossModuleRootSelf()) {
Expand Down