@@ -109,6 +109,11 @@ namespace {
109
109
Address projectMetadataRef (IRGenFunction &IGF, Address addr) {
110
110
return IGF.Builder .CreateStructGEP (addr, 1 , getFixedBufferSize (IGF.IGM ));
111
111
}
112
+
113
+ // / Give the offset of the metadata field of an existential object.
114
+ Size getMetadataRefOffset (IRGenModule &IGM) {
115
+ return getFixedBufferSize (IGM);
116
+ }
112
117
113
118
// / Given the address of an existential object, load its metadata
114
119
// / object.
@@ -810,12 +815,12 @@ class OpaqueExistentialTypeInfo final :
810
815
IndirectTypeInfo<OpaqueExistentialTypeInfo, FixedTypeInfo>>;
811
816
friend super;
812
817
813
- // FIXME: We could get spare bits out of the metadata and/or witness
814
- // pointers.
815
818
OpaqueExistentialTypeInfo (ArrayRef<const ProtocolDecl *> protocols,
816
- llvm::Type *ty, Size size, Alignment align)
819
+ llvm::Type *ty, Size size,
820
+ SpareBitVector &&spareBits,
821
+ Alignment align)
817
822
: super(protocols, ty, size,
818
- SpareBitVector::getConstant (size.getValueInBits(), false ), align,
823
+ std::move (spareBits ), align,
819
824
IsNotPOD, IsBitwiseTakable, IsFixedSize) {}
820
825
821
826
public:
@@ -902,6 +907,37 @@ class OpaqueExistentialTypeInfo final :
902
907
call->setDoesNotThrow ();
903
908
return ;
904
909
}
910
+
911
+ // Opaque existentials have extra inhabitants and spare bits in their type
912
+ // metadata pointer, matching those of a standalone thick metatype (which
913
+ // in turn match those of a heap object).
914
+ unsigned getFixedExtraInhabitantCount (IRGenModule &IGM) const override {
915
+ return getHeapObjectExtraInhabitantCount (IGM);
916
+ }
917
+ APInt getFixedExtraInhabitantValue (IRGenModule &IGM,
918
+ unsigned bits,
919
+ unsigned index) const override {
920
+ auto offset = getLayout ().getMetadataRefOffset (IGM).getValueInBits ();
921
+ return getHeapObjectFixedExtraInhabitantValue (IGM, bits, index , offset);
922
+ }
923
+ APInt getFixedExtraInhabitantMask (IRGenModule &IGM) const override {
924
+ auto mask = APInt::getAllOnesValue (IGM.getPointerSize ().getValueInBits ());
925
+ mask = mask.zext (getFixedSize ().getValueInBits ());
926
+ mask = mask.shl (getLayout ().getMetadataRefOffset (IGM).getValueInBits ());
927
+ return mask;
928
+ }
929
+ llvm::Value *getExtraInhabitantIndex (IRGenFunction &IGF,
930
+ Address src, SILType T,
931
+ bool isOutlined) const override {
932
+ auto type = getLayout ().projectMetadataRef (IGF, src);
933
+ return getHeapObjectExtraInhabitantIndex (IGF, type);
934
+ }
935
+ void storeExtraInhabitant (IRGenFunction &IGF, llvm::Value *index,
936
+ Address dest, SILType T, bool isOutlined)
937
+ const override {
938
+ auto type = getLayout ().projectMetadataRef (IGF, dest);
939
+ return storeHeapObjectExtraInhabitant (IGF, index , type);
940
+ }
905
941
};
906
942
907
943
@@ -1407,7 +1443,27 @@ static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM, CanType T) {
1407
1443
OpaqueExistentialLayout opaque (protosWithWitnessTables.size ());
1408
1444
Alignment align = opaque.getAlignment (IGM);
1409
1445
Size size = opaque.getSize (IGM);
1446
+ // There are spare bits in the metadata pointer and witness table pointers
1447
+ // consistent with a native object reference.
1448
+ SpareBitVector spareBits;
1449
+ spareBits.appendClearBits (size.getValueInBits ());
1450
+ /* TODO: There are spare bits we could theoretically use in the type metadata
1451
+ and witness table pointers, but opaque existentials are currently address-
1452
+ only, and we can't soundly take advantage of spare bits for in-memory
1453
+ representations.
1454
+
1455
+ auto metadataOffset = opaque.getMetadataRefOffset(IGM);
1456
+ spareBits.appendClearBits(metadataOffset.getValueInBits());
1457
+ auto typeSpareBits = IGM.getHeapObjectSpareBits();
1458
+ spareBits.append(typeSpareBits);
1459
+ auto witnessSpareBits =
1460
+ IGM.getWitnessTablePtrSpareBits();
1461
+ for (unsigned i = 0, e = protosWithWitnessTables.size(); i < e; ++i)
1462
+ spareBits.append(witnessSpareBits);
1463
+ assert(spareBits.size() == size.getValueInBits());
1464
+ */
1410
1465
return OpaqueExistentialTypeInfo::create (protosWithWitnessTables, type, size,
1466
+ std::move (spareBits),
1411
1467
align);
1412
1468
}
1413
1469
0 commit comments