|
27 | 27 | #include "swift/AST/ForeignInfo.h" |
28 | 28 | #include "swift/AST/GenericEnvironment.h" |
29 | 29 | #include "swift/AST/LocalArchetypeRequirementCollector.h" |
| 30 | +#include "swift/AST/ASTMangler.h" |
30 | 31 | #include "swift/AST/Module.h" |
31 | 32 | #include "swift/AST/ModuleLoader.h" |
32 | 33 | #include "swift/AST/TypeCheckRequests.h" |
|
46 | 47 | #include "llvm/Support/Debug.h" |
47 | 48 | #include "llvm/Support/ErrorHandling.h" |
48 | 49 | #include "llvm/Support/SaveAndRestore.h" |
| 50 | +#include "llvm/Support/SipHash.h" |
49 | 51 |
|
50 | 52 | using namespace swift; |
51 | 53 | using namespace swift::Lowering; |
@@ -1042,6 +1044,162 @@ CanSILFunctionType SILFunctionType::getAutoDiffDerivativeFunctionType( |
1042 | 1044 | return cachedResult; |
1043 | 1045 | } |
1044 | 1046 |
|
| 1047 | +static void hashStringForFunctionType(SILModule *M, CanSILFunctionType type, |
| 1048 | + raw_ostream &Out, |
| 1049 | + GenericEnvironment *genericEnv); |
| 1050 | + |
| 1051 | +static void hashStringForType(SILModule *M, CanType Ty, raw_ostream &Out, |
| 1052 | + GenericEnvironment *genericEnv) { |
| 1053 | + if (Ty->isAnyClassReferenceType()) { |
| 1054 | + // Any class type has to be hashed opaquely. |
| 1055 | + Out << "-class"; |
| 1056 | + } else if (isa<AnyMetatypeType>(Ty)) { |
| 1057 | + // Any metatype has to be hashed opaquely. |
| 1058 | + Out << "-metatype"; |
| 1059 | + } else if (auto UnwrappedTy = Ty->getOptionalObjectType()) { |
| 1060 | + if (UnwrappedTy->isBridgeableObjectType()) { |
| 1061 | + // Optional<T> is compatible with T when T is class-based. |
| 1062 | + hashStringForType(M, UnwrappedTy->getCanonicalType(), Out, genericEnv); |
| 1063 | + } else if (UnwrappedTy->is<MetatypeType>()) { |
| 1064 | + // Optional<T> is compatible with T when T is a metatype. |
| 1065 | + hashStringForType(M, UnwrappedTy->getCanonicalType(), Out, genericEnv); |
| 1066 | + } else { |
| 1067 | + // Optional<T> is direct if and only if T is. |
| 1068 | + Out << "Optional<"; |
| 1069 | + hashStringForType(M, UnwrappedTy->getCanonicalType(), Out, genericEnv); |
| 1070 | + Out << ">"; |
| 1071 | + } |
| 1072 | + } else if (auto ETy = dyn_cast<ExistentialType>(Ty)) { |
| 1073 | + // Look through existential types |
| 1074 | + hashStringForType(M, ETy->getConstraintType()->getCanonicalType(), |
| 1075 | + Out, genericEnv); |
| 1076 | + } else if (auto GTy = dyn_cast<AnyGenericType>(Ty)) { |
| 1077 | + // For generic and non-generic value types, use the mangled declaration |
| 1078 | + // name, and ignore all generic arguments. |
| 1079 | + NominalTypeDecl *nominal = cast<NominalTypeDecl>(GTy->getDecl()); |
| 1080 | + Out << Mangle::ASTMangler(Ty->getASTContext()).mangleNominalType(nominal); |
| 1081 | + } else if (auto FTy = dyn_cast<SILFunctionType>(Ty)) { |
| 1082 | + Out << "("; |
| 1083 | + hashStringForFunctionType(M, FTy, Out, genericEnv); |
| 1084 | + Out << ")"; |
| 1085 | + } else { |
| 1086 | + Out << "-"; |
| 1087 | + } |
| 1088 | +} |
| 1089 | + |
| 1090 | +template <class T> |
| 1091 | +static void hashStringForList(SILModule *M, const ArrayRef<T> &list, |
| 1092 | + raw_ostream &Out, GenericEnvironment *genericEnv, |
| 1093 | + const SILFunctionType *fnType) { |
| 1094 | + for (auto paramOrRetVal : list) { |
| 1095 | + if (paramOrRetVal.isFormalIndirect()) { |
| 1096 | + // Indirect params and return values have to be opaque. |
| 1097 | + Out << "-indirect"; |
| 1098 | + } else { |
| 1099 | + CanType Ty = M ? paramOrRetVal.getArgumentType( |
| 1100 | + *M, fnType, M->getMaximalTypeExpansionContext()) |
| 1101 | + : paramOrRetVal.getInterfaceType(); |
| 1102 | + if (Ty->hasTypeParameter()) |
| 1103 | + Ty = genericEnv->mapTypeIntoEnvironment(Ty)->getCanonicalType(); |
| 1104 | + hashStringForType(M, Ty, Out, genericEnv); |
| 1105 | + } |
| 1106 | + Out << ":"; |
| 1107 | + } |
| 1108 | +} |
| 1109 | + |
| 1110 | +static void hashStringForList(SILModule *M, const ArrayRef<SILResultInfo> &list, |
| 1111 | + raw_ostream &Out, GenericEnvironment *genericEnv, |
| 1112 | + const SILFunctionType *fnType) { |
| 1113 | + for (auto paramOrRetVal : list) { |
| 1114 | + if (paramOrRetVal.isFormalIndirect()) { |
| 1115 | + // Indirect params and return values have to be opaque. |
| 1116 | + Out << "-indirect"; |
| 1117 | + } else { |
| 1118 | + CanType Ty = M ? paramOrRetVal.getReturnValueType( |
| 1119 | + *M, fnType, M->getMaximalTypeExpansionContext()) |
| 1120 | + : paramOrRetVal.getInterfaceType(); |
| 1121 | + if (Ty->hasTypeParameter()) |
| 1122 | + Ty = genericEnv->mapTypeIntoEnvironment(Ty)->getCanonicalType(); |
| 1123 | + hashStringForType(M, Ty, Out, genericEnv); |
| 1124 | + } |
| 1125 | + Out << ":"; |
| 1126 | + } |
| 1127 | +} |
| 1128 | + |
| 1129 | +static void hashStringForFunctionType(SILModule *M, CanSILFunctionType type, |
| 1130 | + raw_ostream &Out, |
| 1131 | + GenericEnvironment *genericEnv) { |
| 1132 | + Out << (type->isCoroutine() ? "coroutine" : "function") << ":"; |
| 1133 | + Out << type->getNumParameters() << ":"; |
| 1134 | + hashStringForList(M, type->getParameters(), Out, genericEnv, type); |
| 1135 | + Out << type->getNumResults() << ":"; |
| 1136 | + hashStringForList(M, type->getResults(), Out, genericEnv, type); |
| 1137 | + if (type->isCoroutine()) { |
| 1138 | + Out << type->getNumYields() << ":"; |
| 1139 | + hashStringForList(M, type->getYields(), Out, genericEnv, type); |
| 1140 | + } |
| 1141 | +} |
| 1142 | + |
| 1143 | +uint16_t SILFunctionType::getPointerAuthDiscriminator(SILModule *M) { |
| 1144 | + // The hash we need to do here ignores: |
| 1145 | + // - thickness, so that we can promote thin-to-thick without rehashing; |
| 1146 | + // - error results, so that we can promote nonthrowing-to-throwing |
| 1147 | + // without rehashing; |
| 1148 | + // - isolation, so that global actor annotations can change in the SDK |
| 1149 | + // without breaking compatibility and so that we can erase it to |
| 1150 | + // nonisolated without rehashing; |
| 1151 | + // - types of indirect arguments/retvals, so they can be substituted freely; |
| 1152 | + // - types of class arguments/retvals |
| 1153 | + // - types of metatype arguments/retvals |
| 1154 | + // See isABICompatibleWith and areABICompatibleParamsOrReturns in |
| 1155 | + // SILFunctionType.cpp. |
| 1156 | + |
| 1157 | + SmallString<32> Buffer; |
| 1158 | + llvm::raw_svector_ostream Out(Buffer); |
| 1159 | + auto genericSig = getInvocationGenericSignature(); |
| 1160 | + hashStringForFunctionType( |
| 1161 | + M, CanSILFunctionType(this), Out, |
| 1162 | + genericSig.getCanonicalSignature().getGenericEnvironment()); |
| 1163 | + return llvm::getPointerAuthStableSipHash(Out.str()); |
| 1164 | +} |
| 1165 | + |
| 1166 | +uint16_t SILFunctionType::getCoroutineYieldTypesDiscriminator(SILModule &M) { |
| 1167 | + SmallString<32> buffer; |
| 1168 | + llvm::raw_svector_ostream out(buffer); |
| 1169 | + auto genericSig = getInvocationGenericSignature(); |
| 1170 | + auto *genericEnv = genericSig.getCanonicalSignature().getGenericEnvironment(); |
| 1171 | + |
| 1172 | + out << [&]() -> StringRef { |
| 1173 | + switch (getCoroutineKind()) { |
| 1174 | + case SILCoroutineKind::YieldMany: return "yield_many:"; |
| 1175 | + case SILCoroutineKind::YieldOnce: return "yield_once:"; |
| 1176 | + case SILCoroutineKind::YieldOnce2: return "yield_once_2:"; |
| 1177 | + case SILCoroutineKind::None: llvm_unreachable("not a coroutine"); |
| 1178 | + } |
| 1179 | + llvm_unreachable("bad coroutine kind"); |
| 1180 | + }(); |
| 1181 | + |
| 1182 | + out << getNumYields() << ":"; |
| 1183 | + |
| 1184 | + for (auto yield: getYields()) { |
| 1185 | + // We can't mangle types on inout and indirect yields because they're |
| 1186 | + // abstractable. |
| 1187 | + if (yield.isIndirectInOut()) { |
| 1188 | + out << "inout"; |
| 1189 | + } else if (yield.isFormalIndirect()) { |
| 1190 | + out << "indirect"; |
| 1191 | + } else { |
| 1192 | + CanType Ty = yield.getArgumentType(M, this, |
| 1193 | + M.getMaximalTypeExpansionContext()); |
| 1194 | + if (Ty->hasTypeParameter()) |
| 1195 | + Ty = genericEnv->mapTypeIntoEnvironment(Ty)->getCanonicalType(); |
| 1196 | + hashStringForType(&M, Ty, out, genericEnv); |
| 1197 | + } |
| 1198 | + out << ":"; |
| 1199 | + } |
| 1200 | + return llvm::getPointerAuthStableSipHash(out.str()); |
| 1201 | +} |
| 1202 | + |
1045 | 1203 | CanSILFunctionType SILFunctionType::getAutoDiffTransposeFunctionType( |
1046 | 1204 | IndexSubset *parameterIndices, Lowering::TypeConverter &TC, |
1047 | 1205 | LookupConformanceFn lookupConformance, |
|
0 commit comments