@@ -1459,24 +1459,79 @@ void ElementUseCollector::collectClassSelfUses(
1459
1459
}
1460
1460
1461
1461
// ===----------------------------------------------------------------------===//
1462
- // DelegatingInitElementUseCollector
1462
+ // DelegatingValueTypeInitUseCollector
1463
+ // ===----------------------------------------------------------------------===//
1464
+
1465
+ static void
1466
+ collectValueTypeDelegatingInitUses (const DIMemoryObjectInfo &TheMemory,
1467
+ DIElementUseInfo &UseInfo,
1468
+ SingleValueInstruction *I) {
1469
+ for (auto *Op : I->getUses ()) {
1470
+ auto *User = Op->getUser ();
1471
+
1472
+ // destroy_addr is a release of the entire value. This can result from an
1473
+ // early release due to a conditional initializer.
1474
+ if (isa<DestroyAddrInst>(User)) {
1475
+ UseInfo.trackDestroy (User);
1476
+ continue ;
1477
+ }
1478
+
1479
+ // For delegating initializers, we only track calls to self.init with
1480
+ // specialized code. All other uses are modeled as escapes.
1481
+ //
1482
+ // *NOTE* This intentionally ignores all stores, which (if they got emitted
1483
+ // as copyaddr or assigns) will eventually get rewritten as assignments (not
1484
+ // initializations), which is the right thing to do.
1485
+ DIUseKind Kind = DIUseKind::Escape;
1486
+
1487
+ // Stores *to* the allocation are writes. If the value being stored is a
1488
+ // call to self.init()... then we have a self.init call.
1489
+ if (auto *AI = dyn_cast<AssignInst>(User)) {
1490
+ if (AI->getDest () == I) {
1491
+ UseInfo.trackStoreToSelf (AI);
1492
+ Kind = DIUseKind::InitOrAssign;
1493
+ }
1494
+ }
1495
+
1496
+ if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
1497
+ if (CAI->getDest () == I) {
1498
+ UseInfo.trackStoreToSelf (CAI);
1499
+ Kind = DIUseKind::InitOrAssign;
1500
+ }
1501
+ }
1502
+
1503
+ // Look through begin_access
1504
+ if (auto *BAI = dyn_cast<BeginAccessInst>(User)) {
1505
+ collectValueTypeDelegatingInitUses (TheMemory, UseInfo, BAI);
1506
+ continue ;
1507
+ }
1508
+
1509
+ // Ignore end_access
1510
+ if (isa<EndAccessInst>(User))
1511
+ continue ;
1512
+
1513
+ // We can safely handle anything else as an escape. They should all happen
1514
+ // after self.init is invoked.
1515
+ UseInfo.trackUse (DIMemoryUse (User, Kind, 0 , 1 ));
1516
+ }
1517
+ }
1518
+
1519
+ // ===----------------------------------------------------------------------===//
1520
+ // DelegatingClassInitElementUseCollector
1463
1521
// ===----------------------------------------------------------------------===//
1464
1522
1465
1523
namespace {
1466
1524
1467
- class DelegatingInitElementUseCollector {
1525
+ class DelegatingClassInitElementUseCollector {
1468
1526
const DIMemoryObjectInfo &TheMemory;
1469
1527
DIElementUseInfo &UseInfo;
1470
1528
1471
- void collectValueTypeInitSelfUses (SingleValueInstruction *I);
1472
-
1473
1529
public:
1474
- DelegatingInitElementUseCollector (const DIMemoryObjectInfo &TheMemory,
1475
- DIElementUseInfo &UseInfo)
1530
+ DelegatingClassInitElementUseCollector (const DIMemoryObjectInfo &TheMemory,
1531
+ DIElementUseInfo &UseInfo)
1476
1532
: TheMemory(TheMemory), UseInfo(UseInfo) {}
1477
1533
1478
1534
void collectClassInitSelfUses ();
1479
- void collectValueTypeInitSelfUses ();
1480
1535
1481
1536
// *NOTE* Even though this takes a SILInstruction it actually only accepts
1482
1537
// load_borrow and load instructions. This is enforced via an assert.
@@ -1488,7 +1543,7 @@ class DelegatingInitElementUseCollector {
1488
1543
1489
1544
// / collectDelegatingClassInitSelfUses - Collect uses of the self argument in a
1490
1545
// / delegating-constructor-for-a-class case.
1491
- void DelegatingInitElementUseCollector ::collectClassInitSelfUses () {
1546
+ void DelegatingClassInitElementUseCollector ::collectClassInitSelfUses () {
1492
1547
// When we're analyzing a delegating constructor, we aren't field sensitive at
1493
1548
// all. Just treat all members of self as uses of the single
1494
1549
// non-field-sensitive value.
@@ -1631,70 +1686,9 @@ void DelegatingInitElementUseCollector::collectClassInitSelfUses() {
1631
1686
}
1632
1687
}
1633
1688
1634
- void DelegatingInitElementUseCollector::collectValueTypeInitSelfUses (
1635
- SingleValueInstruction *I) {
1636
- for (auto Op : I->getUses ()) {
1637
- auto *User = Op->getUser ();
1638
-
1639
- // destroy_addr is a release of the entire value. This can result from an
1640
- // early release due to a conditional initializer.
1641
- if (isa<DestroyAddrInst>(User)) {
1642
- UseInfo.trackDestroy (User);
1643
- continue ;
1644
- }
1645
-
1646
- // For delegating initializers, we only track calls to self.init with
1647
- // specialized code. All other uses are modeled as escapes.
1648
- //
1649
- // *NOTE* This intentionally ignores all stores, which (if they got emitted
1650
- // as copyaddr or assigns) will eventually get rewritten as assignments (not
1651
- // initializations), which is the right thing to do.
1652
- DIUseKind Kind = DIUseKind::Escape;
1653
-
1654
- // Stores *to* the allocation are writes. If the value being stored is a
1655
- // call to self.init()... then we have a self.init call.
1656
- if (auto *AI = dyn_cast<AssignInst>(User)) {
1657
- if (AI->getDest () == I) {
1658
- UseInfo.trackStoreToSelf (AI);
1659
- Kind = DIUseKind::InitOrAssign;
1660
- }
1661
- }
1662
-
1663
- if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
1664
- if (CAI->getDest () == I) {
1665
- UseInfo.trackStoreToSelf (CAI);
1666
- Kind = DIUseKind::InitOrAssign;
1667
- }
1668
- }
1669
-
1670
- // Look through begin_access
1671
- if (auto *BAI = dyn_cast<BeginAccessInst>(User)) {
1672
- collectValueTypeInitSelfUses (BAI);
1673
- continue ;
1674
- }
1675
-
1676
- // Ignore end_access
1677
- if (isa<EndAccessInst>(User))
1678
- continue ;
1679
-
1680
- // We can safely handle anything else as an escape. They should all happen
1681
- // after self.init is invoked.
1682
- UseInfo.trackUse (DIMemoryUse (User, Kind, 0 , 1 ));
1683
- }
1684
- }
1685
-
1686
- void DelegatingInitElementUseCollector::collectValueTypeInitSelfUses () {
1687
- // When we're analyzing a delegating constructor, we aren't field sensitive at
1688
- // all. Just treat all members of self as uses of the single
1689
- // non-field-sensitive value.
1690
- assert (TheMemory.NumElements == 1 && " delegating inits only have 1 bit" );
1691
-
1692
- auto *MUI = cast<MarkUninitializedInst>(TheMemory.MemoryInst );
1693
- collectValueTypeInitSelfUses (MUI);
1694
- }
1695
-
1696
- void DelegatingInitElementUseCollector::collectDelegatingClassInitSelfLoadUses (
1697
- MarkUninitializedInst *MUI, SingleValueInstruction *LI) {
1689
+ void DelegatingClassInitElementUseCollector::
1690
+ collectDelegatingClassInitSelfLoadUses (MarkUninitializedInst *MUI,
1691
+ SingleValueInstruction *LI) {
1698
1692
assert (isa<LoadBorrowInst>(LI) || isa<LoadInst>(LI));
1699
1693
1700
1694
// If we have a load, then this is a use of the box. Look at the uses of
@@ -1775,31 +1769,38 @@ void DelegatingInitElementUseCollector::collectDelegatingClassInitSelfLoadUses(
1775
1769
// Top Level Entrypoint
1776
1770
// ===----------------------------------------------------------------------===//
1777
1771
1772
+ static bool shouldPerformClassInitSelf (const DIMemoryObjectInfo &MemoryInfo) {
1773
+ if (MemoryInfo.isDelegatingInit ()) {
1774
+ assert (MemoryInfo.isClassInitSelf ());
1775
+ return true ;
1776
+ }
1777
+
1778
+ return MemoryInfo.isNonDelegatingInit () &&
1779
+ MemoryInfo.getType ()->getClassOrBoundGenericClass () != nullptr &&
1780
+ MemoryInfo.isDerivedClassSelfOnly ();
1781
+ }
1782
+
1778
1783
// / collectDIElementUsesFrom - Analyze all uses of the specified allocation
1779
1784
// / instruction (alloc_box, alloc_stack or mark_uninitialized), classifying them
1780
1785
// / and storing the information found into the Uses and Releases lists.
1781
1786
void swift::ownership::collectDIElementUsesFrom (
1782
1787
const DIMemoryObjectInfo &MemoryInfo, DIElementUseInfo &UseInfo,
1783
1788
bool isDIFinished, bool TreatAddressToPointerAsInout) {
1784
- // If we have a delegating init, use the delegating init element use
1785
- // collector.
1786
- if (MemoryInfo.isDelegatingInit ()) {
1787
- DelegatingInitElementUseCollector UseCollector (MemoryInfo, UseInfo);
1788
- if (MemoryInfo.isClassInitSelf ()) {
1789
- UseCollector.collectClassInitSelfUses ();
1790
- } else {
1791
- UseCollector.collectValueTypeInitSelfUses ();
1792
- }
1793
1789
1790
+ if (MemoryInfo.isDelegatingInit () && !MemoryInfo.isClassInitSelf ()) {
1791
+ // When we're analyzing a delegating constructor, we aren't field sensitive
1792
+ // at all. Just treat all members of self as uses of the single
1793
+ // non-field-sensitive value.
1794
+ assert (MemoryInfo.NumElements == 1 && " delegating inits only have 1 bit" );
1795
+ auto *MUI = cast<MarkUninitializedInst>(MemoryInfo.MemoryInst );
1796
+ collectValueTypeDelegatingInitUses (MemoryInfo, UseInfo, MUI);
1794
1797
MemoryInfo.collectRetainCountInfo (UseInfo);
1795
1798
return ;
1796
1799
}
1797
1800
1798
- if (MemoryInfo.isNonDelegatingInit () &&
1799
- MemoryInfo.getType ()->getClassOrBoundGenericClass () != nullptr &&
1800
- MemoryInfo.isDerivedClassSelfOnly ()) {
1801
- DelegatingInitElementUseCollector (MemoryInfo, UseInfo)
1802
- .collectClassInitSelfUses ();
1801
+ if (shouldPerformClassInitSelf (MemoryInfo)) {
1802
+ DelegatingClassInitElementUseCollector UseCollector (MemoryInfo, UseInfo);
1803
+ UseCollector.collectClassInitSelfUses ();
1803
1804
MemoryInfo.collectRetainCountInfo (UseInfo);
1804
1805
return ;
1805
1806
}
0 commit comments