@@ -568,8 +568,10 @@ llvm::Value *IRGenFunction::emitUnmanagedAlloc(const HeapLayout &layout,
568568 const llvm::Twine &name,
569569 llvm::Constant *captureDescriptor,
570570 const HeapNonFixedOffsets *offsets) {
571- if (layout.isKnownEmpty ())
571+ if (layout.isKnownEmpty ()
572+ && layout.isTriviallyDestroyable ()) {
572573 return IGM.RefCountedNull ;
574+ }
573575
574576 llvm::Value *metadata = layout.getPrivateMetadata (IGM, captureDescriptor);
575577 llvm::Value *size, *alignMask;
@@ -1470,7 +1472,7 @@ class BoxTypeInfo : public HeapTypeInfo<BoxTypeInfo> {
14701472
14711473 // / Allocate a box of the given type.
14721474 virtual OwnedAddress
1473- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1475+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *box ,
14741476 const llvm::Twine &name) const = 0 ;
14751477
14761478 // / Deallocate an uninitialized box.
@@ -1488,8 +1490,11 @@ class EmptyBoxTypeInfo final : public BoxTypeInfo {
14881490 EmptyBoxTypeInfo (IRGenModule &IGM) : BoxTypeInfo(IGM) {}
14891491
14901492 OwnedAddress
1491- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1493+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *box ,
14921494 const llvm::Twine &name) const override {
1495+ auto boxedType = getSILBoxFieldType (
1496+ IGF.IGM .getMaximalTypeExpansionContext (),
1497+ box, IGF.IGM .getSILModule ().Types , 0 );
14931498 return OwnedAddress (IGF.getTypeInfo (boxedType).getUndefAddress (),
14941499 IGF.emitAllocEmptyBoxCall ());
14951500 }
@@ -1513,8 +1518,11 @@ class NonFixedBoxTypeInfo final : public BoxTypeInfo {
15131518 NonFixedBoxTypeInfo (IRGenModule &IGM) : BoxTypeInfo(IGM) {}
15141519
15151520 OwnedAddress
1516- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1521+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *boxType ,
15171522 const llvm::Twine &name) const override {
1523+ auto boxedType = getSILBoxFieldType (
1524+ IGF.IGM .getMaximalTypeExpansionContext (),
1525+ boxType, IGF.IGM .getSILModule ().Types , 0 );
15181526 auto &ti = IGF.getTypeInfo (boxedType);
15191527 // Use the runtime to allocate a box of the appropriate size.
15201528 auto metadata = IGF.emitTypeMetadataRefForLayout (boxedType);
@@ -1552,14 +1560,18 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
15521560 FixedBoxTypeInfoBase (IRGenModule &IGM, HeapLayout &&layout)
15531561 : BoxTypeInfo(IGM), layout(std::move(layout))
15541562 {
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 ());
15571566 }
15581567
15591568 OwnedAddress
1560- allocate (IRGenFunction &IGF, SILType boxedType, GenericEnvironment *env ,
1569+ allocate (IRGenFunction &IGF, GenericEnvironment *env, SILBoxType *box ,
15611570 const llvm::Twine &name)
15621571 const override {
1572+ auto boxedType = getSILBoxFieldType (
1573+ IGF.IGM .getMaximalTypeExpansionContext (),
1574+ box, IGF.IGM .getSILModule ().Types , 0 );
15631575 // Allocate a new object using the layout.
15641576 auto boxedInterfaceType = boxedType;
15651577 if (env) {
@@ -1583,13 +1595,21 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
15831595 boxedInterfaceType = SILType::getPrimitiveType (
15841596 astType, boxedInterfaceType.getCategory ());
15851597 }
1586-
1598+
15871599 auto boxDescriptor = IGF.IGM .getAddrOfBoxDescriptor (
15881600 boxedInterfaceType,
15891601 env ? env->getGenericSignature ().getCanonicalSignature ()
15901602 : CanGenericSignature ());
15911603 llvm::Value *allocation = IGF.emitUnmanagedAlloc (layout, name,
15921604 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+
15931613 Address rawAddr = project (IGF, allocation, boxedType);
15941614 return {rawAddr, allocation};
15951615 }
@@ -1639,22 +1659,87 @@ class SingleRefcountedBoxTypeInfo final : public FixedBoxTypeInfoBase {
16391659
16401660// / Implementation of a box for a specific type.
16411661class 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+
16421691public:
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))
16461694 {}
16471695};
16481696
16491697} // end anonymous namespace
16501698
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+
16511735const TypeInfo *TypeConverter::convertBoxType (SILBoxType *T) {
16521736 // We can share a type info for all dynamic-sized heap metadata.
16531737 // TODO: Multi-field boxes
16541738 assert (T->getLayout ()->getFields ().size () == 1
16551739 && " 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);
16581743 if (!eltTI.isFixedSize ()) {
16591744 if (!NonFixedBoxTI)
16601745 NonFixedBoxTI = new NonFixedBoxTypeInfo (IGM);
@@ -1664,12 +1749,16 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
16641749 // For fixed-sized types, we can emit concrete box metadata.
16651750 auto &fixedTI = cast<FixedTypeInfo>(eltTI);
16661751
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
16681753 // which is also the type for indirect enum cases have extra inhabitants of
16691754 // pointers we can't have a nil pointer as a representation for an empty box
16701755 // type -- nil conflicts with the extra inhabitants. We return a static
16711756 // 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)) {
16731762 if (!EmptyBoxTI)
16741763 EmptyBoxTI = new EmptyBoxTypeInfo (IGM);
16751764 return EmptyBoxTI;
@@ -1703,9 +1792,8 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
17031792 // Produce a tailored box metadata for the type.
17041793 assert (T->getLayout ()->getFields ().size () == 1
17051794 && " 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);
17091797}
17101798
17111799OwnedAddress
@@ -1715,12 +1803,7 @@ irgen::emitAllocateBox(IRGenFunction &IGF, CanSILBoxType boxType,
17151803 auto &boxTI = IGF.getTypeInfoForLowered (boxType).as <BoxTypeInfo>();
17161804 assert (boxType->getLayout ()->getFields ().size () == 1
17171805 && " 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);
17241807}
17251808
17261809void irgen::emitDeallocateBox (IRGenFunction &IGF,
@@ -1753,7 +1836,7 @@ Address irgen::emitAllocateExistentialBoxInBuffer(
17531836 // Get a box for the boxed value.
17541837 auto boxType = SILBoxType::get (boxedType.getASTType ());
17551838 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);
17571840 Explosion box;
17581841 box.add (owned.getOwner ());
17591842 boxTI.initialize (IGF, box,
0 commit comments