10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
- #include " SILGen.h"
14
13
#include " ArgumentScope.h"
15
14
#include " ArgumentSource.h"
16
15
#include " Callee.h"
21
20
#include " LValue.h"
22
21
#include " RValue.h"
23
22
#include " ResultPlan.h"
23
+ #include " SILGen.h"
24
24
#include " SILGenDynamicCast.h"
25
25
#include " Scope.h"
26
+ #include " SwitchEnumBuilder.h"
26
27
#include " Varargs.h"
27
28
#include " swift/AST/ASTContext.h"
29
+ #include " swift/AST/ASTMangler.h"
28
30
#include " swift/AST/Decl.h"
29
31
#include " swift/AST/DiagnosticsCommon.h"
30
32
#include " swift/AST/Expr.h"
31
33
#include " swift/AST/ForeignErrorConvention.h"
32
34
#include " swift/AST/GenericEnvironment.h"
33
- #include " swift/AST/ASTMangler.h"
34
35
#include " swift/AST/ParameterList.h"
35
36
#include " swift/AST/ProtocolConformance.h"
36
37
#include " swift/AST/SubstitutionMap.h"
@@ -4202,6 +4203,9 @@ RValue RValueEmitter::visitCollectionExpr(CollectionExpr *E, SGFContext C) {
4202
4203
// / Flattens one level of optional from a nested optional value.
4203
4204
static ManagedValue flattenOptional (SILGenFunction &SGF, SILLocation loc,
4204
4205
ManagedValue optVal) {
4206
+ // This code assumes that we have a +1 value.
4207
+ assert (optVal.isPlusOne (SGF));
4208
+
4205
4209
// FIXME: Largely copied from SILGenFunction::emitOptionalToOptional.
4206
4210
auto contBB = SGF.createBasicBlock ();
4207
4211
auto isNotPresentBB = SGF.createBasicBlock ();
@@ -4212,57 +4216,54 @@ static ManagedValue flattenOptional(SILGenFunction &SGF, SILLocation loc,
4212
4216
assert (resultTy.getSwiftRValueType ().getOptionalObjectType () &&
4213
4217
" input was not a nested optional value" );
4214
4218
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;
4252
4221
if (resultTL.isAddressOnly ()) {
4253
- SGF.emitInjectOptionalNothingInto (loc, result, resultTL);
4254
- SGF.B .createBranch (loc, contBB);
4222
+ addrOnlyResultBuf = SGF.emitTemporary (loc, resultTL);
4255
4223
} 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 ();
4259
4259
4260
4260
// Continue.
4261
4261
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);
4266
4267
}
4267
4268
4268
4269
static ManagedValue
0 commit comments