@@ -189,8 +189,6 @@ namespace {
189
189
#define STMT (ID, BASE ) void visit##ID##Stmt(ID##Stmt *S);
190
190
#include " swift/AST/StmtNodes.def"
191
191
192
- void visitAsyncForEachStmt (ForEachStmt *S);
193
-
194
192
ASTContext &getASTContext () { return SGF.getASTContext (); }
195
193
196
194
SILBasicBlock *createBasicBlock () { return SGF.createBasicBlock (); }
@@ -1020,174 +1018,7 @@ void StmtEmitter::visitRepeatWhileStmt(RepeatWhileStmt *S) {
1020
1018
SGF.BreakContinueDestStack .pop_back ();
1021
1019
}
1022
1020
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
-
1185
1021
void StmtEmitter::visitForEachStmt (ForEachStmt *S) {
1186
- if (S->getAwaitLoc ().isValid ()) {
1187
- visitAsyncForEachStmt (S);
1188
- return ;
1189
- }
1190
-
1191
1022
// Emit the 'iterator' variable that we'll be using for iteration.
1192
1023
LexicalScope OuterForScope (SGF, CleanupLocation (S));
1193
1024
{
0 commit comments