Skip to content

Completely refactor class constructor initialization for ownership #7714

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
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
4 changes: 4 additions & 0 deletions include/swift/SIL/SILValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ struct ValueOwnershipKind {
operator innerty() const { return Value; }

Optional<ValueOwnershipKind> merge(ValueOwnershipKind RHS) const;

bool isTrivialOr(ValueOwnershipKind Kind) const {
return Value == Trivial || Value == Kind;
}
};

llvm::raw_ostream &operator<<(llvm::raw_ostream &os, ValueOwnershipKind Kind);
Expand Down
6 changes: 5 additions & 1 deletion lib/SILGen/Cleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ CleanupStateRestorationScope::pushCurrentCleanupState(CleanupHandle handle) {
SavedStates.push_back({handle, oldState});
}

void CleanupStateRestorationScope::pop() {
void CleanupStateRestorationScope::popImpl() {
// Restore cleanup states in the opposite order in which we saved them.
for (auto i = SavedStates.rbegin(), e = SavedStates.rend(); i != e; ++i) {
CleanupHandle handle = i->first;
Expand All @@ -231,8 +231,12 @@ void CleanupStateRestorationScope::pop() {
"changing state of dead cleanup");
cleanup.setState(Cleanups.Gen, stateToRestore);
}

SavedStates.clear();
}

void CleanupStateRestorationScope::pop() && { popImpl(); }

llvm::raw_ostream &Lowering::operator<<(llvm::raw_ostream &os,
CleanupState state) {
switch (state) {
Expand Down
9 changes: 5 additions & 4 deletions lib/SILGen/Cleanup.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,12 @@ class CleanupStateRestorationScope {
/// Just remember whatever the current state of the given cleanup is.
void pushCurrentCleanupState(CleanupHandle handle);

void pop();
void pop() &&;

~CleanupStateRestorationScope() {
pop();
}
~CleanupStateRestorationScope() { popImpl(); }

private:
void popImpl();
};

} // end namespace Lowering
Expand Down
9 changes: 9 additions & 0 deletions lib/SILGen/JumpDest.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ class LLVM_LIBRARY_VISIBILITY JumpDest {
CleanupsDepth getDepth() const { return Depth; }
CleanupLocation getCleanupLocation() const { return CleanupLoc; }

JumpDest translate(CleanupsDepth NewDepth) && {
JumpDest NewValue(Block, NewDepth, CleanupLoc);
Block = nullptr;
Depth = CleanupsDepth::invalid();
// Null location.
CleanupLoc = CleanupLocation::get(ArtificialUnreachableLocation());
return NewValue;
}

bool isValid() const { return Block != nullptr; }
static JumpDest invalid() {
return JumpDest(CleanupLocation((Expr*) nullptr));
Expand Down
5 changes: 3 additions & 2 deletions lib/SILGen/RValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
//
//===----------------------------------------------------------------------===//

#include "Initialization.h"
#include "RValue.h"
#include "Initialization.h"
#include "SILGenFunction.h"
#include "swift/AST/CanTypeVisitor.h"
#include "swift/SIL/AbstractionPattern.h"
#include "swift/SIL/SILArgument.h"
#include "swift/AST/CanTypeVisitor.h"

using namespace swift;
using namespace Lowering;
Expand Down
5 changes: 3 additions & 2 deletions lib/SILGen/RValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
#define SWIFT_LOWERING_RVALUE_H

#include "ManagedValue.h"
#include "SILGenFunction.h"
#include "llvm/ADT/SmallVector.h"

namespace swift {
namespace Lowering {
class Initialization;

class Initialization;
class SILGenFunction;

/// An "exploded" SIL rvalue, in which tuple values are recursively
/// destructured. (In SILGen we don't try to explode structs, because doing so
Expand Down
47 changes: 40 additions & 7 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
void applySuper(ApplyExpr *apply) {
// Load the 'super' argument.
Expr *arg = apply->getArg();
ManagedValue super = SGF.emitRValueAsSingleValue(arg);
ManagedValue super;

// The callee for a super call has to be either a method or constructor.
Expr *fn = apply->getFn();
Expand All @@ -1296,6 +1296,27 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {

if (ctorRef->getDeclRef().isSpecialized())
substitutions = ctorRef->getDeclRef().getSubstitutions();

assert(SGF.SelfInitDelegationState ==
SILGenFunction::WillSharedBorrowSelf);
SGF.SelfInitDelegationState = SILGenFunction::WillExclusiveBorrowSelf;
super = SGF.emitRValueAsSingleValue(arg);
assert(SGF.SelfInitDelegationState ==
SILGenFunction::DidExclusiveBorrowSelf);

// Check if super is not the same as our base type. This means that we
// performed an upcast. Set SuperInitDelegationState to super.
if (super.getValue() != SGF.InitDelegationSelf.getValue()) {
assert(super.getCleanup() == SGF.InitDelegationSelf.getCleanup());
SILValue underlyingSelf = SGF.InitDelegationSelf.forward(SGF);
SGF.InitDelegationSelf = ManagedValue::forUnmanaged(underlyingSelf);
CleanupHandle newWriteback = SGF.enterDelegateInitSelfWritebackCleanup(
SGF.InitDelegationLoc.getValue(), SGF.InitDelegationSelfBox,
super.getValue());
SGF.SuperInitDelegationSelf =
ManagedValue(super.getValue(), newWriteback);
super = SGF.SuperInitDelegationSelf;
}
} else if (auto *declRef = dyn_cast<DeclRefExpr>(fn)) {
assert(isa<FuncDecl>(declRef->getDecl()) && "non-function super call?!");
constant = SILDeclRef(declRef->getDecl(),
Expand All @@ -1305,8 +1326,10 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {

if (declRef->getDeclRef().isSpecialized())
substitutions = declRef->getDeclRef().getSubstitutions();
} else
super = SGF.emitRValueAsSingleValue(arg);
} else {
llvm_unreachable("invalid super callee");
}

CanType superFormalType = arg->getType()->getCanonicalType();
setSelfParam(ArgumentSource(arg, RValue(SGF, apply, superFormalType, super)),
Expand Down Expand Up @@ -1432,14 +1455,14 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {

// If the initializer is a C function imported as a member,
// there is no 'self' parameter. Mark it undef.
if (ctorRef->getDecl()->isImportAsMember())
if (ctorRef->getDecl()->isImportAsMember()) {
self = SGF.emitUndef(expr, selfFormalType);
else if (SGF.AllocatorMetatype)
} else if (SGF.AllocatorMetatype) {
self = emitCorrespondingSelfValue(
ManagedValue::forUnmanaged(SGF.AllocatorMetatype),
arg);
else
ManagedValue::forUnmanaged(SGF.AllocatorMetatype), arg);
} else {
self = ManagedValue::forUnmanaged(SGF.emitMetatypeOfValue(expr, arg));
}
} else {
// If we're in a protocol extension initializer, we haven't allocated
// "self" yet at this point. Do so. Use alloc_ref_dynamic since we should
Expand All @@ -1455,7 +1478,12 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
// Perform any adjustments needed to 'self'.
self = emitCorrespondingSelfValue(self, arg);
} else {
assert(SGF.SelfInitDelegationState ==
SILGenFunction::WillSharedBorrowSelf);
SGF.SelfInitDelegationState = SILGenFunction::WillExclusiveBorrowSelf;
self = SGF.emitRValueAsSingleValue(arg);
assert(SGF.SelfInitDelegationState ==
SILGenFunction::DidExclusiveBorrowSelf);
}
}

Expand Down Expand Up @@ -3208,6 +3236,11 @@ namespace {
} else {
value = std::move(arg).getAsSingleValue(SGF, contexts.ForEmission);
}

if (param.isConsumed() &&
value.getOwnershipKind() == ValueOwnershipKind::Guaranteed) {
value = value.copyUnmanaged(SGF, arg.getLocation());
}
Args.push_back(value);
}

Expand Down
56 changes: 56 additions & 0 deletions lib/SILGen/SILGenBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,59 @@ ManagedValue SILGenBuilder::createLoadTake(SILLocation loc, ManagedValue v,
assert(!lowering.isAddressOnly() && "cannot retain an unloadable type");
return gen.emitManagedRValueWithCleanup(result, lowering);
}

ManagedValue SILGenBuilder::createLoadCopy(SILLocation loc, ManagedValue v) {
auto &lowering = getFunction().getTypeLowering(v.getType());
return createLoadCopy(loc, v, lowering);
}

ManagedValue SILGenBuilder::createLoadCopy(SILLocation loc, ManagedValue v,
const TypeLowering &lowering) {
assert(lowering.getLoweredType().getAddressType() == v.getType());
SILValue result =
lowering.emitLoadOfCopy(*this, loc, v.forward(gen), IsNotTake);
if (lowering.isTrivial())
return ManagedValue::forUnmanaged(result);
assert(!lowering.isAddressOnly() && "cannot retain an unloadable type");
return gen.emitManagedRValueWithCleanup(result, lowering);
}

ManagedValue SILGenBuilder::createFunctionArgument(SILType type,
ValueDecl *decl) {
SILFunction &F = getFunction();

SILFunctionArgument *arg = F.begin()->createFunctionArgument(type, decl);
if (arg->getType().isObject()) {
if (arg->getOwnershipKind().isTrivialOr(ValueOwnershipKind::Owned))
return gen.emitManagedRValueWithCleanup(arg);
return ManagedValue::forBorrowedRValue(arg);
}

return gen.emitManagedBufferWithCleanup(arg);
}

ManagedValue
SILGenBuilder::createMarkUninitialized(ValueDecl *decl, ManagedValue operand,
MarkUninitializedInst::Kind muKind) {
// We either have an owned or trivial value.
SILValue value =
SILBuilder::createMarkUninitialized(decl, operand.forward(gen), muKind);
assert(value->getType().isObject() && "Expected only objects here");

// If we have a trivial value, just return without a cleanup.
if (operand.getOwnershipKind() != ValueOwnershipKind::Owned) {
return ManagedValue::forUnmanaged(value);
}

// Otherwise, recreate the cleanup.
return gen.emitManagedRValueWithCleanup(value);
}

ManagedValue SILGenBuilder::createEnum(SILLocation loc, ManagedValue payload,
EnumElementDecl *decl, SILType type) {
SILValue result =
SILBuilder::createEnum(loc, payload.forward(gen), decl, type);
if (result.getOwnershipKind() != ValueOwnershipKind::Owned)
return ManagedValue::forUnmanaged(result);
return gen.emitManagedRValueWithCleanup(result);
}
15 changes: 15 additions & 0 deletions lib/SILGen/SILGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ class SILGenBuilder : public SILBuilder {
ManagedValue originalValue);
ManagedValue createOwnedPHIArgument(SILType type);

using SILBuilder::createMarkUninitialized;
ManagedValue createMarkUninitialized(ValueDecl *decl, ManagedValue operand,
MarkUninitializedInst::Kind muKind);

using SILBuilder::createAllocRef;
ManagedValue createAllocRef(SILLocation loc, SILType refType, bool objc,
bool canAllocOnStack,
Expand Down Expand Up @@ -192,6 +196,17 @@ class SILGenBuilder : public SILBuilder {
ManagedValue createLoadTake(SILLocation loc, ManagedValue addr);
ManagedValue createLoadTake(SILLocation loc, ManagedValue addr,
const TypeLowering &lowering);
ManagedValue createLoadCopy(SILLocation Loc, ManagedValue Addr);
ManagedValue createLoadCopy(SILLocation Loc, ManagedValue Addr,
const TypeLowering &Lowering);

ManagedValue createFunctionArgument(SILType type, ValueDecl *decl);

using SILBuilder::createEnum;
ManagedValue createEnum(SILLocation loc, ManagedValue payload,
EnumElementDecl *decl, SILType type);

ManagedValue createSemanticLoadBorrow(SILLocation loc, ManagedValue addr);
};

} // namespace Lowering
Expand Down
Loading