@@ -189,8 +189,6 @@ namespace {
189189#define STMT (ID, BASE ) void visit##ID##Stmt(ID##Stmt *S);
190190#include " swift/AST/StmtNodes.def"
191191
192- void visitAsyncForEachStmt (ForEachStmt *S);
193-
194192 ASTContext &getASTContext () { return SGF.getASTContext (); }
195193
196194 SILBasicBlock *createBasicBlock () { return SGF.createBasicBlock (); }
@@ -1020,174 +1018,7 @@ void StmtEmitter::visitRepeatWhileStmt(RepeatWhileStmt *S) {
10201018 SGF.BreakContinueDestStack .pop_back ();
10211019}
10221020
1023- void StmtEmitter::visitAsyncForEachStmt (ForEachStmt *S) {
1024- // Emit the 'generator' variable that we'll be using for iteration.
1025- LexicalScope OuterForScope (SGF, CleanupLocation (S));
1026- {
1027- SGF.emitPatternBinding (S->getIteratorVar ()->getParentPatternBinding (),
1028- /* index=*/ 0 );
1029- }
1030-
1031- // If we ever reach an unreachable point, stop emitting statements.
1032- // This will need revision if we ever add goto.
1033- if (!SGF.B .hasValidInsertionPoint ()) return ;
1034-
1035- // If generator's optional result is address-only, create a stack allocation
1036- // to hold the results. This will be initialized on every entry into the loop
1037- // header and consumed by the loop body. On loop exit, the terminating value
1038- // will be in the buffer.
1039- CanType optTy;
1040- if (S->getConvertElementExpr ()) {
1041- optTy = S->getConvertElementExpr ()->getType ()->getCanonicalType ();
1042- } else {
1043- optTy = S->getNextCall ()->getType ()->getCanonicalType ();
1044- }
1045- auto &optTL = SGF.getTypeLowering (optTy);
1046- SILValue addrOnlyBuf;
1047- ManagedValue nextBufOrValue;
1048-
1049- if (optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ())
1050- addrOnlyBuf = SGF.emitTemporaryAllocation (S, optTL.getLoweredType ());
1051-
1052- // Create a new basic block and jump into it.
1053- JumpDest loopDest = createJumpDest (S->getBody ());
1054- SGF.B .emitBlock (loopDest.getBlock (), S);
1055-
1056- // Set the destinations for 'break' and 'continue'.
1057- JumpDest endDest = createJumpDest (S->getBody ());
1058- SGF.BreakContinueDestStack .push_back ({ S, endDest, loopDest });
1059-
1060- auto buildElementRValue = [&](SILLocation loc, SGFContext ctx) {
1061- RValue result;
1062- Expr *nextCall = S->getNextCall ();
1063- result = SGF.emitApplyExpr (
1064- cast<ApplyExpr>(nextCall->getSemanticsProvidingExpr ()),
1065- S->getElementExpr () ? SGFContext () : ctx);
1066- if (S->getElementExpr ()) {
1067- SILGenFunction::OpaqueValueRAII pushOpaqueValue (
1068- SGF, S->getElementExpr (),
1069- std::move (result).getAsSingleValue (SGF, loc));
1070- result = SGF.emitRValue (S->getConvertElementExpr (), ctx);
1071- }
1072- return result;
1073- };
1074-
1075- // Then emit the loop destination block.
1076- //
1077- // Advance the generator. Use a scope to ensure that any temporary stack
1078- // allocations in the subexpression are immediately released.
1079- if (optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ()) {
1080- // Create the initialization outside of the innerForScope so that the
1081- // innerForScope doesn't clean it up.
1082- auto nextInit = SGF.useBufferAsTemporary (addrOnlyBuf, optTL);
1083- {
1084- ArgumentScope innerForScope (SGF, SILLocation (S));
1085- SILLocation loc = SILLocation (S);
1086- RValue result = buildElementRValue (loc, SGFContext (nextInit.get ()));
1087- if (!result.isInContext ()) {
1088- ArgumentSource (SILLocation (S->getSequence ()),
1089- std::move (result).ensurePlusOne (SGF, loc))
1090- .forwardInto (SGF, nextInit.get ());
1091- }
1092- innerForScope.pop ();
1093- }
1094- nextBufOrValue = nextInit->getManagedAddress ();
1095- } else {
1096- ArgumentScope innerForScope (SGF, SILLocation (S));
1097- nextBufOrValue = innerForScope.popPreservingValue (
1098- buildElementRValue (SILLocation (S), SGFContext ())
1099- .getAsSingleValue (SGF, SILLocation (S)));
1100- }
1101-
1102- SILBasicBlock *failExitingBlock = createBasicBlock ();
1103- SwitchEnumBuilder switchEnumBuilder (SGF.B , S, nextBufOrValue);
1104-
1105- switchEnumBuilder.addOptionalSomeCase (
1106- createBasicBlock (), loopDest.getBlock (),
1107- [&](ManagedValue inputValue, SwitchCaseFullExpr &&scope) {
1108- SGF.emitProfilerIncrement (S->getBody ());
1109-
1110- // Emit the loop body.
1111- // The declared variable(s) for the current element are destroyed
1112- // at the end of each loop iteration.
1113- {
1114- Scope innerForScope (SGF.Cleanups , CleanupLocation (S->getBody ()));
1115- // Emit the initialization for the pattern. If any of the bound
1116- // patterns
1117- // fail (because this is a 'for case' pattern with a refutable
1118- // pattern,
1119- // the code should jump to the continue block.
1120- InitializationPtr initLoopVars =
1121- SGF.emitPatternBindingInitialization (S->getPattern (), loopDest);
1122-
1123- // If we had a loadable "next" generator value, we know it is present.
1124- // Get the value out of the optional, and wrap it up with a cleanup so
1125- // that any exits out of this scope properly clean it up.
1126- //
1127- // *NOTE* If we do not have an address only value, then inputValue is
1128- // *already properly unwrapped.
1129- if (optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ()) {
1130- inputValue = SGF.emitUncheckedGetOptionalValueFrom (
1131- S, inputValue, optTL, SGFContext (initLoopVars.get ()));
1132- }
1133-
1134- if (!inputValue.isInContext ())
1135- RValue (SGF, S, optTy.getOptionalObjectType (), inputValue)
1136- .forwardInto (SGF, S, initLoopVars.get ());
1137-
1138- // Now that the pattern has been initialized, check any where
1139- // condition.
1140- // If it fails, loop around as if 'continue' happened.
1141- if (auto *Where = S->getWhere ()) {
1142- auto cond = SGF.emitCondition (Where, /* invert*/ true );
1143- // If self is null, branch to the epilog.
1144- cond.enterTrue (SGF);
1145- SGF.Cleanups .emitBranchAndCleanups (loopDest, Where, {});
1146- cond.exitTrue (SGF);
1147- cond.complete (SGF);
1148- }
1149-
1150- visit (S->getBody ());
1151- }
1152-
1153- // If we emitted an unreachable in the body, we will not have a valid
1154- // insertion point. Just return early.
1155- if (!SGF.B .hasValidInsertionPoint ()) {
1156- scope.unreachableExit ();
1157- return ;
1158- }
1159-
1160- // Otherwise, associate the loop body's closing brace with this branch.
1161- RegularLocation L (S->getBody ());
1162- L.pointToEnd ();
1163- scope.exitAndBranch (L);
1164- },
1165- SGF.loadProfilerCount (S->getBody ()));
1166-
1167- // We add loop fail block, just to be defensive about intermediate
1168- // transformations performing cleanups at scope.exit(). We still jump to the
1169- // contBlock.
1170- switchEnumBuilder.addOptionalNoneCase (
1171- createBasicBlock (), failExitingBlock,
1172- [&](ManagedValue inputValue, SwitchCaseFullExpr &&scope) {
1173- assert (!inputValue && " None should not be passed an argument!" );
1174- scope.exitAndBranch (S);
1175- },
1176- SGF.loadProfilerCount (S));
1177-
1178- std::move (switchEnumBuilder).emit ();
1179-
1180- SGF.B .emitBlock (failExitingBlock);
1181- emitOrDeleteBlock (SGF, endDest, S);
1182- SGF.BreakContinueDestStack .pop_back ();
1183- }
1184-
11851021void StmtEmitter::visitForEachStmt (ForEachStmt *S) {
1186- if (S->getAwaitLoc ().isValid ()) {
1187- visitAsyncForEachStmt (S);
1188- return ;
1189- }
1190-
11911022 // Emit the 'iterator' variable that we'll be using for iteration.
11921023 LexicalScope OuterForScope (SGF, CleanupLocation (S));
11931024 {
0 commit comments