@@ -756,16 +756,16 @@ class LetValueInitialization : public Initialization {
756
756
address = SGF.B .createMarkUninitializedVar (vd, address);
757
757
DestroyCleanup = SGF.enterDormantTemporaryCleanup (address, *lowering);
758
758
SGF.VarLocs [vd] = SILGenFunction::VarLoc::get (address);
759
- } else if (!lowering->isTrivial ()) {
760
- // Push a cleanup to destroy the let declaration. This has to be
761
- // inactive until the variable is initialized: if control flow exits the
762
- // before the value is bound, we don't want to destroy the value.
763
- SGF.Cleanups .pushCleanupInState <DestroyLocalVariable>(
764
- CleanupState::Dormant, vd);
765
- DestroyCleanup = SGF.Cleanups .getTopCleanup ();
766
- } else {
767
- DestroyCleanup = CleanupHandle::invalid ();
768
759
}
760
+ // Push a cleanup to destroy the let declaration. This has to be
761
+ // inactive until the variable is initialized: if control flow exits the
762
+ // before the value is bound, we don't want to destroy the value.
763
+ //
764
+ // Cleanups are required for all lexically scoped variables to delimite
765
+ // the variable scope, even if the cleanup does nothing.
766
+ SGF.Cleanups .pushCleanupInState <DestroyLocalVariable>(
767
+ CleanupState::Dormant, vd);
768
+ DestroyCleanup = SGF.Cleanups .getTopCleanup ();
769
769
}
770
770
771
771
~LetValueInitialization () override {
@@ -810,50 +810,26 @@ class LetValueInitialization : public Initialization {
810
810
SplitCleanups);
811
811
}
812
812
813
- // / This is a helper method for bindValue that handles any changes to the
814
- // / value needed for lexical lifetime or no implicit copy purposes.
813
+ // / This is a helper method for bindValue that creates a scopes operation for
814
+ // / the lexical variable lifetime and handles any changes to the value needed
815
+ // / for move-only values.
815
816
SILValue getValueForLexicalLifetimeBinding (SILGenFunction &SGF,
816
817
SILLocation PrologueLoc,
817
818
SILValue value, bool wasPlusOne) {
818
- // If we have none...
819
- if (value->getOwnershipKind () == OwnershipKind::None) {
820
- // Then check if we have a pure move only type. In that case, we need to
821
- // insert a no implicit copy
822
- if (value->getType ().isMoveOnly (/* orWrapped=*/ false )) {
823
- value = SGF.B .createMoveValue (PrologueLoc, value, IsLexical);
824
- return SGF.B .createMarkUnresolvedNonCopyableValueInst (
825
- PrologueLoc, value,
826
- MarkUnresolvedNonCopyableValueInst::CheckKind::
827
- ConsumableAndAssignable);
828
- }
829
-
830
- // If we have a no implicit copy trivial type, wrap it in the move only
831
- // wrapper and mark it as needing checking by the move checker.
832
- if (vd->isNoImplicitCopy () && value->getType ().isTrivial (SGF.F )) {
833
- value =
834
- SGF.B .createOwnedCopyableToMoveOnlyWrapperValue (PrologueLoc, value);
835
- value = SGF.B .createMoveValue (PrologueLoc, value, IsLexical);
836
- return SGF.B .createMarkUnresolvedNonCopyableValueInst (
837
- PrologueLoc, value,
838
- MarkUnresolvedNonCopyableValueInst::CheckKind::
839
- ConsumableAndAssignable);
840
- }
841
-
842
- if (!value->getType ().isTrivial (SGF.F )) {
843
- // A value without ownership of non-trivial type, e.g. Optional<K>.none.
844
- // Mark that it is from a VarDecl.
845
- return SGF.B .createMoveValue (PrologueLoc, value, IsNotLexical,
846
- DoesNotHavePointerEscape, IsFromVarDecl);
847
- }
848
-
819
+ // TODO: emitPatternBindingInitialization creates fake local variables for
820
+ // metatypes within function_conversion expressions that operate on static
821
+ // functions. Creating SIL local variables for all these is impractical and
822
+ // undesirable. We need a better way of representing these "capture_list"
823
+ // locals in a way that doesn't produce SIL locals. For now, bypassing
824
+ // metatypes mostly avoids the issue, but it's not robust and doesn't allow
825
+ // SIL-level analysis of real metatype variables.
826
+ if (isa<MetatypeType>(value->getType ().getASTType ())) {
849
827
return value;
850
828
}
851
829
852
- // Otherwise, we need to perform some additional processing. First, if we
853
- // have an owned moveonly value that had a cleanup, then create a move_value
854
- // that acts as a consuming use of the value. The reason why we want this is
855
- // even if we are only performing a borrow for our lexical lifetime, we want
856
- // to ensure that our defs see this initialization as consuming this value.
830
+ // Preprocess an owned moveonly value that had a cleanup. Even if we are
831
+ // only performing a borrow for our lexical lifetime, this ensures that
832
+ // defs see this initialization as consuming this value.
857
833
if (value->getOwnershipKind () == OwnershipKind::Owned &&
858
834
value->getType ().isMoveOnlyWrapped ()) {
859
835
assert (wasPlusOne);
@@ -864,50 +840,35 @@ class LetValueInitialization : public Initialization {
864
840
value =
865
841
SGF.B .createOwnedMoveOnlyWrapperToCopyableValue (PrologueLoc, value);
866
842
}
867
-
868
- // If we still have a trivial thing, just return that.
869
- if (value->getType ().isTrivial (SGF.F ))
870
- return value;
871
-
872
- // Check if we have a move only type. In that case, we perform a lexical
873
- // move and insert a mark_unresolved_non_copyable_value.
874
- //
875
- // We do this before the begin_borrow "normal" path below since move only
876
- // types do not have no implicit copy attr on them.
877
- if (value->getOwnershipKind () == OwnershipKind::Owned &&
878
- value->getType ().isMoveOnly (/* orWrapped=*/ false )) {
879
- value = SGF.B .createMoveValue (PrologueLoc, value, IsLexical);
880
- return SGF.B .createMarkUnresolvedNonCopyableValueInst (
881
- PrologueLoc, value,
882
- MarkUnresolvedNonCopyableValueInst::CheckKind::
883
- ConsumableAndAssignable);
843
+ auto isLexical =
844
+ IsLexical_t (SGF.F .getLifetime (vd, value->getType ()).isLexical ());
845
+ switch (value->getOwnershipKind ()) {
846
+ case OwnershipKind::None:
847
+ case OwnershipKind::Owned:
848
+ value = SGF.B .createMoveValue (PrologueLoc, value, isLexical,
849
+ DoesNotHavePointerEscape, IsFromVarDecl);
850
+ break ;
851
+ case OwnershipKind::Guaranteed:
852
+ value = SGF.B .createBeginBorrow (PrologueLoc, value, isLexical,
853
+ DoesNotHavePointerEscape, IsFromVarDecl);
854
+ break ;
855
+ case OwnershipKind::Unowned:
856
+ case OwnershipKind::Any:
857
+ llvm_unreachable (" unexpected ownership" );
884
858
}
885
-
886
- // If we have a no implicit copy lexical, emit the instruction stream so
887
- // that the move checker knows to check this variable.
888
859
if (vd->isNoImplicitCopy ()) {
889
- value = SGF.B .createMoveValue (PrologueLoc, value, IsLexical,
890
- DoesNotHavePointerEscape, IsFromVarDecl);
891
860
value =
892
861
SGF.B .createOwnedCopyableToMoveOnlyWrapperValue (PrologueLoc, value);
893
- return SGF.B .createMarkUnresolvedNonCopyableValueInst (
894
- PrologueLoc, value,
895
- MarkUnresolvedNonCopyableValueInst::CheckKind::
896
- ConsumableAndAssignable);
862
+ // fall-through to the owned move-only case...
897
863
}
898
-
899
- // Otherwise, if we do not have a no implicit copy variable, just follow
900
- // the "normal path".
901
-
902
- auto isLexical =
903
- IsLexical_t (SGF.F .getLifetime (vd, value->getType ()).isLexical ());
904
-
905
- if (value->getOwnershipKind () == OwnershipKind::Owned)
906
- return SGF.B .createMoveValue (PrologueLoc, value, isLexical,
907
- DoesNotHavePointerEscape, IsFromVarDecl);
908
-
909
- return SGF.B .createBeginBorrow (PrologueLoc, value, isLexical,
910
- DoesNotHavePointerEscape, IsFromVarDecl);
864
+ if (value->getType ().isMoveOnly (/* orWrapped=*/ true )
865
+ && value->getOwnershipKind () == OwnershipKind::Owned) {
866
+ value = SGF.B .createMarkUnresolvedNonCopyableValueInst (
867
+ PrologueLoc, value,
868
+ MarkUnresolvedNonCopyableValueInst::CheckKind::
869
+ ConsumableAndAssignable);
870
+ }
871
+ return value;
911
872
}
912
873
913
874
void bindValue (SILValue value, SILGenFunction &SGF, bool wasPlusOne,
@@ -2336,23 +2297,37 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
2336
2297
2337
2298
assert (VarLocs.count (vd) && " var decl wasn't emitted?!" );
2338
2299
2300
+ auto emitEndBorrow = [this , silLoc](SILValue value){
2301
+ if (value->getOwnershipKind () == OwnershipKind::None) {
2302
+ B.createExtendLifetime (silLoc, value);
2303
+ } else {
2304
+ B.createEndBorrow (silLoc, value);
2305
+ }
2306
+ };
2307
+
2308
+ auto emitDestroy = [this , silLoc](SILValue value){
2309
+ if (value->getOwnershipKind () == OwnershipKind::None) {
2310
+ B.createExtendLifetime (silLoc, value);
2311
+ } else {
2312
+ B.emitDestroyValueOperation (silLoc, value);
2313
+ }
2314
+ };
2315
+
2339
2316
auto loc = VarLocs[vd];
2340
2317
2341
2318
// For a heap variable, the box is responsible for the value. We just need
2342
2319
// to give up our retain count on it.
2343
- if (loc.box ) {
2320
+ if (auto boxValue = loc.box ) {
2344
2321
if (!getASTContext ().SILOpts .supportsLexicalLifetimes (getModule ())) {
2345
- B. emitDestroyValueOperation (silLoc, loc. box );
2322
+ emitDestroy (boxValue );
2346
2323
return ;
2347
2324
}
2348
2325
2349
- if (auto *bbi = dyn_cast<BeginBorrowInst>(loc.box )) {
2350
- B.createEndBorrow (silLoc, bbi);
2351
- B.emitDestroyValueOperation (silLoc, bbi->getOperand ());
2352
- return ;
2326
+ if (auto *bbi = dyn_cast<BeginBorrowInst>(boxValue)) {
2327
+ emitEndBorrow (bbi);
2328
+ boxValue = bbi->getOperand ();
2353
2329
}
2354
-
2355
- B.emitDestroyValueOperation (silLoc, loc.box );
2330
+ emitDestroy (boxValue);
2356
2331
return ;
2357
2332
}
2358
2333
@@ -2366,73 +2341,72 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
2366
2341
}
2367
2342
2368
2343
if (!getASTContext ().SILOpts .supportsLexicalLifetimes (getModule ())) {
2369
- B. emitDestroyValueOperation (silLoc, Val);
2344
+ emitDestroy ( Val);
2370
2345
return ;
2371
2346
}
2372
2347
2373
- if (Val->getOwnershipKind () == OwnershipKind::None) {
2348
+ // If no variable scope was emitted, then we might not have a defining
2349
+ // instruction.
2350
+ if (!Val.getDefiningInstruction ()) {
2351
+ emitDestroy (Val);
2374
2352
return ;
2375
2353
}
2376
2354
2377
2355
// This handles any case where we copy + begin_borrow or copyable_to_moveonly
2378
2356
// + begin_borrow. In either case we just need to end the lifetime of the
2379
2357
// begin_borrow's operand.
2380
2358
if (auto *bbi = dyn_cast<BeginBorrowInst>(Val.getDefiningInstruction ())) {
2381
- B. createEndBorrow (silLoc, bbi);
2382
- B. emitDestroyValueOperation (silLoc, bbi->getOperand ());
2359
+ emitEndBorrow ( bbi);
2360
+ emitDestroy ( bbi->getOperand ());
2383
2361
return ;
2384
2362
}
2385
2363
2386
2364
if (auto *mvi = dyn_cast<MoveValueInst>(Val.getDefiningInstruction ())) {
2387
- B. emitDestroyValueOperation (silLoc, mvi);
2365
+ emitDestroy ( mvi);
2388
2366
return ;
2389
2367
}
2390
2368
2391
- if (auto *mvi = dyn_cast<MarkUnresolvedNonCopyableValueInst>(
2369
+ // Handle BeginBorrow and MoveValue before bailing-out on trivial values.
2370
+ if (Val->getOwnershipKind () == OwnershipKind::None) {
2371
+ return ;
2372
+ }
2373
+
2374
+ if (auto *mark = dyn_cast<MarkUnresolvedNonCopyableValueInst>(
2392
2375
Val.getDefiningInstruction ())) {
2393
- if (mvi ->hasMoveCheckerKind ()) {
2394
- if (auto *cvi = dyn_cast<CopyValueInst>(mvi ->getOperand ())) {
2376
+ if (mark ->hasMoveCheckerKind ()) {
2377
+ if (auto *cvi = dyn_cast<CopyValueInst>(mark ->getOperand ())) {
2395
2378
if (auto *bbi = dyn_cast<BeginBorrowInst>(cvi->getOperand ())) {
2396
- if (bbi->isLexical ()) {
2397
- B.emitDestroyValueOperation (silLoc, mvi);
2398
- B.createEndBorrow (silLoc, bbi);
2399
- B.emitDestroyValueOperation (silLoc, bbi->getOperand ());
2400
- return ;
2401
- }
2379
+ emitDestroy (mark);
2380
+ emitEndBorrow (bbi);
2381
+ emitDestroy (bbi->getOperand ());
2382
+ return ;
2402
2383
}
2403
2384
}
2404
2385
2405
2386
if (auto *copyToMove = dyn_cast<CopyableToMoveOnlyWrapperValueInst>(
2406
- mvi->getOperand ())) {
2407
- if (auto *move = dyn_cast<MoveValueInst>(copyToMove->getOperand ())) {
2408
- if (move->isLexical ()) {
2409
- B.emitDestroyValueOperation (silLoc, mvi);
2410
- return ;
2411
- }
2387
+ mark->getOperand ())) {
2388
+ if (copyToMove->getOperand ()->isFromVarDecl ()) {
2389
+ emitDestroy (mark);
2390
+ return ;
2412
2391
}
2413
2392
}
2414
2393
2415
- if (auto *cvi = dyn_cast<ExplicitCopyValueInst>(mvi ->getOperand ())) {
2394
+ if (auto *cvi = dyn_cast<ExplicitCopyValueInst>(mark ->getOperand ())) {
2416
2395
if (auto *bbi = dyn_cast<BeginBorrowInst>(cvi->getOperand ())) {
2417
- if (bbi->isLexical ()) {
2418
- B.emitDestroyValueOperation (silLoc, mvi);
2419
- B.createEndBorrow (silLoc, bbi);
2420
- B.emitDestroyValueOperation (silLoc, bbi->getOperand ());
2421
- return ;
2422
- }
2396
+ emitDestroy (mark);
2397
+ emitEndBorrow (bbi);
2398
+ emitDestroy (bbi->getOperand ());
2399
+ return ;
2423
2400
}
2424
2401
}
2425
2402
2426
2403
// Handle trivial arguments.
2427
- if (auto *move = dyn_cast<MoveValueInst>(mvi->getOperand ())) {
2428
- if (move->isLexical ()) {
2429
- B.emitDestroyValueOperation (silLoc, mvi);
2430
- return ;
2431
- }
2404
+ if (auto *move = dyn_cast<MoveValueInst>(mark->getOperand ())) {
2405
+ emitDestroy (mark);
2406
+ return ;
2432
2407
}
2433
2408
}
2434
- }
2435
-
2409
+ }
2436
2410
llvm_unreachable (" unhandled case" );
2437
2411
}
2438
2412
0 commit comments