@@ -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) {
@@ -1581,13 +1593,21 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo {
15811593 boxedInterfaceType = SILType::getPrimitiveType (
15821594 astType, boxedInterfaceType.getCategory ());
15831595 }
1584-
1596+
15851597 auto boxDescriptor = IGF.IGM .getAddrOfBoxDescriptor (
15861598 boxedInterfaceType,
15871599 env ? env->getGenericSignature ().getCanonicalSignature ()
15881600 : CanGenericSignature ());
15891601 llvm::Value *allocation = IGF.emitUnmanagedAlloc (layout, name,
15901602 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+
15911611 Address rawAddr = project (IGF, allocation, boxedType);
15921612 return {rawAddr, allocation};
15931613 }
@@ -1637,22 +1657,87 @@ class SingleRefcountedBoxTypeInfo final : public FixedBoxTypeInfoBase {
16371657
16381658// / Implementation of a box for a specific type.
16391659class 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+
16401689public:
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))
16441692 {}
16451693};
16461694
16471695} // end anonymous namespace
16481696
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+
16491733const TypeInfo *TypeConverter::convertBoxType (SILBoxType *T) {
16501734 // We can share a type info for all dynamic-sized heap metadata.
16511735 // TODO: Multi-field boxes
16521736 assert (T->getLayout ()->getFields ().size () == 1
16531737 && " 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);
16561741 if (!eltTI.isFixedSize ()) {
16571742 if (!NonFixedBoxTI)
16581743 NonFixedBoxTI = new NonFixedBoxTypeInfo (IGM);
@@ -1662,12 +1747,16 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
16621747 // For fixed-sized types, we can emit concrete box metadata.
16631748 auto &fixedTI = cast<FixedTypeInfo>(eltTI);
16641749
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
16661751 // which is also the type for indirect enum cases have extra inhabitants of
16671752 // pointers we can't have a nil pointer as a representation for an empty box
16681753 // type -- nil conflicts with the extra inhabitants. We return a static
16691754 // 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)) {
16711760 if (!EmptyBoxTI)
16721761 EmptyBoxTI = new EmptyBoxTypeInfo (IGM);
16731762 return EmptyBoxTI;
@@ -1701,9 +1790,8 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) {
17011790 // Produce a tailored box metadata for the type.
17021791 assert (T->getLayout ()->getFields ().size () == 1
17031792 && " 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);
17071795}
17081796
17091797OwnedAddress
@@ -1713,12 +1801,7 @@ irgen::emitAllocateBox(IRGenFunction &IGF, CanSILBoxType boxType,
17131801 auto &boxTI = IGF.getTypeInfoForLowered (boxType).as <BoxTypeInfo>();
17141802 assert (boxType->getLayout ()->getFields ().size () == 1
17151803 && " 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);
17221805}
17231806
17241807void irgen::emitDeallocateBox (IRGenFunction &IGF,
@@ -1751,7 +1834,7 @@ Address irgen::emitAllocateExistentialBoxInBuffer(
17511834 // Get a box for the boxed value.
17521835 auto boxType = SILBoxType::get (boxedType.getASTType ());
17531836 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);
17551838 Explosion box;
17561839 box.add (owned.getOwner ());
17571840 boxTI.initialize (IGF, box,
0 commit comments