@@ -445,6 +445,12 @@ class PatternMatchEmission {
445445
446446 void emitCaseBody (CaseStmt *caseBlock);
447447
448+ SILValue getAddressOnlyTemporary (VarDecl *decl) {
449+ auto found = Temporaries.find (decl);
450+ assert (found != Temporaries.end ());
451+ return found->second ;
452+ }
453+
448454private:
449455 void emitWildcardDispatch (ClauseMatrix &matrix, ArgArray args, unsigned row,
450456 const FailureHandler &failure);
@@ -2326,16 +2332,12 @@ void PatternMatchEmission::initSharedCaseBlockDest(CaseStmt *caseBlock,
23262332 auto *block = SGF.createBasicBlock ();
23272333 result.first ->second .first = block;
23282334
2329- // If we do not have any bound decls, we do not need to setup any phi
2330- // arguments for the shared case block. Just bail early.
2331- if (!caseBlock-> hasBoundDecls ()) {
2335+ // Add args for any pattern variables
2336+ auto caseBodyVars = caseBlock-> getCaseBodyVariables ();
2337+ if (!caseBodyVars)
23322338 return ;
2333- }
23342339
2335- auto pattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
2336- SmallVector<VarDecl *, 4 > patternVarDecls;
2337- pattern->collectVariables (patternVarDecls);
2338- for (auto *vd : patternVarDecls) {
2340+ for (auto *vd : *caseBodyVars) {
23392341 if (!vd->hasName ())
23402342 continue ;
23412343
@@ -2363,39 +2365,18 @@ void PatternMatchEmission::emitAddressOnlyAllocations() {
23632365 for (auto &entry : SharedCases) {
23642366 CaseStmt *caseBlock = entry.first ;
23652367
2366- // If we do not have any bound decls, we can bail early.
2367- if (!caseBlock-> hasBoundDecls ()) {
2368+ auto caseBodyVars = caseBlock-> getCaseBodyVariables ();
2369+ if (!caseBodyVars)
23682370 continue ;
2369- }
23702371
2371- // If we have a shared case with bound decls, then the 0th pattern has the
2372- // order of variables that are the incoming BB arguments. Setup the VarLocs
2373- // to point to the incoming args and setup initialization so any args needing
2374- // cleanup will get that as well.
2375- auto pattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
2376- SmallVector<VarDecl *, 4 > patternVarDecls;
2377- pattern->collectVariables (patternVarDecls);
2378- for (auto *vd : patternVarDecls) {
2372+ // If we have a shared case with bound decls, setup the arguments for the
2373+ // shared block by emitting the temporary allocation used for the arguments
2374+ // of the shared block.
2375+ for (auto *vd : *caseBodyVars) {
23792376 if (!vd->hasName ())
23802377 continue ;
23812378
23822379 SILType ty = SGF.getLoweredType (vd->getType ());
2383- if (ty.isNull ()) {
2384- // If we're making the shared block on behalf of a previous case's
2385- // fallthrough, caseBlock's VarDecl's won't be in the SGF yet, so
2386- // determine phi types by using current vars of the same name.
2387- for (auto var : SGF.VarLocs ) {
2388- auto varDecl = dyn_cast<VarDecl>(var.getFirst ());
2389- if (!varDecl || !varDecl->hasName () ||
2390- varDecl->getName () != vd->getName ())
2391- continue ;
2392- ty = var.getSecond ().value ->getType ();
2393- if (var.getSecond ().box ) {
2394- ty = ty.getObjectType ();
2395- }
2396- }
2397- }
2398-
23992380 if (!ty.isAddressOnly (SGF.F .getModule ()))
24002381 continue ;
24012382 assert (!Temporaries[vd]);
@@ -2455,23 +2436,19 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
24552436 assert (SGF.getCleanupsDepth () == PatternMatchStmtDepth);
24562437 SWIFT_DEFER { assert (SGF.getCleanupsDepth () == PatternMatchStmtDepth); };
24572438
2458- // If we do not have any bound decls, just emit the case body since we do
2459- // not need to setup any var locs.
2460- if (!caseBlock->hasBoundDecls ()) {
2439+ auto caseBodyVars = caseBlock->getCaseBodyVariables ();
2440+ if (!caseBodyVars) {
24612441 emitCaseBody (caseBlock);
24622442 continue ;
24632443 }
24642444
2465- // If we have a shared case with bound decls, then the 0th pattern has the
2466- // order of variables that are the incoming BB arguments. Setup the VarLocs
2467- // to point to the incoming args and setup initialization so any args
2468- // needing cleanup will get that as well.
2445+ // If we have a shared case with bound decls, then the case stmt pattern has
2446+ // the order of variables that are the incoming BB arguments. Setup the
2447+ // VarLocs to point to the incoming args and setup initialization so any
2448+ // args needing Cleanup will get that as well.
24692449 Scope scope (SGF.Cleanups , CleanupLocation (caseBlock));
2470- auto pattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
2471- SmallVector<VarDecl *, 4 > patternVarDecls;
2472- pattern->collectVariables (patternVarDecls);
24732450 unsigned argIndex = 0 ;
2474- for (auto *vd : patternVarDecls ) {
2451+ for (auto *vd : *caseBodyVars ) {
24752452 if (!vd->hasName ())
24762453 continue ;
24772454
@@ -2622,10 +2599,33 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26222599
26232600 // Certain case statements can be entered along multiple paths, either because
26242601 // they have multiple labels or because of fallthrough. When we need multiple
2625- // entrance path, we factor the paths with a shared block. If we don't have a
2626- // fallthrough or a multi-pattern 'case', we can just emit the body inline and
2627- // save some dead blocks. Emit the statement here and bail early.
2602+ // entrance path, we factor the paths with a shared block.
2603+ //
2604+ // If we don't have a fallthrough or a multi-pattern 'case', we can emit the
2605+ // body inline. Emit the statement here and bail early.
26282606 if (!row.hasFallthroughTo () && caseBlock->getCaseLabelItems ().size () == 1 ) {
2607+ // If we have case body vars, set them up to point at the matching var
2608+ // decls.
2609+ if (auto caseBodyVars = caseBlock->getCaseBodyVariables ()) {
2610+ // Since we know that we only have one case label item, grab its pattern
2611+ // vars and use that to update expected with the right SILValue.
2612+ //
2613+ // TODO: Do we need a copy here?
2614+ SmallVector<VarDecl *, 4 > patternVars;
2615+ row.getCasePattern ()->collectVariables (patternVars);
2616+ for (auto *expected : *caseBodyVars) {
2617+ if (!expected->hasName ())
2618+ continue ;
2619+ for (auto *vd : patternVars) {
2620+ if (!vd->hasName () || vd->getName () != expected->getName ()) {
2621+ continue ;
2622+ }
2623+
2624+ // Ok, we found a match. Update the VarLocs for the case block.
2625+ SGF.VarLocs [expected] = SGF.VarLocs [vd];
2626+ }
2627+ }
2628+ }
26292629 emission.emitCaseBody (caseBlock);
26302630 return ;
26312631 }
@@ -2639,7 +2639,10 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26392639
26402640 // If we do not have any bound decls, we do not need to setup any
26412641 // variables. Just jump to the shared destination.
2642- if (!caseBlock->hasBoundDecls ()) {
2642+ auto caseBodyVars = caseBlock->getCaseBodyVariables ();
2643+ if (!caseBodyVars) {
2644+ // Don't emit anything yet, we emit it at the cleanup level of the switch
2645+ // statement.
26432646 JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
26442647 SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock);
26452648 return ;
@@ -2650,18 +2653,14 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26502653 // +1 along to the shared case block dest. (The cleanups still happen, as they
26512654 // are threaded through here messily, but the explicit retains here counteract
26522655 // them, and then the retain/release pair gets optimized out.)
2653- ArrayRef<CaseLabelItem> labelItems = caseBlock->getCaseLabelItems ();
26542656 SmallVector<SILValue, 4 > args;
2655- SmallVector<VarDecl *, 4 > expectedVarOrder;
2656- SmallVector<VarDecl *, 4 > vars;
2657- labelItems[0 ].getPattern ()->collectVariables (expectedVarOrder);
2658- row.getCasePattern ()->collectVariables (vars);
2659-
26602657 SILModule &M = SGF.F .getModule ();
2661- for (auto expected : expectedVarOrder) {
2658+ SmallVector<VarDecl *, 4 > patternVars;
2659+ row.getCasePattern ()->collectVariables (patternVars);
2660+ for (auto *expected : *caseBodyVars) {
26622661 if (!expected->hasName ())
26632662 continue ;
2664- for (auto *var : vars ) {
2663+ for (auto *var : patternVars ) {
26652664 if (!var->hasName () || var->getName () != expected->getName ())
26662665 continue ;
26672666
@@ -2690,6 +2689,7 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
26902689 }
26912690 }
26922691
2692+ // Now that we have initialized our arguments, branch to the shared dest.
26932693 SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock, args);
26942694}
26952695
@@ -2837,45 +2837,46 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
28372837void SILGenFunction::emitSwitchFallthrough (FallthroughStmt *S) {
28382838 assert (!SwitchStack.empty () && " fallthrough outside of switch?!" );
28392839 PatternMatchContext *context = SwitchStack.back ();
2840-
2840+
28412841 // Get the destination block.
2842- CaseStmt *caseStmt = S->getFallthroughDest ();
2843- JumpDest sharedDest =
2844- context->Emission .getSharedCaseBlockDest (caseStmt);
2842+ CaseStmt *destCaseStmt = S->getFallthroughDest ();
2843+ JumpDest sharedDest = context->Emission .getSharedCaseBlockDest (destCaseStmt);
28452844
2846- if (!caseStmt->hasBoundDecls ()) {
2845+ // If our destination case doesn't have any bound decls, there is no rebinding
2846+ // to do. Just jump to the shared dest.
2847+ auto destCaseBodyVars = destCaseStmt->getCaseBodyVariables ();
2848+ if (!destCaseBodyVars) {
28472849 Cleanups.emitBranchAndCleanups (sharedDest, S);
28482850 return ;
28492851 }
28502852
28512853 // Generate branch args to pass along current vars to fallthrough case.
28522854 SILModule &M = F.getModule ();
2853- ArrayRef<CaseLabelItem> labelItems = caseStmt->getCaseLabelItems ();
28542855 SmallVector<SILValue, 4 > args;
2855- SmallVector<VarDecl *, 4 > expectedVarOrder;
2856- labelItems[0 ].getPattern ()->collectVariables (expectedVarOrder);
2856+ CaseStmt *fallthroughSourceStmt = S->getFallthroughSource ();
28572857
2858- for (auto *expected : expectedVarOrder ) {
2858+ for (auto *expected : *destCaseBodyVars ) {
28592859 if (!expected->hasName ())
28602860 continue ;
2861- for (auto var : VarLocs) {
2862- auto varDecl = dyn_cast<VarDecl>(var.getFirst ());
2863- if (!varDecl || !varDecl->hasName () ||
2864- varDecl->getName () != expected->getName ()) {
2861+
2862+ // The type checker enforces that if our destination case has variables then
2863+ // our fallthrough source must as well.
2864+ for (auto *var : *fallthroughSourceStmt->getCaseBodyVariables ()) {
2865+ if (!var->hasName () || var->getName () != expected->getName ()) {
28652866 continue ;
28662867 }
28672868
2868- SILValue value = var.getSecond ().value ;
2869+ auto varLoc = VarLocs[var];
2870+ SILValue value = varLoc.value ;
28692871
28702872 if (value->getType ().isAddressOnly (M)) {
28712873 context->Emission .emitAddressOnlyInitialization (expected, value);
28722874 break ;
28732875 }
28742876
2875- if (var.getSecond ().box ) {
2876- auto &lowering = getTypeLowering (value->getType ());
2877- auto argValue = lowering.emitLoad (B, CurrentSILLoc, value,
2878- LoadOwnershipQualifier::Copy);
2877+ if (varLoc.box ) {
2878+ SILValue argValue = B.emitLoadValueOperation (
2879+ CurrentSILLoc, value, LoadOwnershipQualifier::Copy);
28792880 args.push_back (argValue);
28802881 break ;
28812882 }
0 commit comments