Skip to content

Some More Additional ManagedValue APIs #6836

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 3 commits into from
Jan 16, 2017
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
108 changes: 105 additions & 3 deletions lib/SILGen/ManagedValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,106 @@ class ManagedValue {
public:

ManagedValue() = default;

/// Create a managed value for a +1 rvalue.
///
/// Please do not introduce new uses of this method! Instead use one of the
/// static constructors below.
ManagedValue(SILValue value, CleanupHandle cleanup)
: valueAndFlag(value, false), cleanup(cleanup) {
assert(value && "No value specified");
assert(value && "No value specified?!");
}

/// Create a managed value for a +0 rvalue.
///
/// Please do not introduce new uses of this method! Instead use one of the
/// static constructors below!
static ManagedValue forUnmanaged(SILValue value) {
assert(value && "No value specified");
return ManagedValue(value, false, CleanupHandle::invalid());
}

/// Create a managed value for a +1 rvalue object.
static ManagedValue forOwnedObjectRValue(SILValue value,
CleanupHandle cleanup) {
assert(value && "No value specified");
assert(value->getType().isObject() &&
"Expected borrowed rvalues to be objects");
assert(value.getOwnershipKind() != ValueOwnershipKind::Trivial);
return ManagedValue(value, false, cleanup);
}

/// Create a managed value for a +1 rvalue address.
///
/// From a high level perspective, this consists of a temporary buffer.
static ManagedValue forOwnedAddressRValue(SILValue value,
CleanupHandle cleanup) {
assert(value && "No value specified");
assert(value->getType().isAddress() && "Expected value to be an address");
assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial &&
"Addresses always have trivial ownership");
return ManagedValue(value, false, cleanup);
}

/// Create a managed value for a +1 non-trivial rvalue.
static ManagedValue forOwnedRValue(SILValue value, CleanupHandle cleanup) {
if (value->getType().isAddress())
return ManagedValue::forOwnedAddressRValue(value, cleanup);
return ManagedValue::forOwnedObjectRValue(value, cleanup);
}

/// Create a managed value for a +0 borrowed non-trivial rvalue object.
static ManagedValue
forBorrowedObjectRValue(SILValue value,
CleanupHandle cleanup = CleanupHandle::invalid()) {
assert(value && "No value specified");
assert(value->getType().isObject() &&
"Expected borrowed rvalues to be objects");
assert(value.getOwnershipKind() != ValueOwnershipKind::Trivial);
return ManagedValue(value, false, cleanup);
}

/// Create a managed value for a +0 borrowed non-trivial rvalue address.
static ManagedValue
forBorrowedAddressRValue(SILValue value,
CleanupHandle cleanup = CleanupHandle::invalid()) {
assert(value && "No value specified");
assert(value->getType().isAddress() && "Expected value to be an address");
assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial &&
"Addresses always have trivial ownership");
return ManagedValue(value, false, cleanup);
}

/// Create a managed value for a +0 guaranteed rvalue.
static ManagedValue
forBorrowedRValue(SILValue value,
CleanupHandle cleanup = CleanupHandle::invalid()) {
if (value->getType().isAddress())
return ManagedValue::forBorrowedAddressRValue(value, cleanup);
return ManagedValue::forBorrowedObjectRValue(value, cleanup);
}

/// Create a managed value for a +0 trivial object rvalue.
static ManagedValue forTrivialObjectRValue(SILValue value) {
assert(value->getType().isObject() && "Expected an object");
assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial);
return ManagedValue(value, false, CleanupHandle::invalid());
}

/// Create a managed value for a +0 trivial address rvalue.
static ManagedValue forTrivialAddressRValue(SILValue value) {
assert(value->getType().isAddress() && "Expected an address");
assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial);
return ManagedValue(value, false, CleanupHandle::invalid());
}

/// Create a managed value for a +0 trivial rvalue.
static ManagedValue forTrivialRValue(SILValue value) {
if (value->getType().isObject())
return ManagedValue::forTrivialObjectRValue(value);
return ManagedValue::forTrivialAddressRValue(value);
}

/// Create a managed value for an l-value.
static ManagedValue forLValue(SILValue value) {
assert(value && "No value specified");
Expand Down Expand Up @@ -123,7 +210,22 @@ class ManagedValue {
SILValue getValue() const { return valueAndFlag.getPointer(); }

SILType getType() const { return getValue()->getType(); }


/// Transform the given ManagedValue, replacing the underlying value, but
/// keeping the same cleanup.
///
/// For owned values, this is equivalent to forwarding the cleanup and
/// creating a new cleanup of the same type on the new value. This is useful
/// for forwarding sequences.
///
/// For all other values, it is a move.
ManagedValue transform(SILValue newValue) && {
assert(getValue().getOwnershipKind() == newValue.getOwnershipKind() &&
"New value and old value must have the same ownership kind");
ManagedValue M(newValue, isLValue(), getCleanup());
*this = ManagedValue();
return M;
}

CanType getSwiftType() const {
return isLValue()
Expand Down
10 changes: 5 additions & 5 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,11 +925,11 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
objcMetaType = CanExistentialMetatypeType::get(type,
MetatypeRepresentation::ObjC);
}
selfMetaObjC = ManagedValue(
SGF.B.emitThickToObjCMetatype(
loc, selfMeta.getValue(),
SGF.SGM.getLoweredType(objcMetaType)),
selfMeta.getCleanup());
// ObjC metatypes are trivial and thus do not have a cleanup. Only if we
// convert them to an object do they become non-trivial.
assert(!selfMeta.hasCleanup());
selfMetaObjC = ManagedValue::forUnmanaged(SGF.B.emitThickToObjCMetatype(
loc, selfMeta.getValue(), SGF.SGM.getLoweredType(objcMetaType)));
}

// Allocate the object.
Expand Down
12 changes: 10 additions & 2 deletions lib/SILGen/SILGenBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,11 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &gen,
if (bridgedMetaTy->getRepresentation() == MetatypeRepresentation::ObjC) {
SILValue native = gen.B.emitThickToObjCMetatype(loc, v.getValue(),
SILType::getPrimitiveObjectType(loweredBridgedTy));
return ManagedValue(native, v.getCleanup());
// *NOTE*: ObjCMetatypes are trivial types. They only gain ARC semantics
// when they are converted to an object via objc_metatype_to_object.
assert(!v.hasCleanup() &&
"Metatypes are trivial and thus should not have cleanups");
return ManagedValue::forUnmanaged(native);
}
}

Expand Down Expand Up @@ -710,7 +714,11 @@ static ManagedValue emitCBridgedToNativeValue(SILGenFunction &gen,
if (bridgedMetaTy->getRepresentation() == MetatypeRepresentation::ObjC) {
SILValue native = gen.B.emitObjCToThickMetatype(loc, v.getValue(),
gen.getLoweredType(loweredNativeTy));
return ManagedValue(native, v.getCleanup());
// *NOTE*: ObjCMetatypes are trivial types. They only gain ARC semantics
// when they are converted to an object via objc_metatype_to_object.
assert(!v.hasCleanup() && "Metatypes are trivial and should not have "
"cleanups");
return ManagedValue::forUnmanaged(native);
}
}

Expand Down