@@ -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) {
@@ -1581,13 +1593,21 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
1581
1593
boxedInterfaceType = SILType::getPrimitiveType (
1582
1594
astType, boxedInterfaceType.getCategory ());
1583
1595
}
1584
-
1596
+
1585
1597
auto boxDescriptor = IGF.IGM .getAddrOfBoxDescriptor (
1586
1598
boxedInterfaceType,
1587
1599
env ? env->getGenericSignature ().getCanonicalSignature ()
1588
1600
: CanGenericSignature ());
1589
1601
llvm::Value *allocation = IGF.emitUnmanagedAlloc (layout, name,
1590
1602
boxDescriptor);
1603
+ // Store metadata for the necessary bindings if present.
1604
+ if (layout.hasBindings ()) {
1605
+ auto allocationAddr = layout.emitCastTo (IGF, allocation);
1606
+ auto bindingsAddr = layout.getElement (layout.getBindingsIndex ())
1607
+ .project (IGF, allocationAddr, nullptr );
1608
+ layout.getBindings ().save (IGF, bindingsAddr, box->getSubstitutions ());
1609
+ }
1610
+
1591
1611
Address rawAddr = project (IGF, allocation, boxedType);
1592
1612
return {rawAddr, allocation};
1593
1613
}
@@ -1637,22 +1657,87 @@ class SingleRefcountedBoxTypeInfo final : public FixedBoxTypeInfoBase {
1637
1657
1638
1658
// / Implementation of a box for a specific type.
1639
1659
class FixedBoxTypeInfo final : public FixedBoxTypeInfoBase {
1660
+ static SILType getFieldType (IRGenModule &IGM, SILBoxType *T) {
1661
+ return getSILBoxFieldType (IGM.getMaximalTypeExpansionContext (),
1662
+ T, IGM.getSILModule ().Types , 0 );
1663
+ }
1664
+
1665
+ static HeapLayout getHeapLayout (IRGenModule &IGM, SILBoxType *T) {
1666
+ SmallVector<SILType> fieldTypes;
1667
+ fieldTypes.push_back (getFieldType (IGM, T));
1668
+
1669
+ auto bindings = NecessaryBindings::forFixedBox (IGM, T);
1670
+ unsigned bindingsIndex = 0 ;
1671
+ SmallVector<const TypeInfo *, 4 > fields;
1672
+ fields.push_back (&IGM.getTypeInfo (fieldTypes[0 ]));
1673
+
1674
+ if (!bindings.empty ()) {
1675
+ bindingsIndex = 1 ;
1676
+ auto bindingsSize = bindings.getBufferSize (IGM);
1677
+ auto &bindingsTI = IGM.getOpaqueStorageTypeInfo (bindingsSize,
1678
+ IGM.getPointerAlignment ());
1679
+ fieldTypes.push_back (SILType ());
1680
+ fields.push_back (&bindingsTI);
1681
+ }
1682
+
1683
+ return HeapLayout (IGM, LayoutStrategy::Optimal,
1684
+ fieldTypes, fields,
1685
+ /* type to fill */ nullptr ,
1686
+ std::move (bindings), bindingsIndex);
1687
+ }
1688
+
1640
1689
public:
1641
- FixedBoxTypeInfo (IRGenModule &IGM, SILType T)
1642
- : FixedBoxTypeInfoBase(IGM,
1643
- HeapLayout (IGM, LayoutStrategy::Optimal, T, &IGM.getTypeInfo(T)))
1690
+ FixedBoxTypeInfo (IRGenModule &IGM, SILBoxType *T)
1691
+ : FixedBoxTypeInfoBase(IGM, getHeapLayout(IGM, T))
1644
1692
{}
1645
1693
};
1646
1694
1647
1695
} // end anonymous namespace
1648
1696
1697
+ NecessaryBindings
1698
+ NecessaryBindings::forFixedBox (IRGenModule &IGM, SILBoxType *box) {
1699
+ // Don't need to bind metadata if the type is concrete.
1700
+ if (!box->hasArchetype () && !box->hasTypeParameter ()) {
1701
+ return {};
1702
+ }
1703
+
1704
+ auto fieldTy = getSILBoxFieldType (IGM.getMaximalTypeExpansionContext (),
1705
+ box, IGM.getSILModule ().Types , 0 );
1706
+ auto fieldTI = cast<FixedTypeInfo>(&IGM.getTypeInfo (fieldTy));
1707
+
1708
+ // If the type is trivially destroyable, or it's fixed-layout and copyable,
1709
+ // then we can always destroy it without binding type metadata.
1710
+ if (fieldTI->isTriviallyDestroyable (ResilienceExpansion::Maximal)
1711
+ || fieldTI->isCopyable (ResilienceExpansion::Maximal)) {
1712
+ return {};
1713
+ }
1714
+
1715
+ NecessaryBindings bindings (box->getSubstitutions (),
1716
+ /* no escape*/ false );
1717
+
1718
+ // Collect bindings needed by a deinit-shaped function.
1719
+ auto deinitParam = SILParameterInfo (
1720
+ box->getLayout ()->getFields ()[0 ].getLoweredType (),
1721
+ ParameterConvention::Indirect_In);
1722
+ auto deinitFnTy = SILFunctionType::get (box->getLayout ()->getGenericSignature (),
1723
+ SILExtInfo (),
1724
+ SILCoroutineKind::None,
1725
+ ParameterConvention::Direct_Guaranteed,
1726
+ deinitParam,
1727
+ {}, {}, std::nullopt,
1728
+ {}, {}, IGM.Context );
1729
+ bindings.computeBindings (IGM, deinitFnTy, /* consider param sources*/ false );
1730
+ return bindings;
1731
+ }
1732
+
1649
1733
const TypeInfo *TypeConverter::convertBoxType (SILBoxType *T) {
1650
1734
// We can share a type info for all dynamic-sized heap metadata.
1651
1735
// TODO: Multi-field boxes
1652
1736
assert (T->getLayout ()->getFields ().size () == 1
1653
1737
&& " multi-field boxes not implemented yet" );
1654
- auto &eltTI = IGM.getTypeInfoForLowered (getSILBoxFieldLoweredType (
1655
- IGM.getMaximalTypeExpansionContext (), T, IGM.getSILModule ().Types , 0 ));
1738
+ auto eltTy = getSILBoxFieldLoweredType (
1739
+ IGM.getMaximalTypeExpansionContext (), T, IGM.getSILModule ().Types , 0 );
1740
+ auto &eltTI = IGM.getTypeInfoForLowered (eltTy);
1656
1741
if (!eltTI.isFixedSize ()) {
1657
1742
if (!NonFixedBoxTI)
1658
1743
NonFixedBoxTI = new NonFixedBoxTypeInfo (IGM);
@@ -1662,12 +1747,16 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
1662
1747
// For fixed-sized types, we can emit concrete box metadata.
1663
1748
auto &fixedTI = cast<FixedTypeInfo>(eltTI);
1664
1749
1665
- // Because we assume in enum's that payloads with a Builtin.NativeReference
1750
+ // Because we assume in enums that payloads with a Builtin.NativeReference
1666
1751
// which is also the type for indirect enum cases have extra inhabitants of
1667
1752
// pointers we can't have a nil pointer as a representation for an empty box
1668
1753
// type -- nil conflicts with the extra inhabitants. We return a static
1669
1754
// singleton empty box object instead.
1670
- if (fixedTI.isKnownEmpty (ResilienceExpansion::Maximal)) {
1755
+ //
1756
+ // (If the box needs no storage, but the type still carries a deinit,
1757
+ // then we still need to trigger that deinit when the box is freed.)
1758
+ if (fixedTI.isKnownEmpty (ResilienceExpansion::Maximal)
1759
+ && fixedTI.isTriviallyDestroyable (ResilienceExpansion::Maximal)) {
1671
1760
if (!EmptyBoxTI)
1672
1761
EmptyBoxTI = new EmptyBoxTypeInfo (IGM);
1673
1762
return EmptyBoxTI;
@@ -1701,9 +1790,8 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
1701
1790
// Produce a tailored box metadata for the type.
1702
1791
assert (T->getLayout ()->getFields ().size () == 1
1703
1792
&& " multi-field boxes not implemented yet" );
1704
- return new FixedBoxTypeInfo (
1705
- IGM, getSILBoxFieldType (IGM.getMaximalTypeExpansionContext (),
1706
- T, IGM.getSILModule ().Types , 0 ));
1793
+
1794
+ return new FixedBoxTypeInfo (IGM, T);
1707
1795
}
1708
1796
1709
1797
OwnedAddress
@@ -1713,12 +1801,7 @@ irgen::emitAllocateBox(IRGenFunction &IGF, CanSILBoxType boxType,
1713
1801
auto &boxTI = IGF.getTypeInfoForLowered (boxType).as <BoxTypeInfo>();
1714
1802
assert (boxType->getLayout ()->getFields ().size () == 1
1715
1803
&& " multi-field boxes not implemented yet" );
1716
- return boxTI.allocate (
1717
- IGF,
1718
- getSILBoxFieldType (
1719
- IGF.IGM .getMaximalTypeExpansionContext (),
1720
- boxType, IGF.IGM .getSILModule ().Types , 0 ),
1721
- env, name);
1804
+ return boxTI.allocate (IGF, env, boxType, name);
1722
1805
}
1723
1806
1724
1807
void irgen::emitDeallocateBox (IRGenFunction &IGF,
@@ -1751,7 +1834,7 @@ Address irgen::emitAllocateExistentialBoxInBuffer(
1751
1834
// Get a box for the boxed value.
1752
1835
auto boxType = SILBoxType::get (boxedType.getASTType ());
1753
1836
auto &boxTI = IGF.getTypeInfoForLowered (boxType).as <BoxTypeInfo>();
1754
- OwnedAddress owned = boxTI.allocate (IGF, boxedType, env , name);
1837
+ OwnedAddress owned = boxTI.allocate (IGF, env, boxType , name);
1755
1838
Explosion box;
1756
1839
box.add (owned.getOwner ());
1757
1840
boxTI.initialize (IGF, box,
0 commit comments