Fix CastEmitter ownership.

Rewrite ownership forwarding through switch_enums. It's unclear what
the original code was doing, but enabling OSSA verification for
terminators revealed the issue.
This commit is contained in:
Andrew Trick
2021-09-06 13:40:44 -07:00
parent 8f53a927b0
commit 29ee02d5bb

View File

@@ -848,18 +848,10 @@ namespace {
SILValue getOwnedScalar(Source source, const TypeLowering &srcTL) {
assert(!source.isAddress());
return source.Value;
}
Source putOwnedScalar(SILValue scalar, Target target) {
assert(scalar->getType() == target.LoweredType.getObjectType());
if (!target.isAddress())
return target.asScalarSource(scalar);
auto &targetTL = getTypeLowering(target.LoweredType);
targetTL.emitStoreOfCopy(B, Loc, scalar, target.Address,
IsInitialization);
return target.asAddressSource();
auto value = source.Value;
if (value.getOwnershipKind() == OwnershipKind::Guaranteed)
value = B.emitCopyValueOperation(Loc, value);
return value;
}
Source emitSameType(Source source, Target target) {
@@ -917,7 +909,8 @@ namespace {
if (source.isAddress()) {
value = srcTL.emitLoadOfCopy(B, Loc, source.Value, IsTake);
} else {
value = getOwnedScalar(source, srcTL);
// May have any valid ownership.
value = source.Value;
}
auto targetFormalTy = target.FormalType;
auto targetLoweredTy =
@@ -929,7 +922,15 @@ namespace {
} else {
value = B.createUpcast(Loc, value, targetLoweredTy);
}
return putOwnedScalar(value, target);
// If the target is an address, then scalar must be Owned. Otherwise, it
// may be Guaranteed.
assert(value->getType() == target.LoweredType.getObjectType());
if (!target.isAddress())
return target.asScalarSource(value);
auto &targetTL = getTypeLowering(target.LoweredType);
targetTL.emitStoreOfCopy(B, Loc, value, target.Address, IsInitialization);
return target.asAddressSource();
}
Source emitAndInjectIntoOptionals(Source source, Target target,
@@ -961,7 +962,9 @@ namespace {
if (source.isAddress()) {
B.createSwitchEnumAddr(Loc, source.Value, /*default*/ nullptr, cases);
} else {
B.createSwitchEnum(Loc, source.Value, /*default*/ nullptr, cases);
auto *switchEnum =
B.createSwitchEnum(Loc, source.Value, /*default*/ nullptr, cases);
switchEnum->createOptionalSomeResult();
}
// Create the Some block, which recurses.
@@ -988,10 +991,7 @@ namespace {
sourceSomeDecl, loweredSourceObjectType);
objectSource = Source(sourceAddr, sourceObjectType);
} else {
// switch enum always start as @owned.
SILValue sourceObjectValue = someBB->createPhiArgument(
loweredSourceObjectType, OwnershipKind::Owned);
objectSource = Source(sourceObjectValue, sourceObjectType);
objectSource = Source(someBB->getArgument(0), sourceObjectType);
}
Source resultObject = emit(objectSource, objectTarget);
@@ -1006,7 +1006,9 @@ namespace {
if (target.isAddress()) {
B.createBranch(Loc, contBB);
} else {
B.createBranch(Loc, contBB, { result.Value });
auto &resultTL = getTypeLowering(result.Value->getType());
SILValue resultVal = getOwnedScalar(source, resultTL);
B.createBranch(Loc, contBB, {resultVal});
}
}
@@ -1057,6 +1059,8 @@ namespace {
}
}
// May return an Owned or Guaranteed result. If source is has ownership
// None, then the result may still be Guaranteed for nontrivial types.
Source emitSome(Source source, Target target, EmitSomeState &state) {
// If our target is an address, prepareForEmitSome should have set this
// up so that we emitted directly into
@@ -1064,11 +1068,9 @@ namespace {
B.createInjectEnumAddr(Loc, target.Address, state.SomeDecl);
return target.asAddressSource();
} else {
auto &srcTL = getTypeLowering(source.Value->getType());
auto sourceObject = getOwnedScalar(source, srcTL);
auto source = B.createEnum(Loc, sourceObject, state.SomeDecl,
target.LoweredType);
return target.asScalarSource(source);
auto someEnum =
B.createEnum(Loc, source.Value, state.SomeDecl, target.LoweredType);
return target.asScalarSource(someEnum);
}
}