@@ -568,8 +568,10 @@ llvm::Value *IRGenFunction::emitUnmanagedAlloc(const HeapLayout &layout,
568
568
const llvm::Twine &name,
569
569
llvm::Constant *captureDescriptor,
570
570
const HeapNonFixedOffsets *offsets) {
571
- if (layout.isKnownEmpty ())
571
+ if (layout.isKnownEmpty ()
572
+ && layout.isTriviallyDestroyable ()) {
572
573
return IGM.RefCountedNull ;
574
+ }
573
575
574
576
llvm::Value *metadata = layout.getPrivateMetadata (IGM, captureDescriptor);
575
577
llvm::Value *size, *alignMask;
@@ -1470,7 +1472,7 @@ class BoxTypeInfo : public HeapTypeInfo<BoxTypeInfo> {
1470
1472
1471
1473
// / Allocate a box of the given type.
1472
1474
virtual OwnedAddress
1473
- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1475
+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *box ,
1474
1476
const llvm::Twine &name) const = 0 ;
1475
1477
1476
1478
// / Deallocate an uninitialized box.
@@ -1488,8 +1490,11 @@ class EmptyBoxTypeInfo final : public BoxTypeInfo {
1488
1490
EmptyBoxTypeInfo (IRGenModule &IGM) : BoxTypeInfo(IGM) {}
1489
1491
1490
1492
OwnedAddress
1491
- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1493
+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *box ,
1492
1494
const llvm::Twine &name) const override {
1495
+ auto boxedType = getSILBoxFieldType (
1496
+ IGF.IGM .getMaximalTypeExpansionContext (),
1497
+ box, IGF.IGM .getSILModule ().Types , 0 );
1493
1498
return OwnedAddress (IGF.getTypeInfo (boxedType).getUndefAddress (),
1494
1499
IGF.emitAllocEmptyBoxCall ());
1495
1500
}
@@ -1513,8 +1518,11 @@ class NonFixedBoxTypeInfo final : public BoxTypeInfo {
1513
1518
NonFixedBoxTypeInfo (IRGenModule &IGM) : BoxTypeInfo(IGM) {}
1514
1519
1515
1520
OwnedAddress
1516
- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1521
+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *boxType ,
1517
1522
const llvm::Twine &name) const override {
1523
+ auto boxedType = getSILBoxFieldType (
1524
+ IGF.IGM .getMaximalTypeExpansionContext (),
1525
+ boxType, IGF.IGM .getSILModule ().Types , 0 );
1518
1526
auto &ti = IGF.getTypeInfo (boxedType);
1519
1527
// Use the runtime to allocate a box of the appropriate size.
1520
1528
auto metadata = IGF.emitTypeMetadataRefForLayout (boxedType);
@@ -1552,14 +1560,18 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
1552
1560
FixedBoxTypeInfoBase (IRGenModule &IGM, HeapLayout &&layout)
1553
1561
: BoxTypeInfo(IGM), layout(std::move(layout))
1554
1562
{
1555
- // Empty layouts should always use EmptyBoxTypeInfo instead
1556
- assert (!layout.isKnownEmpty ());
1563
+ // Trivial empty layouts should always use EmptyBoxTypeInfo instead
1564
+ assert (!layout.isKnownEmpty ()
1565
+ || !layout.isTriviallyDestroyable ());
1557
1566
}
1558
1567
1559
1568
OwnedAddress
1560
- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1569
+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *box ,
1561
1570
const llvm::Twine &name)
1562
1571
const override {
1572
+ auto boxedType = getSILBoxFieldType (
1573
+ IGF.IGM .getMaximalTypeExpansionContext (),
1574
+ box, IGF.IGM .getSILModule ().Types , 0 );
1563
1575
// Allocate a new object using the layout.
1564
1576
auto boxedInterfaceType = boxedType;
1565
1577
if (env) {
@@ -1583,13 +1595,21 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
1583
1595
boxedInterfaceType = SILType::getPrimitiveType (
1584
1596
astType, boxedInterfaceType.getCategory ());
1585
1597
}
1586
-
1598
+
1587
1599
auto boxDescriptor = IGF.IGM .getAddrOfBoxDescriptor (
1588
1600
boxedInterfaceType,
1589
1601
env ? env->getGenericSignature ().getCanonicalSignature ()
1590
1602
: CanGenericSignature ());
1591
1603
llvm::Value *allocation = IGF.emitUnmanagedAlloc (layout, name,
1592
1604
boxDescriptor);
1605
+ // Store metadata for the necessary bindings if present.
1606
+ if (layout.hasBindings ()) {
1607
+ auto allocationAddr = layout.emitCastTo (IGF, allocation);
1608
+ auto bindingsAddr = layout.getElement (layout.getBindingsIndex ())
1609
+ .project (IGF, allocationAddr, nullptr );
1610
+ layout.getBindings ().save (IGF, bindingsAddr, box->getSubstitutions ());
1611
+ }
1612
+
1593
1613
Address rawAddr = project (IGF, allocation, boxedType);
1594
1614
return {rawAddr, allocation};
1595
1615
}
@@ -1639,22 +1659,87 @@ class SingleRefcountedBoxTypeInfo final : public FixedBoxTypeInfoBase {
1639
1659
1640
1660
// / Implementation of a box for a specific type.
1641
1661
class FixedBoxTypeInfo final : public FixedBoxTypeInfoBase {
1662
+ static SILType getFieldType (IRGenModule &IGM, SILBoxType *T) {
1663
+ return getSILBoxFieldType (IGM.getMaximalTypeExpansionContext (),
1664
+ T, IGM.getSILModule ().Types , 0 );
1665
+ }
1666
+
1667
+ static HeapLayout getHeapLayout (IRGenModule &IGM, SILBoxType *T) {
1668
+ SmallVector<SILType> fieldTypes;
1669
+ fieldTypes.push_back (getFieldType (IGM, T));
1670
+
1671
+ auto bindings = NecessaryBindings::forFixedBox (IGM, T);
1672
+ unsigned bindingsIndex = 0 ;
1673
+ SmallVector<const TypeInfo *, 4 > fields;
1674
+ fields.push_back (&IGM.getTypeInfo (fieldTypes[0 ]));
1675
+
1676
+ if (!bindings.empty ()) {
1677
+ bindingsIndex = 1 ;
1678
+ auto bindingsSize = bindings.getBufferSize (IGM);
1679
+ auto &bindingsTI = IGM.getOpaqueStorageTypeInfo (bindingsSize,
1680
+ IGM.getPointerAlignment ());
1681
+ fieldTypes.push_back (SILType ());
1682
+ fields.push_back (&bindingsTI);
1683
+ }
1684
+
1685
+ return HeapLayout (IGM, LayoutStrategy::Optimal,
1686
+ fieldTypes, fields,
1687
+ /* type to fill */ nullptr ,
1688
+ std::move (bindings), bindingsIndex);
1689
+ }
1690
+
1642
1691
public:
1643
- FixedBoxTypeInfo (IRGenModule &IGM, SILType T)
1644
- : FixedBoxTypeInfoBase(IGM,
1645
- HeapLayout (IGM, LayoutStrategy::Optimal, T, &IGM.getTypeInfo(T)))
1692
+ FixedBoxTypeInfo (IRGenModule &IGM, SILBoxType *T)
1693
+ : FixedBoxTypeInfoBase(IGM, getHeapLayout(IGM, T))
1646
1694
{}
1647
1695
};
1648
1696
1649
1697
} // end anonymous namespace
1650
1698
1699
+ NecessaryBindings
1700
+ NecessaryBindings::forFixedBox (IRGenModule &IGM, SILBoxType *box) {
1701
+ // Don't need to bind metadata if the type is concrete.
1702
+ if (!box->hasArchetype () && !box->hasTypeParameter ()) {
1703
+ return {};
1704
+ }
1705
+
1706
+ auto fieldTy = getSILBoxFieldType (IGM.getMaximalTypeExpansionContext (),
1707
+ box, IGM.getSILModule ().Types , 0 );
1708
+ auto fieldTI = cast<FixedTypeInfo>(&IGM.getTypeInfo (fieldTy));
1709
+
1710
+ // If the type is trivially destroyable, or it's fixed-layout and copyable,
1711
+ // then we can always destroy it without binding type metadata.
1712
+ if (fieldTI->isTriviallyDestroyable (ResilienceExpansion::Maximal)
1713
+ || fieldTI->isCopyable (ResilienceExpansion::Maximal)) {
1714
+ return {};
1715
+ }
1716
+
1717
+ NecessaryBindings bindings (box->getSubstitutions (),
1718
+ /* no escape*/ false );
1719
+
1720
+ // Collect bindings needed by a deinit-shaped function.
1721
+ auto deinitParam = SILParameterInfo (
1722
+ box->getLayout ()->getFields ()[0 ].getLoweredType (),
1723
+ ParameterConvention::Indirect_In);
1724
+ auto deinitFnTy = SILFunctionType::get (box->getLayout ()->getGenericSignature (),
1725
+ SILExtInfo (),
1726
+ SILCoroutineKind::None,
1727
+ ParameterConvention::Direct_Guaranteed,
1728
+ deinitParam,
1729
+ {}, {}, std::nullopt,
1730
+ {}, {}, IGM.Context );
1731
+ bindings.computeBindings (IGM, deinitFnTy, /* consider param sources*/ false );
1732
+ return bindings;
1733
+ }
1734
+
1651
1735
const TypeInfo *TypeConverter::convertBoxType (SILBoxType *T) {
1652
1736
// We can share a type info for all dynamic-sized heap metadata.
1653
1737
// TODO: Multi-field boxes
1654
1738
assert (T->getLayout ()->getFields ().size () == 1
1655
1739
&& " multi-field boxes not implemented yet" );
1656
- auto &eltTI = IGM.getTypeInfoForLowered (getSILBoxFieldLoweredType (
1657
- IGM.getMaximalTypeExpansionContext (), T, IGM.getSILModule ().Types , 0 ));
1740
+ auto eltTy = getSILBoxFieldLoweredType (
1741
+ IGM.getMaximalTypeExpansionContext (), T, IGM.getSILModule ().Types , 0 );
1742
+ auto &eltTI = IGM.getTypeInfoForLowered (eltTy);
1658
1743
if (!eltTI.isFixedSize ()) {
1659
1744
if (!NonFixedBoxTI)
1660
1745
NonFixedBoxTI = new NonFixedBoxTypeInfo (IGM);
@@ -1664,12 +1749,16 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
1664
1749
// For fixed-sized types, we can emit concrete box metadata.
1665
1750
auto &fixedTI = cast<FixedTypeInfo>(eltTI);
1666
1751
1667
- // Because we assume in enum's that payloads with a Builtin.NativeReference
1752
+ // Because we assume in enums that payloads with a Builtin.NativeReference
1668
1753
// which is also the type for indirect enum cases have extra inhabitants of
1669
1754
// pointers we can't have a nil pointer as a representation for an empty box
1670
1755
// type -- nil conflicts with the extra inhabitants. We return a static
1671
1756
// singleton empty box object instead.
1672
- if (fixedTI.isKnownEmpty (ResilienceExpansion::Maximal)) {
1757
+ //
1758
+ // (If the box needs no storage, but the type still carries a deinit,
1759
+ // then we still need to trigger that deinit when the box is freed.)
1760
+ if (fixedTI.isKnownEmpty (ResilienceExpansion::Maximal)
1761
+ && fixedTI.isTriviallyDestroyable (ResilienceExpansion::Maximal)) {
1673
1762
if (!EmptyBoxTI)
1674
1763
EmptyBoxTI = new EmptyBoxTypeInfo (IGM);
1675
1764
return EmptyBoxTI;
@@ -1703,9 +1792,8 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
1703
1792
// Produce a tailored box metadata for the type.
1704
1793
assert (T->getLayout ()->getFields ().size () == 1
1705
1794
&& " multi-field boxes not implemented yet" );
1706
- return new FixedBoxTypeInfo (
1707
- IGM, getSILBoxFieldType (IGM.getMaximalTypeExpansionContext (),
1708
- T, IGM.getSILModule ().Types , 0 ));
1795
+
1796
+ return new FixedBoxTypeInfo (IGM, T);
1709
1797
}
1710
1798
1711
1799
OwnedAddress
@@ -1715,12 +1803,7 @@ irgen::emitAllocateBox(IRGenFunction &IGF, CanSILBoxType boxType,
1715
1803
auto &boxTI = IGF.getTypeInfoForLowered (boxType).as <BoxTypeInfo>();
1716
1804
assert (boxType->getLayout ()->getFields ().size () == 1
1717
1805
&& " multi-field boxes not implemented yet" );
1718
- return boxTI.allocate (
1719
- IGF,
1720
- getSILBoxFieldType (
1721
- IGF.IGM .getMaximalTypeExpansionContext (),
1722
- boxType, IGF.IGM .getSILModule ().Types , 0 ),
1723
- env, name);
1806
+ return boxTI.allocate (IGF, env, boxType, name);
1724
1807
}
1725
1808
1726
1809
void irgen::emitDeallocateBox (IRGenFunction &IGF,
@@ -1753,7 +1836,7 @@ Address irgen::emitAllocateExistentialBoxInBuffer(
1753
1836
// Get a box for the boxed value.
1754
1837
auto boxType = SILBoxType::get (boxedType.getASTType ());
1755
1838
auto &boxTI = IGF.getTypeInfoForLowered (boxType).as <BoxTypeInfo>();
1756
- OwnedAddress owned = boxTI.allocate (IGF, boxedType, env , name);
1839
+ OwnedAddress owned = boxTI.allocate (IGF, env, boxType , name);
1757
1840
Explosion box;
1758
1841
box.add (owned.getOwner ());
1759
1842
boxTI.initialize (IGF, box,
0 commit comments