@@ -2631,6 +2631,81 @@ static void emitDiagnoseOfUnexpectedEnumCase(SILGenFunction &SGF,
26312631 SGFContext ());
26322632}
26332633
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+
26342709void SILGenFunction::emitSwitchStmt (SwitchStmt *S) {
26352710 LLVM_DEBUG (llvm::dbgs () << " emitting switch stmt\n " ;
26362711 S->dump (llvm::dbgs ());
@@ -2646,81 +2721,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
26462721 return ;
26472722 }
26482723
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);
27222727 };
2723-
27242728 PatternMatchEmission emission (*this , S, completionHandler);
27252729
27262730 // Add a row for each label of each case.
0 commit comments