41
41
#include " IRGenDebugInfo.h"
42
42
#include " IRGenFunction.h"
43
43
#include " IRGenModule.h"
44
+ #include " MetadataLayout.h"
44
45
#include " StructLayout.h"
45
46
#include " TypeInfo.h"
46
47
@@ -815,15 +816,72 @@ static llvm::Constant *getMemCpyFunction(IRGenModule &IGM,
815
816
});
816
817
}
817
818
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
+
818
877
// / Find a witness to the fact that a type is a value type.
819
878
// / 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) {
827
885
auto addFunction = [&](llvm::Constant *fn) {
828
886
fn = llvm::ConstantExpr::getBitCast (fn, IGM.Int8PtrTy );
829
887
B.addSignedPointer (fn, IGM.getOptions ().PointerAuth .ValueWitnesses , index);
@@ -880,57 +938,51 @@ static void addValueWitness(IRGenModule &IGM,
880
938
goto standard;
881
939
882
940
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);
888
944
}
889
945
890
946
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 ());
914
955
}
915
956
916
957
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));
922
962
}
923
963
924
964
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);
930
968
}
931
969
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
+ }
933
979
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 ));
934
986
goto standard;
935
987
}
936
988
@@ -949,7 +1001,7 @@ static void addValueWitness(IRGenModule &IGM,
949
1001
buildValueWitnessFunction (IGM, fn, index, packing, abstractType,
950
1002
concreteType, concreteTI);
951
1003
addFunction (fn);
952
- }
1004
+ }
953
1005
954
1006
static bool shouldAddEnumWitnesses (CanType abstractType) {
955
1007
// Needs to handle UnboundGenericType.
@@ -964,22 +1016,21 @@ static llvm::StructType *getValueWitnessTableType(IRGenModule &IGM,
964
1016
}
965
1017
966
1018
// / 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) {
973
1024
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 );
976
1027
}
977
1028
if (shouldAddEnumWitnesses (abstractType)) {
978
1029
for (auto i = unsigned (ValueWitness::First_EnumValueWitness);
979
1030
i <= unsigned (ValueWitness::Last_EnumValueWitness);
980
1031
++i) {
981
- addValueWitness (IGM, B, ValueWitness (i), packing,
982
- abstractType, concreteType, concreteTI);
1032
+ addValueWitness (IGM, B, ValueWitness (i), packing, abstractType,
1033
+ concreteType, concreteTI, boundGenericCharacteristics );
983
1034
}
984
1035
}
985
1036
}
@@ -995,6 +1046,19 @@ static void addValueWitnessesForAbstractType(IRGenModule &IGM,
995
1046
ConstantStructBuilder &B,
996
1047
CanType abstractType,
997
1048
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
+ }
998
1062
CanType concreteFormalType = getFormalTypeInContext (abstractType);
999
1063
1000
1064
auto concreteLoweredType = IGM.getLoweredType (concreteFormalType);
@@ -1003,10 +1067,12 @@ static void addValueWitnessesForAbstractType(IRGenModule &IGM,
1003
1067
1004
1068
// For now, assume that we never have any interest in dynamically
1005
1069
// changing the value witnesses for something that's fixed-layout.
1006
- canBeConstant = concreteTI.isFixedSize ();
1070
+ canBeConstant = boundGenericCharacteristics
1071
+ ? boundGenericCharacteristics->TI ->isFixedSize ()
1072
+ : concreteTI.isFixedSize ();
1007
1073
1008
- addValueWitnesses (IGM, B, packing, abstractType,
1009
- concreteLoweredType, concreteTI );
1074
+ addValueWitnesses (IGM, B, packing, abstractType, concreteLoweredType,
1075
+ concreteTI, boundGenericCharacteristics );
1010
1076
}
1011
1077
1012
1078
static constexpr uint64_t sizeAndAlignment (Size size, Alignment alignment) {
0 commit comments