@@ -408,6 +408,8 @@ class PatternMatchEmission {
408
408
CleanupsDepth PatternMatchStmtDepth;
409
409
llvm::MapVector<CaseStmt*, std::pair<SILBasicBlock*, bool >> SharedCases;
410
410
411
+ llvm::DenseMap<VarDecl*, SILValue> Temporaries;
412
+
411
413
using CompletionHandlerTy =
412
414
llvm::function_ref<void (PatternMatchEmission &, ArgArray, ClauseRow &)>;
413
415
CompletionHandlerTy CompletionHandler;
@@ -416,14 +418,17 @@ class PatternMatchEmission {
416
418
PatternMatchEmission (SILGenFunction &SGF, Stmt *S,
417
419
CompletionHandlerTy completionHandler)
418
420
: SGF(SGF), PatternMatchStmt(S),
419
- PatternMatchStmtDepth (SGF.getCleanupsDepth()),
420
421
CompletionHandler (completionHandler) {}
421
422
422
423
void emitDispatch (ClauseMatrix &matrix, ArgArray args,
423
424
const FailureHandler &failure);
424
425
425
426
void initSharedCaseBlockDest (CaseStmt *caseBlock, bool hasFallthroughTo);
426
427
428
+ void emitAddressOnlyAllocations ();
429
+
430
+ void emitAddressOnlyInitialization (VarDecl *dest, SILValue value);
431
+
427
432
JumpDest getSharedCaseBlockDest (CaseStmt *caseStmt);
428
433
429
434
void emitSharedCaseBlocks ();
@@ -2363,6 +2368,42 @@ JumpDest PatternMatchEmission::getSharedCaseBlockDest(CaseStmt *caseBlock) {
2363
2368
CleanupLocation (PatternMatchStmt));
2364
2369
}
2365
2370
2371
+ void PatternMatchEmission::emitAddressOnlyAllocations () {
2372
+ for (auto &entry: SharedCases) {
2373
+ CaseStmt *caseBlock = entry.first ;
2374
+
2375
+ // If we have a shared case with bound decls, then the 0th pattern has the
2376
+ // order of variables that are the incoming BB arguments. Setup the VarLocs
2377
+ // to point to the incoming args and setup initialization so any args needing
2378
+ // cleanup will get that as well.
2379
+ if (caseBlock->hasBoundDecls ()) {
2380
+ auto pattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
2381
+ pattern->forEachVariable ([&](VarDecl *V) {
2382
+ if (!V->hasName ())
2383
+ return ;
2384
+
2385
+ SILType ty = SGF.getLoweredType (V->getType ());
2386
+
2387
+ if (ty.isAddressOnly (SGF.F .getModule ())) {
2388
+ assert (!Temporaries[V]);
2389
+ Temporaries[V] = SGF.emitTemporaryAllocation (V, ty);
2390
+ return ;
2391
+ }
2392
+ });
2393
+ }
2394
+ }
2395
+
2396
+ // Now we have all of our cleanups entered, so we can record the
2397
+ // depth.
2398
+ PatternMatchStmtDepth = SGF.getCleanupsDepth ();
2399
+ }
2400
+
2401
+ void PatternMatchEmission::
2402
+ emitAddressOnlyInitialization (VarDecl *dest, SILValue value) {
2403
+ auto found = Temporaries.find (dest);
2404
+ assert (found != Temporaries.end ());
2405
+ SGF.B .createCopyAddr (dest, value, found->second , IsNotTake, IsInitialization);
2406
+ }
2366
2407
2367
2408
// / Emit all the shared case statements.
2368
2409
void PatternMatchEmission::emitSharedCaseBlocks () {
@@ -2416,27 +2457,37 @@ void PatternMatchEmission::emitSharedCaseBlocks() {
2416
2457
return ;
2417
2458
2418
2459
SILType ty = SGF.getLoweredType (V->getType ());
2460
+
2461
+ SILValue value;
2419
2462
if (ty.isAddressOnly (SGF.F .getModule ())) {
2420
- // Just assign SILUndef as a value for address only values.
2421
- SGF.VarLocs [V].value = SILUndef::get (ty, SGF.F .getModule ());
2422
- return ;
2463
+ // There's no basic block argument, since we don't allow basic blocks
2464
+ // to have address arguments.
2465
+ //
2466
+ // Instead, we map the variable to a temporary alloc_stack in
2467
+ // emitAddressOnlyAllocations(), and store into it at each
2468
+ // predecessor block.
2469
+ //
2470
+ // There's nothing to do here, since the value should already have
2471
+ // been initialized on entry.
2472
+ auto found = Temporaries.find (V);
2473
+ assert (found != Temporaries.end ());
2474
+ value = found->second ;
2475
+ } else {
2476
+ value = caseBB->getArgument (argIndex++);
2423
2477
}
2424
2478
2425
2479
if (V->isLet ()) {
2426
2480
// Just emit a let with cleanup.
2427
- SGF.VarLocs [V].value = caseBB->getArgument (argIndex++);
2428
- SGF.emitInitializationForVarDecl (V, V->isLet ())
2429
- ->finishInitialization (SGF);
2481
+ SGF.VarLocs [V].value = value;
2482
+ SGF.enterDestroyCleanup (value);
2430
2483
} else {
2431
2484
// The pattern variables were all emitted as lets and one got passed in,
2432
2485
// now we finally alloc a box for the var and forward in the chosen value.
2433
2486
SGF.VarLocs .erase (V);
2434
2487
auto newVar = SGF.emitInitializationForVarDecl (V, V->isLet ());
2435
- auto loc = SGF.CurrentSILLoc ;
2436
- auto value =
2437
- ManagedValue::forUnmanaged (caseBB->getArgument (argIndex++));
2438
- auto formalType = V->getType ()->getCanonicalType ();
2439
- RValue (SGF, loc, formalType, value).forwardInto (SGF, loc, newVar.get ());
2488
+ auto mv = ManagedValue::forUnmanaged (value);
2489
+ newVar->copyOrInitValueInto (SGF, V, mv, /* isInit*/ true );
2490
+ newVar->finishInitialization (SGF);
2440
2491
}
2441
2492
});
2442
2493
emitCaseBody (caseBlock);
@@ -2535,35 +2586,6 @@ void SILGenFunction::usingImplicitVariablesForPattern(Pattern *pattern, CaseStmt
2535
2586
variableSwapper ();
2536
2587
}
2537
2588
2538
- static void diagnoseMultiPatternCaseAddressOnlyBinding (SILGenFunction &SGF,
2539
- ValueDecl *decl,
2540
- SILValue value) {
2541
- SILLocation loc (decl);
2542
-
2543
- // Try to figure out why this is an address only type. This is just an
2544
- // approximation. The targets of interest are:
2545
- //
2546
- // 1. existentials.
2547
- // 2. generics.
2548
- //
2549
- // If we are unable to show that we have an existential or generic, we use the
2550
- // more general unknown_addressonly_type_used_in_multipattern_case diagnostic.
2551
- unsigned errorPatternIndex = 0 ;
2552
- CanType ty = value->getType ().getSwiftRValueType ();
2553
-
2554
- if (ty.findIf ([&](Type ty) -> bool {
2555
- return ty->is <ProtocolType>() || ty->is <ProtocolCompositionType>();
2556
- })) {
2557
- errorPatternIndex = 1 ;
2558
- } else if (ty.findIf (
2559
- [&](Type ty) -> bool { return ty->is <ArchetypeType>(); })) {
2560
- errorPatternIndex = 2 ;
2561
- }
2562
-
2563
- SGF.SGM .diagnose (loc, diag::addressonly_type_used_in_multipattern_case,
2564
- errorPatternIndex, ty);
2565
- }
2566
-
2567
2589
void SILGenFunction::emitSwitchStmt (SwitchStmt *S) {
2568
2590
DEBUG (llvm::dbgs () << " emitting switch stmt\n " ;
2569
2591
S->print (llvm::dbgs ());
@@ -2581,8 +2603,6 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2581
2603
return failure (SILLocation (S));
2582
2604
}
2583
2605
2584
- bool diagnosedError = false ;
2585
-
2586
2606
auto completionHandler = [&](PatternMatchEmission &emission,
2587
2607
ArgArray argArray,
2588
2608
ClauseRow &row) {
@@ -2601,16 +2621,12 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2601
2621
JumpDest sharedDest =
2602
2622
emission.getSharedCaseBlockDest (caseBlock);
2603
2623
2604
- // Generate the arguments from this row's pattern in the case block's expected order,
2605
- // and keep those arguments from being cleaned up, as we're passing the +1 along to
2606
- // the shared case block dest. (The cleanups still happen, as they are threaded through
2607
- // here messily, but the explicit retains here counteract them, and then the
2624
+ // Generate the arguments from this row's pattern in the case block's
2625
+ // expected order, and keep those arguments from being cleaned up, as
2626
+ // we're passing the +1 along to the shared case block dest. (The
2627
+ // cleanups still happen, as they are threaded through here messily,
2628
+ // but the explicit retains here counteract them, and then the
2608
2629
// retain/release pair gets optimized out.)
2609
- //
2610
- // *NOTE*. We assume that all values are passed as objects for
2611
- // simplicity. This is ok to do since any time we diagnose an error, we
2612
- // pass SILUndef to the shared case block. This is to maintain the CFG
2613
- // structure and thus prevent spurious 'dead code' warnings.
2614
2630
ArrayRef<CaseLabelItem> labelItems = caseBlock->getCaseLabelItems ();
2615
2631
SmallVector<SILValue, 4 > args;
2616
2632
SmallVector<VarDecl *, 4 > expectedVarOrder;
@@ -2626,10 +2642,12 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2626
2642
if (var->hasName () && var->getName () == expected->getName ()) {
2627
2643
SILValue value = VarLocs[var].value ;
2628
2644
SILType type = value->getType ();
2645
+
2646
+ // If we have an address-only type, initialize the temporary
2647
+ // allocation. We're not going to pass the address as a block
2648
+ // argument.
2629
2649
if (type.isAddressOnly (M)) {
2630
- if (!diagnosedError)
2631
- diagnoseMultiPatternCaseAddressOnlyBinding (*this , var, value);
2632
- diagnosedError = true ;
2650
+ emission.emitAddressOnlyInitialization (expected, value);
2633
2651
break ;
2634
2652
}
2635
2653
@@ -2683,6 +2701,10 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
2683
2701
hasFallthrough = containsFallthrough (caseBlock->getBody ());
2684
2702
}
2685
2703
2704
+ // Emit alloc_stacks for address-only variables appearing in
2705
+ // multiple-entry case blocks.
2706
+ emission.emitAddressOnlyAllocations ();
2707
+
2686
2708
SILBasicBlock *contBB = createBasicBlock ();
2687
2709
emitProfilerIncrement (S);
2688
2710
JumpDest contDest (contBB, Cleanups.getCleanupsDepth (), CleanupLocation (S));
0 commit comments