Skip to content

Commit abda01a

Browse files
committed
[+0-normal-args] Change flattenOptional to use switch_enum instead of select_enum+cond_br.
Along the .none path, select_enum+cond_br causes the ownership verifier to trigger since the .none path looks like a leak. By using a switch_enum, we avoid this problem since the ownership verifier thinks the switch_enum consumes the input value and views the owned value along the .some path as a value with separate ownership. rdar://34222540
1 parent 568ae2d commit abda01a

File tree

1 file changed

+49
-48
lines changed

1 file changed

+49
-48
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "SILGen.h"
1413
#include "ArgumentScope.h"
1514
#include "ArgumentSource.h"
1615
#include "Callee.h"
@@ -21,16 +20,18 @@
2120
#include "LValue.h"
2221
#include "RValue.h"
2322
#include "ResultPlan.h"
23+
#include "SILGen.h"
2424
#include "SILGenDynamicCast.h"
2525
#include "Scope.h"
26+
#include "SwitchEnumBuilder.h"
2627
#include "Varargs.h"
2728
#include "swift/AST/ASTContext.h"
29+
#include "swift/AST/ASTMangler.h"
2830
#include "swift/AST/Decl.h"
2931
#include "swift/AST/DiagnosticsCommon.h"
3032
#include "swift/AST/Expr.h"
3133
#include "swift/AST/ForeignErrorConvention.h"
3234
#include "swift/AST/GenericEnvironment.h"
33-
#include "swift/AST/ASTMangler.h"
3435
#include "swift/AST/ParameterList.h"
3536
#include "swift/AST/ProtocolConformance.h"
3637
#include "swift/AST/SubstitutionMap.h"
@@ -4202,6 +4203,9 @@ RValue RValueEmitter::visitCollectionExpr(CollectionExpr *E, SGFContext C) {
42024203
/// Flattens one level of optional from a nested optional value.
42034204
static ManagedValue flattenOptional(SILGenFunction &SGF, SILLocation loc,
42044205
ManagedValue optVal) {
4206+
// This code assumes that we have a +1 value.
4207+
assert(optVal.isPlusOne(SGF));
4208+
42054209
// FIXME: Largely copied from SILGenFunction::emitOptionalToOptional.
42064210
auto contBB = SGF.createBasicBlock();
42074211
auto isNotPresentBB = SGF.createBasicBlock();
@@ -4212,57 +4216,54 @@ static ManagedValue flattenOptional(SILGenFunction &SGF, SILLocation loc,
42124216
assert(resultTy.getSwiftRValueType().getOptionalObjectType() &&
42134217
"input was not a nested optional value");
42144218

4215-
// If the result is address-only, we need to return something in memory,
4216-
// otherwise the result is the BBArgument in the merge point.
4217-
SILValue result;
4218-
if (resultTL.isAddressOnly())
4219-
result = SGF.emitTemporaryAllocation(loc, resultTy);
4220-
else
4221-
result = contBB->createPHIArgument(resultTy, ValueOwnershipKind::Owned);
4222-
4223-
// Branch on whether the input is optional, this doesn't consume the value.
4224-
auto isPresent = SGF.emitDoesOptionalHaveValue(loc, optVal.getValue());
4225-
SGF.B.createCondBranch(loc, isPresent, isPresentBB, isNotPresentBB);
4226-
4227-
// If it's present, apply the recursive transformation to the value.
4228-
SGF.B.emitBlock(isPresentBB);
4229-
SILValue branchArg;
4230-
{
4231-
// Don't allow cleanups to escape the conditional block.
4232-
FullExpr presentScope(SGF.Cleanups, CleanupLocation::get(loc));
4233-
4234-
// Pull the value out. This will load if the value is not address-only.
4235-
auto &inputTL = SGF.getTypeLowering(optVal.getType());
4236-
auto resultValue = SGF.emitUncheckedGetOptionalValueFrom(loc, optVal,
4237-
inputTL);
4238-
4239-
// Inject that into the result type if the result is address-only.
4240-
if (resultTL.isAddressOnly())
4241-
resultValue.forwardInto(SGF, loc, result);
4242-
else
4243-
branchArg = resultValue.forward(SGF);
4244-
}
4245-
if (branchArg)
4246-
SGF.B.createBranch(loc, contBB, branchArg);
4247-
else
4248-
SGF.B.createBranch(loc, contBB);
4249-
4250-
// If it's not present, inject 'nothing' into the result.
4251-
SGF.B.emitBlock(isNotPresentBB);
4219+
SILValue contBBArg;
4220+
TemporaryInitializationPtr addrOnlyResultBuf;
42524221
if (resultTL.isAddressOnly()) {
4253-
SGF.emitInjectOptionalNothingInto(loc, result, resultTL);
4254-
SGF.B.createBranch(loc, contBB);
4222+
addrOnlyResultBuf = SGF.emitTemporary(loc, resultTL);
42554223
} else {
4256-
branchArg = SGF.getOptionalNoneValue(loc, resultTL);
4257-
SGF.B.createBranch(loc, contBB, branchArg);
4258-
}
4224+
contBBArg = contBB->createPHIArgument(resultTy, ValueOwnershipKind::Owned);
4225+
}
4226+
4227+
SwitchEnumBuilder SEB(SGF.B, loc, optVal);
4228+
4229+
auto *someDecl = SGF.getASTContext().getOptionalSomeDecl();
4230+
SEB.addCase(someDecl, isPresentBB, contBB, [&](ManagedValue input,
4231+
SwitchCaseFullExpr &scope) {
4232+
if (resultTL.isAddressOnly()) {
4233+
SILValue addr =
4234+
addrOnlyResultBuf->getAddressForInPlaceInitialization(SGF, loc);
4235+
input = SGF.B.createUncheckedTakeEnumDataAddr(
4236+
loc, input, someDecl, input.getType().getOptionalObjectType());
4237+
SGF.B.createCopyAddr(loc, input.getValue(), addr, IsNotTake,
4238+
IsInitialization);
4239+
scope.exitAndBranch(loc);
4240+
return;
4241+
}
4242+
scope.exitAndBranch(loc, input.forward(SGF));
4243+
});
4244+
SEB.addCase(
4245+
SGF.getASTContext().getOptionalNoneDecl(), isNotPresentBB, contBB,
4246+
[&](ManagedValue input, SwitchCaseFullExpr &scope) {
4247+
if (resultTL.isAddressOnly()) {
4248+
SILValue addr =
4249+
addrOnlyResultBuf->getAddressForInPlaceInitialization(SGF, loc);
4250+
SGF.emitInjectOptionalNothingInto(loc, addr, resultTL);
4251+
scope.exitAndBranch(loc);
4252+
return;
4253+
}
4254+
4255+
auto mv = SGF.B.createManagedOptionalNone(loc, resultTy).forward(SGF);
4256+
scope.exitAndBranch(loc, mv);
4257+
});
4258+
std::move(SEB).emit();
42594259

42604260
// Continue.
42614261
SGF.B.emitBlock(contBB);
4262-
if (resultTL.isAddressOnly())
4263-
return SGF.emitManagedBufferWithCleanup(result, resultTL);
4264-
4265-
return SGF.emitManagedRValueWithCleanup(result, resultTL);
4262+
if (resultTL.isAddressOnly()) {
4263+
addrOnlyResultBuf->finishInitialization(SGF);
4264+
return addrOnlyResultBuf->getManagedAddress();
4265+
}
4266+
return SGF.emitManagedRValueWithCleanup(contBBArg, resultTL);
42664267
}
42674268

42684269
static ManagedValue

0 commit comments

Comments
 (0)