18
18
#include " Scope.h"
19
19
#include " SwitchEnumBuilder.h"
20
20
#include " swift/AST/ASTMangler.h"
21
+ #include " swift/AST/DiagnosticsSIL.h"
21
22
#include " swift/AST/GenericEnvironment.h"
22
23
#include " swift/AST/Module.h"
23
24
#include " swift/AST/NameLookup.h"
24
- #include " swift/AST/ProtocolConformance.h"
25
25
#include " swift/AST/PropertyWrappers.h"
26
+ #include " swift/AST/ProtocolConformance.h"
26
27
#include " swift/Basic/ProfileCounter.h"
27
28
#include " swift/SIL/FormalLinkage.h"
28
29
#include " swift/SIL/PrettyStackTrace.h"
29
30
#include " swift/SIL/SILArgument.h"
30
31
#include " swift/SIL/SILDebuggerClient.h"
32
+ #include " swift/SIL/SILInstruction.h"
31
33
#include " swift/SIL/SILType.h"
32
34
#include " swift/SIL/TypeLowering.h"
33
35
#include " llvm/ADT/SmallString.h"
36
38
using namespace swift ;
37
39
using namespace Lowering ;
38
40
41
+ // Utility for emitting diagnostics.
42
+ template <typename ... T, typename ... U>
43
+ static void diagnose (ASTContext &Context, SourceLoc loc, Diag<T...> diag,
44
+ U &&...args) {
45
+ Context.Diags .diagnose (loc, diag, std::forward<U>(args)...);
46
+ }
47
+
39
48
void Initialization::_anchor () {}
40
49
void SILDebuggerClient::anchor () {}
41
50
@@ -254,10 +263,6 @@ class DestroyLocalVariable : public Cleanup {
254
263
255
264
void emit (SILGenFunction &SGF, CleanupLocation l,
256
265
ForUnwind_t forUnwind) override {
257
- SILValue val = SGF.VarLocs [Var].value ;
258
- if (SGF.getASTContext ().SILOpts .EnableExperimentalLexicalLifetimes &&
259
- val->getOwnershipKind () != OwnershipKind::None)
260
- SGF.B .createEndBorrow (l, val);
261
266
SGF.destroyLocalVariable (l, Var);
262
267
}
263
268
@@ -456,7 +461,16 @@ class LetValueInitialization : public Initialization {
456
461
needsTemporaryBuffer =
457
462
lowering.isAddressOnly () && SGF.silConv .useLoweredAddresses ();
458
463
}
459
-
464
+
465
+ // Make sure that we have a non-address only type when binding a
466
+ // @_noImplicitCopy let.
467
+ if (SGF.getASTContext ().LangOpts .EnableExperimentalMoveOnly &&
468
+ lowering.isAddressOnly () &&
469
+ vd->getAttrs ().hasAttribute <NoImplicitCopyAttr>()) {
470
+ auto d = diag::noimplicitcopy_used_on_generic_or_existential;
471
+ diagnose (SGF.getASTContext (), vd->getLoc (), d);
472
+ }
473
+
460
474
if (needsTemporaryBuffer) {
461
475
address = SGF.emitTemporaryAllocation (vd, lowering.getLoweredType ());
462
476
if (isUninitialized)
@@ -517,7 +531,7 @@ class LetValueInitialization : public Initialization {
517
531
SplitCleanups);
518
532
}
519
533
520
- void bindValue (SILValue value, SILGenFunction &SGF) {
534
+ void bindValue (SILValue value, SILGenFunction &SGF, bool wasPlusOne ) {
521
535
assert (!SGF.VarLocs .count (vd) && " Already emitted this vardecl?" );
522
536
// If we're binding an address to this let value, then we can use it as an
523
537
// address later. This happens when binding an address only parameter to
@@ -527,9 +541,33 @@ class LetValueInitialization : public Initialization {
527
541
SILLocation PrologueLoc (vd);
528
542
529
543
if (SGF.getASTContext ().SILOpts .EnableExperimentalLexicalLifetimes &&
530
- value->getOwnershipKind () != OwnershipKind::None)
531
- value = SILValue (
532
- SGF.B .createBeginBorrow (PrologueLoc, value, /* isLexical*/ true ));
544
+ value->getOwnershipKind () != OwnershipKind::None) {
545
+ if (!SGF.getASTContext ().LangOpts .EnableExperimentalMoveOnly ) {
546
+ value = SILValue (
547
+ SGF.B .createBeginBorrow (PrologueLoc, value, /* isLexical*/ true ));
548
+ } else {
549
+ // If we have an owned value that had a cleanup, then create a
550
+ // move_value that acts as a consuming use of the value. The reason why
551
+ // we want this is even if we are only performing a borrow for our
552
+ // lexical lifetime, we want to ensure that our defs see this
553
+ // initialization as consuming this value.
554
+ if (value->getOwnershipKind () == OwnershipKind::Owned) {
555
+ assert (wasPlusOne);
556
+ value = SILValue (SGF.B .createMoveValue (PrologueLoc, value));
557
+ }
558
+
559
+ if (vd->getAttrs ().hasAttribute <NoImplicitCopyAttr>()) {
560
+ value = SILValue (SGF.B .createBeginBorrow (PrologueLoc, value,
561
+ /* isLexical*/ true ));
562
+ value = SGF.B .createCopyValue (PrologueLoc, value);
563
+ value = SGF.B .createMoveValue (PrologueLoc, value);
564
+ } else {
565
+ value = SILValue (
566
+ SGF.B .createBeginBorrow (PrologueLoc, value, /* isLexical*/ true ));
567
+ }
568
+ }
569
+ }
570
+
533
571
SGF.VarLocs [vd] = SILGenFunction::VarLoc::get (value);
534
572
535
573
// Emit a debug_value[_addr] instruction to record the start of this value's
@@ -540,26 +578,27 @@ class LetValueInitialization : public Initialization {
540
578
SILDebugVariable DbgVar (vd->isLet (), /* ArgNo=*/ 0 );
541
579
SGF.B .emitDebugDescription (PrologueLoc, value, DbgVar);
542
580
}
543
-
581
+
544
582
void copyOrInitValueInto (SILGenFunction &SGF, SILLocation loc,
545
583
ManagedValue value, bool isInit) override {
546
584
// If this let value has an address, we can handle it just like a single
547
585
// buffer value.
548
- if (hasAddress ())
586
+ if (hasAddress ()) {
549
587
return SingleBufferInitialization::
550
588
copyOrInitValueIntoSingleBuffer (SGF, loc, value, isInit, address);
551
-
589
+ }
590
+
552
591
// Otherwise, we bind the value.
553
592
if (isInit) {
554
593
// Disable the rvalue expression cleanup, since the let value
555
594
// initialization has a cleanup that lives for the entire scope of the
556
595
// let declaration.
557
- bindValue (value.forward (SGF), SGF);
596
+ bindValue (value.forward (SGF), SGF, value. isPlusOne (SGF) );
558
597
} else {
559
598
// Disable the expression cleanup of the copy, since the let value
560
599
// initialization has a cleanup that lives for the entire scope of the
561
600
// let declaration.
562
- bindValue (value.copyUnmanaged (SGF, loc).forward (SGF), SGF);
601
+ bindValue (value.copyUnmanaged (SGF, loc).forward (SGF), SGF, true );
563
602
}
564
603
}
565
604
@@ -1715,16 +1754,38 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
1715
1754
// For 'let' bindings, we emit a release_value or destroy_addr, depending on
1716
1755
// whether we have an address or not.
1717
1756
SILValue Val = loc.value ;
1718
- if (!Val->getType ().isAddress ()) {
1719
- SILValue valueToBeDestroyed;
1720
- if (getASTContext ().SILOpts .EnableExperimentalLexicalLifetimes &&
1721
- Val->getOwnershipKind () != OwnershipKind::None) {
1722
- auto *inst = cast<BeginBorrowInst>(Val.getDefiningInstruction ());
1723
- valueToBeDestroyed = inst->getOperand ();
1724
- } else {
1725
- valueToBeDestroyed = Val;
1726
- }
1727
- B.emitDestroyValueOperation (silLoc, valueToBeDestroyed);
1728
- } else
1757
+
1758
+ if (Val->getType ().isAddress ()) {
1729
1759
B.createDestroyAddr (silLoc, Val);
1760
+ return ;
1761
+ }
1762
+
1763
+ if (!getASTContext ().SILOpts .EnableExperimentalLexicalLifetimes ||
1764
+ Val->getOwnershipKind () == OwnershipKind::None) {
1765
+ B.emitDestroyValueOperation (silLoc, Val);
1766
+ return ;
1767
+ }
1768
+
1769
+ if (auto *bbi = dyn_cast<BeginBorrowInst>(Val.getDefiningInstruction ())) {
1770
+ B.createEndBorrow (silLoc, bbi);
1771
+ B.emitDestroyValueOperation (silLoc, bbi->getOperand ());
1772
+ return ;
1773
+ }
1774
+
1775
+ if (getASTContext ().LangOpts .EnableExperimentalMoveOnly ) {
1776
+ if (auto *mvi = dyn_cast<MoveValueInst>(Val.getDefiningInstruction ())) {
1777
+ if (auto *cvi = dyn_cast<CopyValueInst>(mvi->getOperand ())) {
1778
+ if (auto *bbi = dyn_cast<BeginBorrowInst>(cvi->getOperand ())) {
1779
+ if (bbi->isLexical ()) {
1780
+ B.emitDestroyValueOperation (silLoc, mvi);
1781
+ B.createEndBorrow (silLoc, bbi);
1782
+ B.emitDestroyValueOperation (silLoc, bbi->getOperand ());
1783
+ return ;
1784
+ }
1785
+ }
1786
+ }
1787
+ }
1788
+ }
1789
+
1790
+ llvm_unreachable (" unhandled case" );
1730
1791
}
0 commit comments