@@ -1476,15 +1476,15 @@ void ElementUseCollector::collectClassSelfUses(
1476
1476
}
1477
1477
1478
1478
// ===----------------------------------------------------------------------===//
1479
- // DelegatingValueTypeInitUseCollector
1479
+ // DelegatingInitUseCollector
1480
1480
// ===----------------------------------------------------------------------===//
1481
1481
1482
1482
static void
1483
- collectValueTypeDelegatingInitUses (const DIMemoryObjectInfo &TheMemory,
1484
- DIElementUseInfo &UseInfo,
1485
- SingleValueInstruction *I) {
1483
+ collectDelegatingInitUses (const DIMemoryObjectInfo &TheMemory,
1484
+ DIElementUseInfo &UseInfo,
1485
+ SingleValueInstruction *I) {
1486
1486
for (auto *Op : I->getUses ()) {
1487
- auto *User = Op->getUser ();
1487
+ SILInstruction *User = Op->getUser ();
1488
1488
1489
1489
// destroy_addr is a release of the entire value. This can result from an
1490
1490
// early release due to a conditional initializer.
@@ -1519,13 +1519,48 @@ collectValueTypeDelegatingInitUses(const DIMemoryObjectInfo &TheMemory,
1519
1519
1520
1520
// Look through begin_access
1521
1521
if (auto *BAI = dyn_cast<BeginAccessInst>(User)) {
1522
- collectValueTypeDelegatingInitUses (TheMemory, UseInfo, BAI);
1522
+ collectDelegatingInitUses (TheMemory, UseInfo, BAI);
1523
1523
continue ;
1524
1524
}
1525
1525
1526
1526
// Ignore end_access
1527
1527
if (isa<EndAccessInst>(User))
1528
1528
continue ;
1529
+
1530
+ // A load of the value that's only used to handle a type(of:) query before
1531
+ // self has been initialized can just use the initializer's metatype
1532
+ // argument. For value types, there's no metatype subtyping to worry about,
1533
+ // and for class convenience initializers, `self` notionally has the
1534
+ // original Self type as its dynamic type before theoretically being
1535
+ // rebound.
1536
+ //
1537
+ // This is necessary for source compatibility; previously, convenience
1538
+ // initializers behaved like in Objective-C where the initializer received
1539
+ // an uninitialized object to fill in, and type(of: self) worked by asking
1540
+ // for the dynamic type of that uninitialized object.
1541
+ if (isa<LoadInst>(User)) {
1542
+ auto UserVal = cast<SingleValueInstruction>(User);
1543
+ if (UserVal->hasOneUse ()
1544
+ && isa<ValueMetatypeInst>(UserVal->getSingleUse ()->get ())) {
1545
+ Kind = DIUseKind::LoadForTypeOfSelf;
1546
+ }
1547
+ }
1548
+ // value_metatype may appear on a borrowed load, in which case there'll
1549
+ // be an end_borrow use in addition to the value_metatype.
1550
+ if (isa<LoadBorrowInst>(User)) {
1551
+ auto UserVal = cast<SingleValueInstruction>(User);
1552
+ bool onlyUseIsValueMetatype = true ;
1553
+ for (auto use : UserVal->getUses ()) {
1554
+ if (isa<EndBorrowInst>(use->getUser ())
1555
+ || isa<ValueMetatypeInst>(use->getUser ()))
1556
+ continue ;
1557
+ onlyUseIsValueMetatype = false ;
1558
+ break ;
1559
+ }
1560
+ if (onlyUseIsValueMetatype) {
1561
+ Kind = DIUseKind::LoadForTypeOfSelf;
1562
+ }
1563
+ }
1529
1564
1530
1565
// We can safely handle anything else as an escape. They should all happen
1531
1566
// after self.init is invoked.
@@ -1534,33 +1569,33 @@ collectValueTypeDelegatingInitUses(const DIMemoryObjectInfo &TheMemory,
1534
1569
}
1535
1570
1536
1571
// ===----------------------------------------------------------------------===//
1537
- // DelegatingClassInitElementUseCollector
1572
+ // ClassInitElementUseCollector
1538
1573
// ===----------------------------------------------------------------------===//
1539
1574
1540
1575
namespace {
1541
1576
1542
- class DelegatingClassInitElementUseCollector {
1577
+ class ClassInitElementUseCollector {
1543
1578
const DIMemoryObjectInfo &TheMemory;
1544
1579
DIElementUseInfo &UseInfo;
1545
1580
1546
1581
public:
1547
- DelegatingClassInitElementUseCollector (const DIMemoryObjectInfo &TheMemory,
1582
+ ClassInitElementUseCollector (const DIMemoryObjectInfo &TheMemory,
1548
1583
DIElementUseInfo &UseInfo)
1549
1584
: TheMemory(TheMemory), UseInfo(UseInfo) {}
1550
1585
1551
1586
void collectClassInitSelfUses ();
1552
1587
1553
1588
// *NOTE* Even though this takes a SILInstruction it actually only accepts
1554
1589
// load_borrow and load instructions. This is enforced via an assert.
1555
- void collectDelegatingClassInitSelfLoadUses (MarkUninitializedInst *MUI,
1556
- SingleValueInstruction *LI);
1590
+ void collectClassInitSelfLoadUses (MarkUninitializedInst *MUI,
1591
+ SingleValueInstruction *LI);
1557
1592
};
1558
1593
1559
1594
} // end anonymous namespace
1560
1595
1561
1596
// / collectDelegatingClassInitSelfUses - Collect uses of the self argument in a
1562
1597
// / delegating-constructor-for-a-class case.
1563
- void DelegatingClassInitElementUseCollector ::collectClassInitSelfUses () {
1598
+ void ClassInitElementUseCollector ::collectClassInitSelfUses () {
1564
1599
// When we're analyzing a delegating constructor, we aren't field sensitive at
1565
1600
// all. Just treat all members of self as uses of the single
1566
1601
// non-field-sensitive value.
@@ -1668,8 +1703,7 @@ void DelegatingClassInitElementUseCollector::collectClassInitSelfUses() {
1668
1703
1669
1704
// Loads of the box produce self, so collect uses from them.
1670
1705
if (isa<LoadInst>(User) || isa<LoadBorrowInst>(User)) {
1671
- collectDelegatingClassInitSelfLoadUses (MUI,
1672
- cast<SingleValueInstruction>(User));
1706
+ collectClassInitSelfLoadUses (MUI, cast<SingleValueInstruction>(User));
1673
1707
continue ;
1674
1708
}
1675
1709
@@ -1691,8 +1725,8 @@ void DelegatingClassInitElementUseCollector::collectClassInitSelfUses() {
1691
1725
gatherDestroysOfContainer (MUI, UseInfo);
1692
1726
}
1693
1727
1694
- void DelegatingClassInitElementUseCollector ::
1695
- collectDelegatingClassInitSelfLoadUses (MarkUninitializedInst *MUI,
1728
+ void ClassInitElementUseCollector ::
1729
+ collectClassInitSelfLoadUses (MarkUninitializedInst *MUI,
1696
1730
SingleValueInstruction *LI) {
1697
1731
assert (isa<LoadBorrowInst>(LI) || isa<LoadInst>(LI));
1698
1732
@@ -1794,13 +1828,12 @@ void swift::ownership::collectDIElementUsesFrom(
1794
1828
// at all. Just treat all members of self as uses of the single
1795
1829
// non-field-sensitive value.
1796
1830
assert (MemoryInfo.NumElements == 1 && " delegating inits only have 1 bit" );
1797
- collectValueTypeDelegatingInitUses (MemoryInfo, UseInfo,
1798
- MemoryInfo.MemoryInst );
1831
+ collectDelegatingInitUses (MemoryInfo, UseInfo, MemoryInfo.MemoryInst );
1799
1832
return ;
1800
1833
}
1801
1834
1802
1835
if (shouldPerformClassInitSelf (MemoryInfo)) {
1803
- DelegatingClassInitElementUseCollector UseCollector (MemoryInfo, UseInfo);
1836
+ ClassInitElementUseCollector UseCollector (MemoryInfo, UseInfo);
1804
1837
UseCollector.collectClassInitSelfUses ();
1805
1838
return ;
1806
1839
}
0 commit comments