@@ -2631,6 +2631,81 @@ static void emitDiagnoseOfUnexpectedEnumCase(SILGenFunction &SGF,
2631
2631
SGFContext ());
2632
2632
}
2633
2633
2634
+ static void switchCaseStmtSuccessCallback (SILGenFunction &SGF,
2635
+ PatternMatchEmission &emission,
2636
+ ArgArray argArray, ClauseRow &row) {
2637
+ auto caseBlock = row.getClientData <CaseStmt>();
2638
+ SGF.emitProfilerIncrement (caseBlock);
2639
+
2640
+ // Certain case statements can be entered along multiple paths, either
2641
+ // because they have multiple labels or because of fallthrough. When we
2642
+ // need multiple entrance path, we factor the paths with a shared block.
2643
+ if (!caseBlock->hasBoundDecls ()) {
2644
+ // Don't emit anything yet, we emit it at the cleanup level of the switch
2645
+ // statement.
2646
+ JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2647
+ SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock);
2648
+ return ;
2649
+ }
2650
+
2651
+ // If we don't have a fallthrough or a multi-pattern 'case', we can just
2652
+ // emit the body inline and save some dead blocks. Emit the statement here.
2653
+ if (!row.hasFallthroughTo () && caseBlock->getCaseLabelItems ().size () == 1 ) {
2654
+ emission.emitCaseBody (caseBlock);
2655
+ return ;
2656
+ }
2657
+
2658
+ JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2659
+
2660
+ // Generate the arguments from this row's pattern in the case block's
2661
+ // expected order, and keep those arguments from being cleaned up, as
2662
+ // we're passing the +1 along to the shared case block dest. (The
2663
+ // cleanups still happen, as they are threaded through here messily,
2664
+ // but the explicit retains here counteract them, and then the
2665
+ // retain/release pair gets optimized out.)
2666
+ ArrayRef<CaseLabelItem> labelItems = caseBlock->getCaseLabelItems ();
2667
+ SmallVector<SILValue, 4 > args;
2668
+ SmallVector<VarDecl *, 4 > expectedVarOrder;
2669
+ SmallVector<VarDecl *, 4 > vars;
2670
+ labelItems[0 ].getPattern ()->collectVariables (expectedVarOrder);
2671
+ row.getCasePattern ()->collectVariables (vars);
2672
+
2673
+ SILModule &M = SGF.F .getModule ();
2674
+ for (auto expected : expectedVarOrder) {
2675
+ if (!expected->hasName ())
2676
+ continue ;
2677
+ for (auto *var : vars) {
2678
+ if (!var->hasName () || var->getName () != expected->getName ())
2679
+ continue ;
2680
+
2681
+ SILValue value = SGF.VarLocs [var].value ;
2682
+ SILType type = value->getType ();
2683
+
2684
+ // If we have an address-only type, initialize the temporary
2685
+ // allocation. We're not going to pass the address as a block
2686
+ // argument.
2687
+ if (type.isAddressOnly (M)) {
2688
+ emission.emitAddressOnlyInitialization (expected, value);
2689
+ break ;
2690
+ }
2691
+
2692
+ // If we have a loadable address, perform a load [copy].
2693
+ if (type.isAddress ()) {
2694
+ value = SGF.B .emitLoadValueOperation (SGF.CurrentSILLoc , value,
2695
+ LoadOwnershipQualifier::Copy);
2696
+ args.push_back (value);
2697
+ break ;
2698
+ }
2699
+
2700
+ value = SGF.B .emitCopyValueOperation (SGF.CurrentSILLoc , value);
2701
+ args.push_back (value);
2702
+ break ;
2703
+ }
2704
+ }
2705
+
2706
+ SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock, args);
2707
+ }
2708
+
2634
2709
void SILGenFunction::emitSwitchStmt (SwitchStmt *S) {
2635
2710
LLVM_DEBUG (llvm::dbgs () << " emitting switch stmt\n " ;
2636
2711
S->dump (llvm::dbgs ());
@@ -2646,81 +2721,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2646
2721
return ;
2647
2722
}
2648
2723
2649
- auto completionHandler = [&](PatternMatchEmission &emission,
2650
- ArgArray argArray,
2651
- ClauseRow &row) {
2652
- auto caseBlock = row.getClientData <CaseStmt>();
2653
- emitProfilerIncrement (caseBlock);
2654
-
2655
- // Certain case statements can be entered along multiple paths, either
2656
- // because they have multiple labels or because of fallthrough. When we
2657
- // need multiple entrance path, we factor the paths with a shared block.
2658
- if (!caseBlock->hasBoundDecls ()) {
2659
- // Don't emit anything yet, we emit it at the cleanup level of the switch
2660
- // statement.
2661
- JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2662
- Cleanups.emitBranchAndCleanups (sharedDest, caseBlock);
2663
- return ;
2664
- }
2665
-
2666
- // If we don't have a fallthrough or a multi-pattern 'case', we can just
2667
- // emit the body inline and save some dead blocks. Emit the statement here.
2668
- if (!row.hasFallthroughTo () && caseBlock->getCaseLabelItems ().size () == 1 ) {
2669
- emission.emitCaseBody (caseBlock);
2670
- return ;
2671
- }
2672
-
2673
- JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2674
-
2675
- // Generate the arguments from this row's pattern in the case block's
2676
- // expected order, and keep those arguments from being cleaned up, as
2677
- // we're passing the +1 along to the shared case block dest. (The
2678
- // cleanups still happen, as they are threaded through here messily,
2679
- // but the explicit retains here counteract them, and then the
2680
- // retain/release pair gets optimized out.)
2681
- ArrayRef<CaseLabelItem> labelItems = caseBlock->getCaseLabelItems ();
2682
- SmallVector<SILValue, 4 > args;
2683
- SmallVector<VarDecl *, 4 > expectedVarOrder;
2684
- SmallVector<VarDecl *, 4 > vars;
2685
- labelItems[0 ].getPattern ()->collectVariables (expectedVarOrder);
2686
- row.getCasePattern ()->collectVariables (vars);
2687
-
2688
- SILModule &M = F.getModule ();
2689
- for (auto expected : expectedVarOrder) {
2690
- if (!expected->hasName ())
2691
- continue ;
2692
- for (auto *var : vars) {
2693
- if (!var->hasName () || var->getName () != expected->getName ())
2694
- continue ;
2695
-
2696
- SILValue value = VarLocs[var].value ;
2697
- SILType type = value->getType ();
2698
-
2699
- // If we have an address-only type, initialize the temporary
2700
- // allocation. We're not going to pass the address as a block
2701
- // argument.
2702
- if (type.isAddressOnly (M)) {
2703
- emission.emitAddressOnlyInitialization (expected, value);
2704
- break ;
2705
- }
2706
-
2707
- // If we have a loadable address, perform a load [copy].
2708
- if (type.isAddress ()) {
2709
- value = B.emitLoadValueOperation (CurrentSILLoc, value,
2710
- LoadOwnershipQualifier::Copy);
2711
- args.push_back (value);
2712
- break ;
2713
- }
2714
-
2715
- value = B.emitCopyValueOperation (CurrentSILLoc, value);
2716
- args.push_back (value);
2717
- break ;
2718
- }
2719
- }
2720
-
2721
- Cleanups.emitBranchAndCleanups (sharedDest, caseBlock, args);
2724
+ auto completionHandler = [this ](PatternMatchEmission &emission,
2725
+ ArgArray argArray, ClauseRow &row) {
2726
+ return switchCaseStmtSuccessCallback (*this , emission, argArray, row);
2722
2727
};
2723
-
2724
2728
PatternMatchEmission emission (*this , S, completionHandler);
2725
2729
2726
2730
// Add a row for each label of each case.
0 commit comments