@@ -422,7 +422,10 @@ class PatternMatchEmission {
422
422
void emitDispatch (ClauseMatrix &matrix, ArgArray args,
423
423
const FailureHandler &failure);
424
424
425
- JumpDest getSharedCaseBlockDest (CaseStmt *caseStmt, bool hasFallthroughTo);
425
+ void initSharedCaseBlockDest (CaseStmt *caseBlock, bool hasFallthroughTo);
426
+
427
+ JumpDest getSharedCaseBlockDest (CaseStmt *caseStmt);
428
+
426
429
void emitSharedCaseBlocks ();
427
430
428
431
void emitCaseBody (CaseStmt *caseBlock);
@@ -2324,45 +2327,43 @@ void PatternMatchEmission::emitCaseBody(CaseStmt *caseBlock) {
2324
2327
}
2325
2328
}
2326
2329
2327
- // / Retrieve the jump destination for a shared case block.
2328
- JumpDest PatternMatchEmission::getSharedCaseBlockDest (CaseStmt *caseBlock,
2329
- bool hasFallthroughTo) {
2330
+ void PatternMatchEmission::initSharedCaseBlockDest (CaseStmt *caseBlock,
2331
+ bool hasFallthroughTo) {
2330
2332
auto result = SharedCases.insert ({caseBlock, {nullptr , hasFallthroughTo}});
2333
+ assert (result.second );
2331
2334
2332
- // If there's already an entry, use that.
2333
- SILBasicBlock *block;
2334
- if (!result.second ) {
2335
- block = result.first ->second .first ;
2336
- assert (block);
2337
- } else {
2338
- // Create the shared destination at the first place that might
2339
- // have needed it.
2340
- block = SGF.createBasicBlock ();
2341
- result.first ->second .first = block;
2335
+ auto *block = SGF.createBasicBlock ();
2336
+ result.first ->second .first = block;
2342
2337
2343
- // Add args for any pattern variables
2344
- if (caseBlock->hasBoundDecls ()) {
2345
- auto pattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
2346
- pattern->forEachVariable ([&](VarDecl *V) {
2347
- if (!V->hasName ())
2348
- return ;
2349
- // We should never PHI addresses. To eliminate that possibility, we:
2350
- //
2351
- // 1. Load all loadable types and pass them as objects to the block.
2352
- // 2. We do not emit arguments for address only types. We instead just
2353
- // assign SILUndef to the VarLoc.
2354
- SILType ty = SGF.getLoweredType (V->getType ());
2355
- if (ty.isAddressOnly (SGF.F .getModule ()))
2356
- return ;
2357
- block->createPHIArgument (ty, ValueOwnershipKind::Owned, V);
2358
- });
2359
- }
2338
+ // Add args for any pattern variables
2339
+ if (caseBlock->hasBoundDecls ()) {
2340
+ auto pattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
2341
+ pattern->forEachVariable ([&](VarDecl *V) {
2342
+ if (!V->hasName ())
2343
+ return ;
2344
+
2345
+ // We don't pass address-only values in basic block arguments.
2346
+ SILType ty = SGF.getLoweredType (V->getType ());
2347
+ if (ty.isAddressOnly (SGF.F .getModule ()))
2348
+ return ;
2349
+ block->createPHIArgument (ty, ValueOwnershipKind::Owned, V);
2350
+ });
2360
2351
}
2352
+ }
2353
+
2354
+ // / Retrieve the jump destination for a shared case block.
2355
+ JumpDest PatternMatchEmission::getSharedCaseBlockDest (CaseStmt *caseBlock) {
2356
+ auto result = SharedCases.find (caseBlock);
2357
+ assert (result != SharedCases.end ());
2358
+
2359
+ auto *block = result->second .first ;
2360
+ assert (block);
2361
2361
2362
2362
return JumpDest (block, PatternMatchStmtDepth,
2363
2363
CleanupLocation (PatternMatchStmt));
2364
2364
}
2365
2365
2366
+
2366
2367
// / Emit all the shared case statements.
2367
2368
void PatternMatchEmission::emitSharedCaseBlocks () {
2368
2369
for (auto &entry: SharedCases) {
@@ -2386,8 +2387,13 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
2386
2387
SGF.B .setInsertionPoint (predBB);
2387
2388
2388
2389
} else {
2390
+ // FIXME: Figure out why this is necessary.
2391
+ if (caseBB->pred_empty ()) {
2392
+ SGF.eraseBasicBlock (caseBB);
2393
+ continue ;
2394
+ }
2395
+
2389
2396
// Otherwise, move the block to after the first predecessor.
2390
- assert (!caseBB->pred_empty () && " Emitted an unused shared block?" );
2391
2397
auto predBB = *caseBB->pred_begin ();
2392
2398
caseBB->moveAfter (predBB);
2393
2399
@@ -2593,12 +2599,11 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2593
2599
if (!caseBlock->hasBoundDecls ()) {
2594
2600
// Don't emit anything yet, we emit it at the cleanup level of the switch
2595
2601
// statement.
2596
- JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock,
2597
- row.hasFallthroughTo ());
2602
+ JumpDest sharedDest = emission.getSharedCaseBlockDest (caseBlock);
2598
2603
Cleanups.emitBranchAndCleanups (sharedDest, caseBlock);
2599
2604
} else if (caseBlock->getCaseLabelItems ().size () > 1 ) {
2600
2605
JumpDest sharedDest =
2601
- emission.getSharedCaseBlockDest (caseBlock, row. hasFallthroughTo () );
2606
+ emission.getSharedCaseBlockDest (caseBlock);
2602
2607
2603
2608
// Generate the arguments from this row's pattern in the case block's expected order,
2604
2609
// and keep those arguments from being cleaned up, as we're passing the +1 along to
@@ -2679,6 +2684,12 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2679
2684
clauseRows.reserve (S->getRawCases ().size ());
2680
2685
bool hasFallthrough = false ;
2681
2686
for (auto caseBlock : S->getCases ()) {
2687
+ if (!caseBlock->hasBoundDecls () ||
2688
+ caseBlock->getCaseLabelItems ().size () > 1 ||
2689
+ hasFallthrough) {
2690
+ emission.initSharedCaseBlockDest (caseBlock, hasFallthrough);
2691
+ }
2692
+
2682
2693
for (auto &labelItem : caseBlock->getCaseLabelItems ()) {
2683
2694
clauseRows.emplace_back (caseBlock,
2684
2695
const_cast <Pattern*>(labelItem.getPattern ()),
@@ -2721,7 +2732,7 @@ void SILGenFunction::emitSwitchFallthrough(FallthroughStmt *S) {
2721
2732
// Get the destination block.
2722
2733
CaseStmt *caseStmt = S->getFallthroughDest ();
2723
2734
JumpDest sharedDest =
2724
- context->Emission .getSharedCaseBlockDest (caseStmt, true );
2735
+ context->Emission .getSharedCaseBlockDest (caseStmt);
2725
2736
Cleanups.emitBranchAndCleanups (sharedDest, S);
2726
2737
}
2727
2738
0 commit comments