4141#include " IRGenDebugInfo.h"
4242#include " IRGenFunction.h"
4343#include " IRGenModule.h"
44+ #include " MetadataLayout.h"
4445#include " StructLayout.h"
4546#include " TypeInfo.h"
4647
@@ -815,15 +816,72 @@ static llvm::Constant *getMemCpyFunction(IRGenModule &IGM,
815816 });
816817}
817818
819+ namespace {
820+ struct BoundGenericTypeCharacteristics {
821+ SILType concreteType;
822+ const TypeInfo *TI;
823+ FixedPacking packing;
824+ };
825+
826+ ValueWitnessFlags getValueWitnessFlags (const TypeInfo *TI, SILType concreteType,
827+ FixedPacking packing) {
828+ ValueWitnessFlags flags;
829+
830+ // If we locally know that the type has fixed layout, we can emit
831+ // meaningful flags for it.
832+ if (auto *fixedTI = dyn_cast<FixedTypeInfo>(TI)) {
833+ assert (packing == FixedPacking::OffsetZero ||
834+ packing == FixedPacking::Allocate);
835+ bool isInline = packing == FixedPacking::OffsetZero;
836+ bool isBitwiseTakable =
837+ fixedTI->isBitwiseTakable (ResilienceExpansion::Maximal);
838+ assert (isBitwiseTakable || !isInline);
839+ flags = flags.withAlignment (fixedTI->getFixedAlignment ().getValue ())
840+ .withPOD (fixedTI->isPOD (ResilienceExpansion::Maximal))
841+ .withInlineStorage (isInline)
842+ .withBitwiseTakable (isBitwiseTakable);
843+ } else {
844+ flags = flags.withIncomplete (true );
845+ }
846+
847+ if (concreteType.getEnumOrBoundGenericEnum ())
848+ flags = flags.withEnumWitnesses (true );
849+
850+ return flags;
851+ }
852+
853+ unsigned getExtraInhabitantCount (const TypeInfo *TI, IRGenModule &IGM) {
854+ unsigned value = 0 ;
855+ if (auto *fixedTI = dyn_cast<FixedTypeInfo>(TI)) {
856+ value = fixedTI->getFixedExtraInhabitantCount (IGM);
857+ }
858+ return value;
859+ }
860+
861+ void addSize (ConstantStructBuilder &B, const TypeInfo *TI, IRGenModule &IGM) {
862+ if (auto staticSize = TI->getStaticSize (IGM))
863+ return B.add (staticSize);
864+ // Just fill in 0 here if the type can't be statically laid out.
865+ return B.addSize (Size (0 ));
866+ }
867+
868+ void addStride (ConstantStructBuilder &B, const TypeInfo *TI, IRGenModule &IGM) {
869+ if (auto value = TI->getStaticStride (IGM))
870+ return B.add (value);
871+
872+ // Just fill in null here if the type can't be statically laid out.
873+ return B.addSize (Size (0 ));
874+ }
875+ } // end anonymous namespace
876+
818877// / Find a witness to the fact that a type is a value type.
819878// / Always adds an i8*.
820- static void addValueWitness (IRGenModule &IGM,
821- ConstantStructBuilder &B,
822- ValueWitness index,
823- FixedPacking packing,
824- CanType abstractType,
825- SILType concreteType,
826- const TypeInfo &concreteTI) {
879+ static void addValueWitness (IRGenModule &IGM, ConstantStructBuilder &B,
880+ ValueWitness index, FixedPacking packing,
881+ CanType abstractType, SILType concreteType,
882+ const TypeInfo &concreteTI,
883+ const Optional<BoundGenericTypeCharacteristics>
884+ boundGenericCharacteristics = llvm::None) {
827885 auto addFunction = [&](llvm::Constant *fn) {
828886 fn = llvm::ConstantExpr::getBitCast (fn, IGM.Int8PtrTy );
829887 B.addSignedPointer (fn, IGM.getOptions ().PointerAuth .ValueWitnesses , index);
@@ -880,57 +938,51 @@ static void addValueWitness(IRGenModule &IGM,
880938 goto standard;
881939
882940 case ValueWitness::Size: {
883- if (auto value = concreteTI.getStaticSize (IGM))
884- return B.add (value);
885-
886- // Just fill in 0 here if the type can't be statically laid out.
887- return B.addSize (Size (0 ));
941+ if (boundGenericCharacteristics)
942+ return addSize (B, boundGenericCharacteristics->TI , IGM);
943+ return addSize (B, &concreteTI, IGM);
888944 }
889945
890946 case ValueWitness::Flags: {
891- ValueWitnessFlags flags;
892-
893- // If we locally know that the type has fixed layout, we can emit
894- // meaningful flags for it.
895- if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&concreteTI)) {
896- assert (packing == FixedPacking::OffsetZero ||
897- packing == FixedPacking::Allocate);
898- bool isInline = packing == FixedPacking::OffsetZero;
899- bool isBitwiseTakable =
900- fixedTI->isBitwiseTakable (ResilienceExpansion::Maximal);
901- assert (isBitwiseTakable || !isInline);
902- flags = flags.withAlignment (fixedTI->getFixedAlignment ().getValue ())
903- .withPOD (fixedTI->isPOD (ResilienceExpansion::Maximal))
904- .withInlineStorage (isInline)
905- .withBitwiseTakable (isBitwiseTakable);
906- } else {
907- flags = flags.withIncomplete (true );
908- }
909-
910- if (concreteType.getEnumOrBoundGenericEnum ())
911- flags = flags.withEnumWitnesses (true );
912-
913- return B.addInt32 (flags.getOpaqueValue ());
947+ if (boundGenericCharacteristics)
948+ return B.addInt32 (
949+ getValueWitnessFlags (boundGenericCharacteristics->TI ,
950+ boundGenericCharacteristics->concreteType ,
951+ boundGenericCharacteristics->packing )
952+ .getOpaqueValue ());
953+ return B.addInt32 (getValueWitnessFlags (&concreteTI, concreteType, packing)
954+ .getOpaqueValue ());
914955 }
915956
916957 case ValueWitness::ExtraInhabitantCount: {
917- unsigned value = 0 ;
918- if (auto *fixedTI = dyn_cast<FixedTypeInfo>(&concreteTI)) {
919- value = fixedTI->getFixedExtraInhabitantCount (IGM);
920- }
921- return B.addInt32 (value);
958+ if (boundGenericCharacteristics)
959+ return B.addInt32 (
960+ getExtraInhabitantCount (boundGenericCharacteristics->TI , IGM));
961+ return B.addInt32 (getExtraInhabitantCount (&concreteTI, IGM));
922962 }
923963
924964 case ValueWitness::Stride: {
925- if (auto value = concreteTI.getStaticStride (IGM))
926- return B.add (value);
927-
928- // Just fill in null here if the type can't be statically laid out.
929- return B.addSize (Size (0 ));
965+ if (boundGenericCharacteristics)
966+ return addStride (B, boundGenericCharacteristics->TI , IGM);
967+ return addStride (B, &concreteTI, IGM);
930968 }
931969
932- case ValueWitness::GetEnumTagSinglePayload:
970+ case ValueWitness::GetEnumTagSinglePayload: {
971+ if (boundGenericCharacteristics)
972+ if (auto *enumDecl = boundGenericCharacteristics->concreteType
973+ .getEnumOrBoundGenericEnum ())
974+ if (IGM.getMetadataLayout (enumDecl).hasPayloadSizeOffset ())
975+ return B.add (llvm::ConstantExpr::getBitCast (
976+ IGM.getGetMultiPayloadEnumTagSinglePayloadFn (), IGM.Int8PtrTy ));
977+ goto standard;
978+ }
933979 case ValueWitness::StoreEnumTagSinglePayload: {
980+ if (boundGenericCharacteristics)
981+ if (auto *enumDecl = boundGenericCharacteristics->concreteType
982+ .getEnumOrBoundGenericEnum ())
983+ if (IGM.getMetadataLayout (enumDecl).hasPayloadSizeOffset ())
984+ return B.add (llvm::ConstantExpr::getBitCast (
985+ IGM.getStoreMultiPayloadEnumTagSinglePayloadFn (), IGM.Int8PtrTy ));
934986 goto standard;
935987 }
936988
@@ -949,7 +1001,7 @@ static void addValueWitness(IRGenModule &IGM,
9491001 buildValueWitnessFunction (IGM, fn, index, packing, abstractType,
9501002 concreteType, concreteTI);
9511003 addFunction (fn);
952- }
1004+ }
9531005
9541006static bool shouldAddEnumWitnesses (CanType abstractType) {
9551007 // Needs to handle UnboundGenericType.
@@ -964,22 +1016,21 @@ static llvm::StructType *getValueWitnessTableType(IRGenModule &IGM,
9641016}
9651017
9661018// / Collect the value witnesses for a particular type.
967- static void addValueWitnesses (IRGenModule &IGM,
968- ConstantStructBuilder &B,
969- FixedPacking packing,
970- CanType abstractType,
971- SILType concreteType,
972- const TypeInfo &concreteTI) {
1019+ static void addValueWitnesses (IRGenModule &IGM, ConstantStructBuilder &B,
1020+ FixedPacking packing, CanType abstractType,
1021+ SILType concreteType, const TypeInfo &concreteTI,
1022+ const Optional<BoundGenericTypeCharacteristics>
1023+ boundGenericCharacteristics = llvm::None) {
9731024 for (unsigned i = 0 ; i != NumRequiredValueWitnesses; ++i) {
974- addValueWitness (IGM, B, ValueWitness (i), packing,
975- abstractType, concreteType, concreteTI);
1025+ addValueWitness (IGM, B, ValueWitness (i), packing, abstractType,
1026+ concreteType, concreteTI, boundGenericCharacteristics );
9761027 }
9771028 if (shouldAddEnumWitnesses (abstractType)) {
9781029 for (auto i = unsigned (ValueWitness::First_EnumValueWitness);
9791030 i <= unsigned (ValueWitness::Last_EnumValueWitness);
9801031 ++i) {
981- addValueWitness (IGM, B, ValueWitness (i), packing,
982- abstractType, concreteType, concreteTI);
1032+ addValueWitness (IGM, B, ValueWitness (i), packing, abstractType,
1033+ concreteType, concreteTI, boundGenericCharacteristics );
9831034 }
9841035 }
9851036}
@@ -995,6 +1046,19 @@ static void addValueWitnessesForAbstractType(IRGenModule &IGM,
9951046 ConstantStructBuilder &B,
9961047 CanType abstractType,
9971048 bool &canBeConstant) {
1049+ Optional<BoundGenericTypeCharacteristics> boundGenericCharacteristics;
1050+ if (auto boundGenericType = dyn_cast<BoundGenericType>(abstractType)) {
1051+ CanType concreteFormalType = getFormalTypeInContext (abstractType);
1052+
1053+ auto concreteLoweredType = IGM.getLoweredType (concreteFormalType);
1054+ const auto *boundConcreteTI = &IGM.getTypeInfo (concreteLoweredType);
1055+ auto packing = boundConcreteTI->getFixedPacking (IGM);
1056+ boundGenericCharacteristics = {concreteLoweredType, boundConcreteTI,
1057+ packing};
1058+
1059+ abstractType =
1060+ boundGenericType->getDecl ()->getDeclaredType ()->getCanonicalType ();
1061+ }
9981062 CanType concreteFormalType = getFormalTypeInContext (abstractType);
9991063
10001064 auto concreteLoweredType = IGM.getLoweredType (concreteFormalType);
@@ -1003,10 +1067,12 @@ static void addValueWitnessesForAbstractType(IRGenModule &IGM,
10031067
10041068 // For now, assume that we never have any interest in dynamically
10051069 // changing the value witnesses for something that's fixed-layout.
1006- canBeConstant = concreteTI.isFixedSize ();
1070+ canBeConstant = boundGenericCharacteristics
1071+ ? boundGenericCharacteristics->TI ->isFixedSize ()
1072+ : concreteTI.isFixedSize ();
10071073
1008- addValueWitnesses (IGM, B, packing, abstractType,
1009- concreteLoweredType, concreteTI );
1074+ addValueWitnesses (IGM, B, packing, abstractType, concreteLoweredType,
1075+ concreteTI, boundGenericCharacteristics );
10101076}
10111077
10121078static constexpr uint64_t sizeAndAlignment (Size size, Alignment alignment) {
0 commit comments