Skip to content

[silgen] Require ManagedValue::{forward,assign}Into to only accept pl… #14566

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
28 changes: 16 additions & 12 deletions lib/SILGen/ManagedValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,29 +110,22 @@ SILValue ManagedValue::forward(SILGenFunction &SGF) const {

void ManagedValue::forwardInto(SILGenFunction &SGF, SILLocation loc,
SILValue address) {
if (!hasCleanup() && getOwnershipKind() != ValueOwnershipKind::Trivial)
return copyUnmanaged(SGF, loc).forwardInto(SGF, loc, address);

if (hasCleanup())
forwardCleanup(SGF);

assert(isPlusOne(SGF));
auto &addrTL = SGF.getTypeLowering(address->getType());
SGF.emitSemanticStore(loc, getValue(), address,
addrTL, IsInitialization);
SGF.emitSemanticStore(loc, forward(SGF), address, addrTL, IsInitialization);
}

void ManagedValue::assignInto(SILGenFunction &SGF, SILLocation loc,
SILValue address) {
if (hasCleanup())
forwardCleanup(SGF);

assert(isPlusOne(SGF));
auto &addrTL = SGF.getTypeLowering(address->getType());
SGF.emitSemanticStore(loc, getValue(), address, addrTL,
SGF.emitSemanticStore(loc, forward(SGF), address, addrTL,
IsNotInitialization);
}

void ManagedValue::forwardInto(SILGenFunction &SGF, SILLocation loc,
Initialization *dest) {
assert(isPlusOne(SGF));
dest->copyOrInitValueInto(SGF, loc, *this, /*isInit*/ true);
dest->finishInitialization(SGF);
}
Expand Down Expand Up @@ -208,3 +201,14 @@ ManagedValue ManagedValue::ensurePlusOne(SILGenFunction &SGF,
}
return *this;
}

bool ManagedValue::isPlusOne(SILGenFunction &SGF) const {
// Ignore trivial values and objects with trivial value ownership kind.
if (getType().isTrivial(SGF.F.getModule()) ||
(getType().isObject() &&
getOwnershipKind() == ValueOwnershipKind::Trivial))
return true;
return hasCleanup();
}

bool ManagedValue::isPlusZero() const { return hasCleanup(); }
28 changes: 27 additions & 1 deletion lib/SILGen/ManagedValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,33 @@ class ManagedValue {
// either +0 or trivial (in which case +0 vs +1 doesn't matter).
return !hasCleanup();
}


/// Returns true if this is an managed value that can be used safely as a +1
/// managed value.
///
/// This returns true iff:
///
/// 1. All sub-values are trivially typed.
/// 2. There exists at least one non-trivial typed sub-value and all such
/// sub-values all have cleanups.
///
/// *NOTE* Due to 1. isPlusOne and isPlusZero both return true for managed
/// values consisting of only trivial values.
bool isPlusOne(SILGenFunction &SGF) const;

/// Returns true if this is an ManagedValue that can be used safely as a +0
/// ManagedValue.
///
/// Specifically, we return true if:
///
/// 1. All sub-values are trivially typed.
/// 2. At least 1 subvalue is non-trivial and all such non-trivial values do
/// not have a cleanup.
///
/// *NOTE* Due to 1. isPlusOne and isPlusZero both return true for
/// ManagedValues consisting of only trivial values.
bool isPlusZero() const;

SILValue getLValueAddress() const {
assert(isLValue() && "This isn't an lvalue");
return getValue();
Expand Down
15 changes: 4 additions & 11 deletions lib/SILGen/RValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -788,20 +788,13 @@ void RValue::verify(SILGenFunction &SGF) const & {
}

bool RValue::isPlusOne(SILGenFunction &SGF) const & {
return llvm::all_of(values, [&SGF](ManagedValue mv) -> bool {
// Ignore trivial values and objects with trivial value ownership kind.
if (mv.getType().isTrivial(SGF.F.getModule()) ||
(mv.getType().isObject() &&
mv.getOwnershipKind() == ValueOwnershipKind::Trivial))
return true;
return mv.hasCleanup();
});
return llvm::all_of(
values, [&SGF](ManagedValue mv) -> bool { return mv.isPlusOne(SGF); });
}

bool RValue::isPlusZero(SILGenFunction &SGF) const & {
return llvm::none_of(values, [](ManagedValue mv) -> bool {
return mv.hasCleanup();
});
return llvm::none_of(values,
[](ManagedValue mv) -> bool { return mv.isPlusZero(); });
}

const TypeLowering &RValue::getTypeLowering(SILGenFunction &SGF) const & {
Expand Down