@@ -804,6 +804,97 @@ void DataflowState::init() {
804
804
}
805
805
}
806
806
807
+ // Returns true if we emitted a diagnostic and handled the single block
808
+ // case. Returns false if we visited all of the uses and seeded the UseState
809
+ // struct with the information needed to perform our interprocedural dataflow.
810
+ static bool performSingleBasicBlockAnalysis (DataflowState &dataflowState,
811
+ SILValue address,
812
+ MarkUnresolvedMoveAddrInst *mvi) {
813
+ // First scan downwards to make sure we are move out of this block.
814
+ auto &useState = dataflowState.useState ;
815
+ SILInstruction *interestingUser = nullptr ;
816
+ switch (downwardScanForMoveOut (mvi, useState, &interestingUser)) {
817
+ case DownwardScanResult::Invalid:
818
+ llvm_unreachable (" invalid" );
819
+ case DownwardScanResult::Destroy: {
820
+ // If we found a destroy, then we found a single block case that we can
821
+ // handle. Remove the destroy and convert the mark_unresolved_move_addr
822
+ // into a true move.
823
+ auto *dvi = cast<DestroyAddrInst>(interestingUser);
824
+ SILBuilderWithScope builder (mvi);
825
+ builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (), IsTake,
826
+ IsInitialization);
827
+ useState.destroys .erase (dvi);
828
+ mvi->eraseFromParent ();
829
+ dvi->eraseFromParent ();
830
+ return false ;
831
+ }
832
+ case DownwardScanResult::UseForDiagnostic: {
833
+ // Then check if we found a user that violated our dataflow rules. In such
834
+ // a case, emit an error, cleanup our mark_unresolved_move_addr, and
835
+ // finally continue.
836
+ auto &astCtx = mvi->getFunction ()->getASTContext ();
837
+ {
838
+ auto diag =
839
+ diag::sil_movekillscopyablevalue_value_consumed_more_than_once;
840
+ StringRef name = getDebugVarName (address);
841
+ diagnose (astCtx, getSourceLocFromValue (address), diag, name);
842
+ }
843
+
844
+ {
845
+ auto diag = diag::sil_movekillscopyablevalue_move_here;
846
+ diagnose (astCtx, mvi->getLoc ().getSourceLoc (), diag);
847
+ }
848
+
849
+ {
850
+ auto diag = diag::sil_movekillscopyablevalue_use_here;
851
+ diagnose (astCtx, interestingUser->getLoc ().getSourceLoc (), diag);
852
+ }
853
+
854
+ // We purposely continue to see if at least in simple cases, we can flag
855
+ // mistakes from other moves. Since we are setting emittedDiagnostic to
856
+ // true, we will not perform the actual dataflow due to a check after
857
+ // the loop.
858
+ //
859
+ // We also clean up mvi by converting it to a copy_addr init so we do not
860
+ // emit fail errors later.
861
+ //
862
+ // TODO: Can we handle multiple errors in the same block for a single
863
+ // move?
864
+ SILBuilderWithScope builder (mvi);
865
+ builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (),
866
+ IsNotTake, IsInitialization);
867
+ mvi->eraseFromParent ();
868
+ return true ;
869
+ }
870
+ case DownwardScanResult::Reinit: {
871
+ convertMemoryReinitToInitForm (interestingUser);
872
+ useState.reinits .erase (interestingUser);
873
+ SILBuilderWithScope builder (mvi);
874
+ builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (), IsTake,
875
+ IsInitialization);
876
+ mvi->eraseFromParent ();
877
+ return false ;
878
+ }
879
+ case DownwardScanResult::MoveOut:
880
+ break ;
881
+ }
882
+
883
+ // If we did not found any uses later in the block that was an interesting
884
+ // use, we need to perform dataflow.
885
+ LLVM_DEBUG (llvm::dbgs () << " Our move is live out, so we need to process "
886
+ " it with the dataflow.\n " );
887
+ dataflowState.markMovesToDataflow .emplace_back (mvi);
888
+
889
+ // Now scan up to see if mvi is also a use to seed the dataflow. This could
890
+ // happen if we have an earlier move.
891
+ if (upwardScanForUseOut (mvi, dataflowState.useState )) {
892
+ LLVM_DEBUG (llvm::dbgs () << " MVI projects a use up" );
893
+ dataflowState.useBlocks [mvi->getParent ()] = mvi;
894
+ }
895
+ return false ;
896
+ }
897
+
807
898
// ===----------------------------------------------------------------------===//
808
899
// Address Checker
809
900
// ===----------------------------------------------------------------------===//
@@ -817,7 +908,6 @@ struct MoveKillsCopyableAddressesObjectChecker {
817
908
818
909
MoveKillsCopyableAddressesObjectChecker (SILFunction *fn)
819
910
: fn(fn), useState(), dataflowState(useState) {}
820
- bool performSingleBasicBlockAnalysisForAllMarkMoves (SILValue address);
821
911
822
912
bool check (SILValue address);
823
913
@@ -829,102 +919,6 @@ struct MoveKillsCopyableAddressesObjectChecker {
829
919
830
920
} // namespace
831
921
832
- // Returns true if we emitted a diagnostic and handled the single block
833
- // case. Returns false if we visited all of the uses and seeded the UseState
834
- // struct with the information needed to perform our interprocedural dataflow.
835
- bool MoveKillsCopyableAddressesObjectChecker::
836
- performSingleBasicBlockAnalysisForAllMarkMoves (SILValue address) {
837
- bool didEmitSingleBlockDiagnostic = false ;
838
- for (auto *mvi : useState.markMoves ) {
839
- // First scan downwards to make sure we are move out of this block.
840
-
841
- SILInstruction *interestingUser = nullptr ;
842
- switch (downwardScanForMoveOut (mvi, useState, &interestingUser)) {
843
- case DownwardScanResult::Invalid:
844
- llvm_unreachable (" invalid" );
845
- case DownwardScanResult::Destroy: {
846
- // If we found a destroy, then we found a single block case that we can
847
- // handle. Remove the destroy and convert the mark_unresolved_move_addr
848
- // into a true move.
849
- auto *dvi = cast<DestroyAddrInst>(interestingUser);
850
- SILBuilderWithScope builder (mvi);
851
- builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (),
852
- IsTake, IsInitialization);
853
- useState.destroys .erase (dvi);
854
- mvi->eraseFromParent ();
855
- dvi->eraseFromParent ();
856
- continue ;
857
- }
858
- case DownwardScanResult::UseForDiagnostic: {
859
- // Then check if we found a user that violated our dataflow rules. In such
860
- // a case, emit an error, cleanup our mark_unresolved_move_addr, and
861
- // finally continue.
862
- didEmitSingleBlockDiagnostic = true ;
863
-
864
- {
865
- auto diag =
866
- diag::sil_movekillscopyablevalue_value_consumed_more_than_once;
867
- StringRef name = getDebugVarName (address);
868
- diagnose (getASTContext (), getSourceLocFromValue (address), diag, name);
869
- }
870
-
871
- {
872
- auto diag = diag::sil_movekillscopyablevalue_move_here;
873
- diagnose (getASTContext (), mvi->getLoc ().getSourceLoc (), diag);
874
- }
875
-
876
- {
877
- auto diag = diag::sil_movekillscopyablevalue_use_here;
878
- diagnose (getASTContext (), interestingUser->getLoc ().getSourceLoc (),
879
- diag);
880
- }
881
-
882
- // We purposely continue to see if at least in simple cases, we can flag
883
- // mistakes from other moves. Since we are setting emittedDiagnostic to
884
- // true, we will not perform the actual dataflow due to a check after
885
- // the loop.
886
- //
887
- // We also clean up mvi by converting it to a copy_addr init so we do not
888
- // emit fail errors later.
889
- //
890
- // TODO: Can we handle multiple errors in the same block for a single
891
- // move?
892
- SILBuilderWithScope builder (mvi);
893
- builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (),
894
- IsNotTake, IsInitialization);
895
- mvi->eraseFromParent ();
896
- continue ;
897
- }
898
- case DownwardScanResult::Reinit: {
899
- convertMemoryReinitToInitForm (interestingUser);
900
- useState.reinits .erase (interestingUser);
901
- SILBuilderWithScope builder (mvi);
902
- builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (),
903
- IsTake, IsInitialization);
904
- mvi->eraseFromParent ();
905
- continue ;
906
- }
907
- case DownwardScanResult::MoveOut:
908
- break ;
909
- }
910
-
911
- // If we did not found any uses later in the block that was an interesting
912
- // use, we need to perform dataflow.
913
- LLVM_DEBUG (llvm::dbgs () << " Our move is live out, so we need to process "
914
- " it with the dataflow.\n " );
915
- dataflowState.markMovesToDataflow .emplace_back (mvi);
916
-
917
- // Now scan up to see if mvi is also a use to seed the dataflow. This could
918
- // happen if we have an earlier move.
919
- if (upwardScanForUseOut (mvi, useState)) {
920
- LLVM_DEBUG (llvm::dbgs () << " MVI projects a use up" );
921
- dataflowState.useBlocks [mvi->getParent ()] = mvi;
922
- }
923
- }
924
-
925
- return didEmitSingleBlockDiagnostic;
926
- }
927
-
928
922
bool MoveKillsCopyableAddressesObjectChecker::check (SILValue address) {
929
923
auto accessPathWithBase = AccessPathWithBase::compute (address);
930
924
auto accessPath = accessPathWithBase.accessPath ;
@@ -968,7 +962,12 @@ bool MoveKillsCopyableAddressesObjectChecker::check(SILValue address) {
968
962
// mark_move that propagates its state out of the current block, this
969
963
// routine also prepares the pass for running the multi-basic block
970
964
// diagnostic.
971
- if (performSingleBasicBlockAnalysisForAllMarkMoves (address)) {
965
+ bool emittedSingleBBDiagnostic = false ;
966
+ for (auto *mvi : useState.markMoves ) {
967
+ emittedSingleBBDiagnostic |=
968
+ performSingleBasicBlockAnalysis (dataflowState, address, mvi);
969
+ }
970
+ if (emittedSingleBBDiagnostic) {
972
971
LLVM_DEBUG (llvm::dbgs () << " Performed single block analysis!\n " );
973
972
return true ;
974
973
}
0 commit comments