11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include " SILGen.h"
14
- #include " Scope.h"
15
14
#include " Condition.h"
16
15
#include " Initialization.h"
17
16
#include " LValue.h"
18
17
#include " RValue.h"
18
+ #include " Scope.h"
19
+ #include " SwitchCaseFullExpr.h"
19
20
#include " swift/AST/AST.h"
20
- #include " swift/SIL/SILArgument.h"
21
21
#include " swift/AST/DiagnosticsSIL.h"
22
+ #include " swift/SIL/SILArgument.h"
22
23
#include " llvm/Support/SaveAndRestore.h"
23
24
24
25
using namespace swift ;
@@ -745,7 +746,7 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
745
746
// Emit the 'iterator' variable that we'll be using for iteration.
746
747
LexicalScope OuterForScope (SGF.Cleanups , SGF, CleanupLocation (S));
747
748
SGF.visitPatternBindingDecl (S->getIterator ());
748
-
749
+
749
750
// If we ever reach an unreachable point, stop emitting statements.
750
751
// This will need revision if we ever add goto.
751
752
if (!SGF.B .hasValidInsertionPoint ()) return ;
@@ -756,100 +757,130 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
756
757
// will be in the buffer.
757
758
auto optTy = S->getIteratorNext ()->getType ()->getCanonicalType ();
758
759
auto &optTL = SGF.getTypeLowering (optTy);
759
- SILValue nextBufOrValue;
760
+ SILValue addrOnlyBuf;
761
+ ManagedValue nextBufOrValue;
760
762
761
763
if (optTL.isAddressOnly ())
762
- nextBufOrValue = SGF.emitTemporaryAllocation (S, optTL.getLoweredType ());
763
-
764
+ addrOnlyBuf = SGF.emitTemporaryAllocation (S, optTL.getLoweredType ());
765
+
764
766
// Create a new basic block and jump into it.
765
767
JumpDest loopDest = createJumpDest (S->getBody ());
766
768
SGF.B .emitBlock (loopDest.getBlock (), S);
767
-
769
+
768
770
// Set the destinations for 'break' and 'continue'.
769
771
JumpDest endDest = createJumpDest (S->getBody ());
770
772
SGF.BreakContinueDestStack .push_back ({ S, endDest, loopDest });
771
773
774
+ // Then emit the loop destination block.
775
+ //
772
776
// Advance the generator. Use a scope to ensure that any temporary stack
773
777
// allocations in the subexpression are immediately released.
774
778
if (optTL.isAddressOnly ()) {
775
779
Scope InnerForScope (SGF.Cleanups , CleanupLocation (S->getIteratorNext ()));
776
- auto nextInit = SGF.useBufferAsTemporary (nextBufOrValue , optTL);
780
+ auto nextInit = SGF.useBufferAsTemporary (addrOnlyBuf , optTL);
777
781
SGF.emitExprInto (S->getIteratorNext (), nextInit.get ());
778
- nextInit->getManagedAddress ().forward (SGF);
779
- } else {
780
- Scope InnerForScope (SGF.Cleanups , CleanupLocation (S->getIteratorNext ()));
781
782
nextBufOrValue =
782
- SGF.emitRValueAsSingleValue (S->getIteratorNext ()).forward (SGF);
783
- }
784
-
785
- // Continue if the value is present.
786
- Condition Cond = SGF.emitCondition (
787
- SGF.emitDoesOptionalHaveValue (S, nextBufOrValue), S,
788
- /* hasFalseCode=*/ false , /* invertValue=*/ false );
789
-
790
- if (Cond.hasTrue ()) {
791
- Cond.enterTrue (SGF);
792
- SGF.emitProfilerIncrement (S->getBody ());
793
-
794
- // Emit the loop body.
795
- // The declared variable(s) for the current element are destroyed
796
- // at the end of each loop iteration.
783
+ ManagedValue::forUnmanaged (nextInit->getManagedAddress ().forward (SGF));
784
+ } else {
785
+ // SEMANTIC SIL TODO: I am doing this to match previous behavior. We need to
786
+ // forward tmp below to ensure that we do not prematurely destroy the
787
+ // induction variable at the end of scope. I tried to use the
788
+ // CleanupRestorationScope and dormant, but it seemingly did not work and I
789
+ // do not have time to look into this now = (.
790
+ SILValue tmpValue;
791
+ bool hasCleanup;
797
792
{
798
- Scope InnerForScope (SGF.Cleanups , CleanupLocation (S->getBody ()));
799
- // Emit the initialization for the pattern. If any of the bound patterns
800
- // fail (because this is a 'for case' pattern with a refutable pattern,
801
- // the code should jump to the continue block.
802
- InitializationPtr initLoopVars
803
- = SGF.emitPatternBindingInitialization (S->getPattern (), loopDest);
804
- ManagedValue val;
805
-
806
- // If we had a loadable "next" generator value, we know it is present.
807
- // Get the value out of the optional, and wrap it up with a cleanup so
808
- // that any exits out of this scope properly clean it up.
809
- if (optTL.isLoadable ()) {
810
- val = SGF.emitManagedRValueWithCleanup (nextBufOrValue);
811
- } else {
812
- val = SGF.emitManagedBufferWithCleanup (nextBufOrValue);
813
- }
814
- val = SGF.emitUncheckedGetOptionalValueFrom (S, val, optTL,
815
- SGFContext (initLoopVars.get ()));
816
- if (!val.isInContext ())
817
- RValue (SGF, S, optTy.getAnyOptionalObjectType (), val)
818
- .forwardInto (SGF, S, initLoopVars.get ());
819
-
820
- // Now that the pattern has been initialized, check any where condition.
821
- // If it fails, loop around as if 'continue' happened.
822
- if (auto *Where = S->getWhere ()) {
823
- auto cond = SGF.emitCondition (Where, /* hasFalse*/ false , /* invert*/ true );
824
- // If self is null, branch to the epilog.
825
- cond.enterTrue (SGF);
826
- SGF.Cleanups .emitBranchAndCleanups (loopDest, Where, { });
827
- cond.exitTrue (SGF);
828
- cond.complete (SGF);
829
- }
830
-
831
- visit (S->getBody ());
793
+ Scope InnerForScope (SGF.Cleanups , CleanupLocation (S->getIteratorNext ()));
794
+ ManagedValue tmp = SGF.emitRValueAsSingleValue (S->getIteratorNext ());
795
+ hasCleanup = tmp.hasCleanup ();
796
+ tmpValue = tmp.forward (SGF);
832
797
}
833
-
834
- // Loop back to the header.
835
- if (SGF.B .hasValidInsertionPoint ()) {
836
- // Associate the loop body's closing brace with this branch.
837
- RegularLocation L (S->getBody ());
838
- L.pointToEnd ();
839
- SGF.B .createBranch (L, loopDest.getBlock ());
840
- }
841
- Cond.exitTrue (SGF);
842
- }
843
-
844
- // Complete the conditional execution.
845
- Cond.complete (SGF);
846
-
798
+ nextBufOrValue = hasCleanup ? SGF.emitManagedRValueWithCleanup (tmpValue)
799
+ : ManagedValue::forUnmanaged (tmpValue);
800
+ }
801
+
802
+ SILBasicBlock *failExitingBlock = createBasicBlock ();
803
+ SwitchEnumBuilder switchEnumBuilder (SGF.B , S, nextBufOrValue);
804
+
805
+ switchEnumBuilder.addCase (
806
+ SGF.getASTContext ().getOptionalSomeDecl (), createBasicBlock (),
807
+ loopDest.getBlock (),
808
+ [&](ManagedValue inputValue, SwitchCaseFullExpr &scope) {
809
+ SGF.emitProfilerIncrement (S->getBody ());
810
+
811
+ // Emit the loop body.
812
+ // The declared variable(s) for the current element are destroyed
813
+ // at the end of each loop iteration.
814
+ {
815
+ Scope innerForScope (SGF.Cleanups , CleanupLocation (S->getBody ()));
816
+ // Emit the initialization for the pattern. If any of the bound
817
+ // patterns
818
+ // fail (because this is a 'for case' pattern with a refutable
819
+ // pattern,
820
+ // the code should jump to the continue block.
821
+ InitializationPtr initLoopVars =
822
+ SGF.emitPatternBindingInitialization (S->getPattern (), loopDest);
823
+
824
+ // If we had a loadable "next" generator value, we know it is present.
825
+ // Get the value out of the optional, and wrap it up with a cleanup so
826
+ // that any exits out of this scope properly clean it up.
827
+ //
828
+ // *NOTE* If we do not have an address only value, then inputValue is
829
+ // *already properly unwrapped.
830
+ if (optTL.isAddressOnly ()) {
831
+ inputValue =
832
+ SGF.emitManagedBufferWithCleanup (nextBufOrValue.getValue ());
833
+ inputValue = SGF.emitUncheckedGetOptionalValueFrom (
834
+ S, inputValue, optTL, SGFContext (initLoopVars.get ()));
835
+ }
836
+
837
+ if (!inputValue.isInContext ())
838
+ RValue (SGF, S, optTy.getAnyOptionalObjectType (), inputValue)
839
+ .forwardInto (SGF, S, initLoopVars.get ());
840
+
841
+ // Now that the pattern has been initialized, check any where
842
+ // condition.
843
+ // If it fails, loop around as if 'continue' happened.
844
+ if (auto *Where = S->getWhere ()) {
845
+ auto cond =
846
+ SGF.emitCondition (Where, /* hasFalse*/ false , /* invert*/ true );
847
+ // If self is null, branch to the epilog.
848
+ cond.enterTrue (SGF);
849
+ SGF.Cleanups .emitBranchAndCleanups (loopDest, Where, {});
850
+ cond.exitTrue (SGF);
851
+ cond.complete (SGF);
852
+ }
853
+
854
+ visit (S->getBody ());
855
+ }
856
+
857
+ // If we emitted an unreachable in the body, we will not have a valid
858
+ // insertion point. Just return early.
859
+ if (!SGF.B .hasValidInsertionPoint ())
860
+ return ;
861
+
862
+ // Otherwise, associate the loop body's closing brace with this branch.
863
+ RegularLocation L (S->getBody ());
864
+ L.pointToEnd ();
865
+ scope.exit (L);
866
+ });
867
+
868
+ // We add loop fail block, just to be defensive about intermediate
869
+ // transformations performing cleanups at scope.exit(). We still jump to the
870
+ // contBlock.
871
+ switchEnumBuilder.addCase (
872
+ SGF.getASTContext ().getOptionalNoneDecl (), createBasicBlock (),
873
+ failExitingBlock,
874
+ [&](ManagedValue inputValue, SwitchCaseFullExpr &scope) {
875
+ assert (!inputValue && " None should not be passed an argument!" );
876
+ scope.exit (S);
877
+ });
878
+
879
+ std::move (switchEnumBuilder).emit ();
880
+
881
+ SGF.B .emitBlock (failExitingBlock);
847
882
emitOrDeleteBlock (SGF, endDest, S);
848
883
SGF.BreakContinueDestStack .pop_back ();
849
-
850
- // We do not need to destroy the value in the 'nextBuf' slot here, because
851
- // either the 'for' loop finished naturally and the buffer contains '.None',
852
- // or we exited by 'break' and the value in the buffer was consumed.
853
884
}
854
885
855
886
void StmtEmitter::visitBreakStmt (BreakStmt *S) {
0 commit comments