[sil] Add a new CastConsumptionKind called BorrowAlways.

This means that:

1. SILGenPattern always borrows the object before it emits a case.
2. Any cast with this cast has a +0 result.

NOTE: That one can not use this with address types (so we assert if you
pass this checked_cast_addr_br).
NOTE: Once we have opaque values, checked_cast_br of a guaranteed value will
lower to a copy + checked_cast_addr_br (assuming the operation is a consuming
cast). To make sure this does not become a problem in terms of performance, we
will need a pass that can transform SILGenPattern +0 cases to +1 cases. This is
something that we have talked about in the past and I think it is reasonable to
implement.

This is an incremental commit towards fixing SILGenPattern for ownership.

rdar://29791263
This commit is contained in:
Michael Gottesman
2018-10-08 13:05:03 -07:00
parent 2a18ea7b79
commit 62b5110357
12 changed files with 93 additions and 19 deletions

View File

@@ -1165,6 +1165,7 @@ static bool shouldTake(ConsumableManagedValue value, bool isIrrefutable) {
case CastConsumptionKind::TakeAlways: return true;
case CastConsumptionKind::TakeOnSuccess: return isIrrefutable;
case CastConsumptionKind::CopyOnSuccess: return false;
case CastConsumptionKind::BorrowAlways: return false;
}
llvm_unreachable("bad consumption kind");
}
@@ -1349,14 +1350,17 @@ static ConsumableManagedValue
getManagedSubobject(SILGenFunction &SGF, SILValue value,
const TypeLowering &valueTL,
CastConsumptionKind consumption) {
if (consumption == CastConsumptionKind::CopyOnSuccess) {
switch (consumption) {
case CastConsumptionKind::BorrowAlways:
case CastConsumptionKind::CopyOnSuccess:
return {ManagedValue::forUnmanaged(value), consumption};
case CastConsumptionKind::TakeAlways:
case CastConsumptionKind::TakeOnSuccess:
assert((!SGF.F.getModule().getOptions().EnableSILOwnership ||
consumption != CastConsumptionKind::TakeOnSuccess) &&
"TakeOnSuccess should never be used when sil ownership is enabled");
return {SGF.emitManagedRValueWithCleanup(value, valueTL), consumption};
}
assert((!SGF.F.getModule().getOptions().EnableSILOwnership ||
consumption != CastConsumptionKind::TakeOnSuccess) &&
"TakeOnSuccess should never be used when sil ownership is enabled");
return {SGF.emitManagedRValueWithCleanup(value, valueTL), consumption};
}
static ConsumableManagedValue
@@ -1873,6 +1877,7 @@ void PatternMatchEmission::emitEnumElementDispatch(
switch (src.getFinalConsumption()) {
case CastConsumptionKind::TakeAlways:
case CastConsumptionKind::CopyOnSuccess:
case CastConsumptionKind::BorrowAlways:
// No change to src necessary.
break;
@@ -1977,7 +1982,13 @@ void PatternMatchEmission::emitEnumElementDispatch(
eltValue = SGF.B.createUncheckedTakeEnumDataAddr(loc, srcValue,
elt, eltTy);
break;
case CastConsumptionKind::BorrowAlways:
// If we reach this point, we know that we have a loadable
// element type from an enum with mixed address
// only/loadable cases. Since we had an address only type,
// we assume that we will not have BorrowAlways since
// address only types do not support BorrowAlways.
llvm_unreachable("not allowed");
case CastConsumptionKind::CopyOnSuccess: {
auto copy = SGF.emitTemporaryAllocation(loc, srcValue->getType());
SGF.B.createCopyAddr(loc, srcValue, copy,