Skip to content

Commit 11d7c1e

Browse files
committed
Refactor: create SILFunctionType::getPointerAuthDiscriminator
1 parent 76c7be7 commit 11d7c1e

File tree

3 files changed

+166
-151
lines changed

3 files changed

+166
-151
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5949,6 +5949,10 @@ class SILFunctionType final
59495949
bool isReabstractionThunk = false,
59505950
CanType origTypeOfAbstraction = CanType());
59515951

5952+
/// If \p M is nullptr, the type is not substituted.
5953+
uint16_t getPointerAuthDiscriminator(SILModule *M);
5954+
5955+
uint16_t getCoroutineYieldTypesDiscriminator(SILModule &M);
59525956

59535957
/// Returns the type of the transpose function for the given parameter
59545958
/// indices, transpose function generic signature (optional), and other

lib/IRGen/GenPointerAuth.cpp

Lines changed: 4 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -478,163 +478,16 @@ PointerAuthEntity::getDeclDiscriminator(IRGenModule &IGM) const {
478478
llvm_unreachable("bad kind");
479479
}
480480

481-
static void hashStringForFunctionType(IRGenModule &IGM, CanSILFunctionType type,
482-
raw_ostream &Out,
483-
GenericEnvironment *genericEnv);
484-
485-
static void hashStringForType(IRGenModule &IGM, CanType Ty, raw_ostream &Out,
486-
GenericEnvironment *genericEnv) {
487-
if (Ty->isAnyClassReferenceType()) {
488-
// Any class type has to be hashed opaquely.
489-
Out << "-class";
490-
} else if (isa<AnyMetatypeType>(Ty)) {
491-
// Any metatype has to be hashed opaquely.
492-
Out << "-metatype";
493-
} else if (auto UnwrappedTy = Ty->getOptionalObjectType()) {
494-
if (UnwrappedTy->isBridgeableObjectType()) {
495-
// Optional<T> is compatible with T when T is class-based.
496-
hashStringForType(IGM, UnwrappedTy->getCanonicalType(), Out, genericEnv);
497-
} else if (UnwrappedTy->is<MetatypeType>()) {
498-
// Optional<T> is compatible with T when T is a metatype.
499-
hashStringForType(IGM, UnwrappedTy->getCanonicalType(), Out, genericEnv);
500-
} else {
501-
// Optional<T> is direct if and only if T is.
502-
Out << "Optional<";
503-
hashStringForType(IGM, UnwrappedTy->getCanonicalType(), Out, genericEnv);
504-
Out << ">";
505-
}
506-
} else if (auto ETy = dyn_cast<ExistentialType>(Ty)) {
507-
// Look through existential types
508-
hashStringForType(IGM, ETy->getConstraintType()->getCanonicalType(),
509-
Out, genericEnv);
510-
} else if (auto GTy = dyn_cast<AnyGenericType>(Ty)) {
511-
// For generic and non-generic value types, use the mangled declaration
512-
// name, and ignore all generic arguments.
513-
NominalTypeDecl *nominal = cast<NominalTypeDecl>(GTy->getDecl());
514-
Out << Mangle::ASTMangler(IGM.Context).mangleNominalType(nominal);
515-
} else if (auto FTy = dyn_cast<SILFunctionType>(Ty)) {
516-
Out << "(";
517-
hashStringForFunctionType(IGM, FTy, Out, genericEnv);
518-
Out << ")";
519-
} else {
520-
Out << "-";
521-
}
522-
}
523-
524-
template <class T>
525-
static void hashStringForList(IRGenModule &IGM, const ArrayRef<T> &list,
526-
raw_ostream &Out, GenericEnvironment *genericEnv,
527-
const SILFunctionType *fnType) {
528-
for (auto paramOrRetVal : list) {
529-
if (paramOrRetVal.isFormalIndirect()) {
530-
// Indirect params and return values have to be opaque.
531-
Out << "-indirect";
532-
} else {
533-
CanType Ty = paramOrRetVal.getArgumentType(
534-
IGM.getSILModule(), fnType, IGM.getMaximalTypeExpansionContext());
535-
if (Ty->hasTypeParameter())
536-
Ty = genericEnv->mapTypeIntoEnvironment(Ty)->getCanonicalType();
537-
hashStringForType(IGM, Ty, Out, genericEnv);
538-
}
539-
Out << ":";
540-
}
541-
}
542-
543-
static void hashStringForList(IRGenModule &IGM,
544-
const ArrayRef<SILResultInfo> &list,
545-
raw_ostream &Out, GenericEnvironment *genericEnv,
546-
const SILFunctionType *fnType) {
547-
for (auto paramOrRetVal : list) {
548-
if (paramOrRetVal.isFormalIndirect()) {
549-
// Indirect params and return values have to be opaque.
550-
Out << "-indirect";
551-
} else {
552-
CanType Ty = paramOrRetVal.getReturnValueType(
553-
IGM.getSILModule(), fnType, IGM.getMaximalTypeExpansionContext());
554-
if (Ty->hasTypeParameter())
555-
Ty = genericEnv->mapTypeIntoEnvironment(Ty)->getCanonicalType();
556-
hashStringForType(IGM, Ty, Out, genericEnv);
557-
}
558-
Out << ":";
559-
}
560-
}
561-
562-
static void hashStringForFunctionType(IRGenModule &IGM, CanSILFunctionType type,
563-
raw_ostream &Out,
564-
GenericEnvironment *genericEnv) {
565-
Out << (type->isCoroutine() ? "coroutine" : "function") << ":";
566-
Out << type->getNumParameters() << ":";
567-
hashStringForList(IGM, type->getParameters(), Out, genericEnv, type);
568-
Out << type->getNumResults() << ":";
569-
hashStringForList(IGM, type->getResults(), Out, genericEnv, type);
570-
if (type->isCoroutine()) {
571-
Out << type->getNumYields() << ":";
572-
hashStringForList(IGM, type->getYields(), Out, genericEnv, type);
573-
}
574-
}
575-
576481
static llvm::ConstantInt *getTypeDiscriminator(IRGenModule &IGM,
577482
CanSILFunctionType type) {
578-
// The hash we need to do here ignores:
579-
// - thickness, so that we can promote thin-to-thick without rehashing;
580-
// - error results, so that we can promote nonthrowing-to-throwing
581-
// without rehashing;
582-
// - isolation, so that global actor annotations can change in the SDK
583-
// without breaking compatibility and so that we can erase it to
584-
// nonisolated without rehashing;
585-
// - types of indirect arguments/retvals, so they can be substituted freely;
586-
// - types of class arguments/retvals
587-
// - types of metatype arguments/retvals
588-
// See isABICompatibleWith and areABICompatibleParamsOrReturns in
589-
// SILFunctionType.cpp.
590-
591-
SmallString<32> Buffer;
592-
llvm::raw_svector_ostream Out(Buffer);
593-
auto genericSig = type->getInvocationGenericSignature();
594-
hashStringForFunctionType(
595-
IGM, type, Out,
596-
genericSig.getCanonicalSignature().getGenericEnvironment());
597-
return getDiscriminatorForString(IGM, Out.str());
483+
return llvm::ConstantInt::get(
484+
IGM.Int64Ty, type->getPointerAuthDiscriminator(&IGM.getSILModule()));
598485
}
599486

600487
static llvm::ConstantInt *
601488
getCoroutineYieldTypesDiscriminator(IRGenModule &IGM, CanSILFunctionType type) {
602-
SmallString<32> buffer;
603-
llvm::raw_svector_ostream out(buffer);
604-
auto genericSig = type->getInvocationGenericSignature();
605-
auto *genericEnv = genericSig.getCanonicalSignature().getGenericEnvironment();
606-
607-
out << [&]() -> StringRef {
608-
switch (type->getCoroutineKind()) {
609-
case SILCoroutineKind::YieldMany: return "yield_many:";
610-
case SILCoroutineKind::YieldOnce: return "yield_once:";
611-
case SILCoroutineKind::YieldOnce2:
612-
return "yield_once_2:";
613-
case SILCoroutineKind::None: llvm_unreachable("not a coroutine");
614-
}
615-
llvm_unreachable("bad coroutine kind");
616-
}();
617-
618-
out << type->getNumYields() << ":";
619-
620-
for (auto yield: type->getYields()) {
621-
// We can't mangle types on inout and indirect yields because they're
622-
// abstractable.
623-
if (yield.isIndirectInOut()) {
624-
out << "inout";
625-
} else if (yield.isFormalIndirect()) {
626-
out << "indirect";
627-
} else {
628-
CanType Ty = yield.getArgumentType(IGM.getSILModule(), type,
629-
IGM.getMaximalTypeExpansionContext());
630-
if (Ty->hasTypeParameter())
631-
Ty = genericEnv->mapTypeIntoEnvironment(Ty)->getCanonicalType();
632-
hashStringForType(IGM, Ty, out, genericEnv);
633-
}
634-
out << ":";
635-
}
636-
637-
return getDiscriminatorForString(IGM, out.str());
489+
return llvm::ConstantInt::get(
490+
IGM.Int64Ty, type->getCoroutineYieldTypesDiscriminator(IGM.getSILModule()));
638491
}
639492

640493
llvm::ConstantInt *

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/ForeignInfo.h"
2828
#include "swift/AST/GenericEnvironment.h"
2929
#include "swift/AST/LocalArchetypeRequirementCollector.h"
30+
#include "swift/AST/ASTMangler.h"
3031
#include "swift/AST/Module.h"
3132
#include "swift/AST/ModuleLoader.h"
3233
#include "swift/AST/TypeCheckRequests.h"
@@ -46,6 +47,7 @@
4647
#include "llvm/Support/Debug.h"
4748
#include "llvm/Support/ErrorHandling.h"
4849
#include "llvm/Support/SaveAndRestore.h"
50+
#include "llvm/Support/SipHash.h"
4951

5052
using namespace swift;
5153
using namespace swift::Lowering;
@@ -1042,6 +1044,162 @@ CanSILFunctionType SILFunctionType::getAutoDiffDerivativeFunctionType(
10421044
return cachedResult;
10431045
}
10441046

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+
10451203
CanSILFunctionType SILFunctionType::getAutoDiffTransposeFunctionType(
10461204
IndexSubset *parameterIndices, Lowering::TypeConverter &TC,
10471205
LookupConformanceFn lookupConformance,

0 commit comments

Comments
 (0)