Skip to content

Commit 1d05c35

Browse files
committed
SIL: AbstractionPattern support for typed throws
1 parent 736d0da commit 1d05c35

File tree

5 files changed

+160
-9
lines changed

5 files changed

+160
-9
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,22 @@ class AbstractionPattern {
15211521
/// abstraction pattern for its result type.
15221522
AbstractionPattern getFunctionResultType() const;
15231523

1524+
/// Given that the value being abstracted is a function, return the
1525+
/// abstraction pattern for its thrown error type.
1526+
llvm::Optional<AbstractionPattern> getFunctionThrownErrorType() const;
1527+
1528+
/// Utility method to adjust a thrown error pattern and thrown error type
1529+
/// to account for some quirks in type lowering.
1530+
///
1531+
/// When lowered with an opaque pattern,
1532+
///
1533+
/// - () -> () becomes () -> (),
1534+
/// - () throws(any Error) -> () becomes () -> (@error any Error),
1535+
///
1536+
/// *not* () -> (@error_indirect Never) or () -> (@error_indirect any Error).
1537+
llvm::Optional<std::pair<AbstractionPattern, CanType>>
1538+
getFunctionThrownErrorType(CanAnyFunctionType substFnInterfaceType) const;
1539+
15241540
/// Given that the value being abstracted is a function type, return
15251541
/// the abstraction pattern for one of its parameter types.
15261542
AbstractionPattern getFunctionParamType(unsigned index) const;
@@ -1611,15 +1627,19 @@ class AbstractionPattern {
16111627
/// Given that this is a pack expansion, do the pack elements need to be
16121628
/// passed indirectly?
16131629
bool arePackElementsPassedIndirectly(TypeConverter &TC) const;
1614-
1630+
16151631
/// If this abstraction pattern appears in function return position, how is
16161632
/// the corresponding value returned?
16171633
CallingConventionKind getResultConvention(TypeConverter &TC) const;
1618-
1634+
16191635
/// If this abstraction pattern appears in function parameter position, how
16201636
/// is the corresponding value passed?
16211637
CallingConventionKind getParameterConvention(TypeConverter &TC) const;
1622-
1638+
1639+
/// If this abstraction pattern appears in function thrown error position, how
1640+
/// is the corresponding value passed?
1641+
CallingConventionKind getErrorConvention(TypeConverter &TC) const;
1642+
16231643
/// Generate the abstraction pattern for lowering the substituted SIL
16241644
/// function type for a function type matching this abstraction pattern.
16251645
///

include/swift/SIL/SILFunctionConventions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ class SILModuleConventions {
7878
public:
7979
static bool isPassedIndirectlyInSIL(SILType type, SILModule &M);
8080

81+
static bool isThrownIndirectlyInSIL(SILType type, SILModule &M);
82+
8183
static bool isReturnedIndirectlyInSIL(SILType type, SILModule &M);
8284

8385
static SILModuleConventions getLoweredAddressConventions(SILModule &M) {

include/swift/SIL/SILType.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,13 @@ class SILType {
340340
return isAddressOnly(type, tc, sig, TypeExpansionContext::minimal());
341341
}
342342

343+
/// Return true if this type must be thrown indirectly.
344+
static bool isFormallyThrownIndirectly(CanType type,
345+
Lowering::TypeConverter &tc,
346+
CanGenericSignature sig) {
347+
return isAddressOnly(type, tc, sig, TypeExpansionContext::minimal());
348+
}
349+
343350
/// True if the type, or the referenced type of an address type, is loadable.
344351
/// This is the opposite of isAddressOnly.
345352
bool isLoadable(const SILFunction &F) const {

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,78 @@ AbstractionPattern AbstractionPattern::getFunctionResultType() const {
12141214
llvm_unreachable("bad kind");
12151215
}
12161216

1217+
llvm::Optional<AbstractionPattern>
1218+
AbstractionPattern::getFunctionThrownErrorType() const {
1219+
switch (getKind()) {
1220+
case Kind::Invalid:
1221+
llvm_unreachable("querying invalid abstraction pattern!");
1222+
case Kind::ObjCCompletionHandlerArgumentsType:
1223+
case Kind::Tuple:
1224+
llvm_unreachable("abstraction pattern for tuple cannot be function");
1225+
case Kind::Opaque:
1226+
return *this;
1227+
case Kind::Type: {
1228+
if (isTypeParameterOrOpaqueArchetype())
1229+
return getOpaque();
1230+
1231+
if (auto errorType = cast<AnyFunctionType>(getType())->getEffectiveThrownErrorType()) {
1232+
return AbstractionPattern(getGenericSubstitutions(),
1233+
getGenericSignatureForFunctionComponent(),
1234+
(*errorType)->getCanonicalType());
1235+
}
1236+
1237+
return llvm::None;
1238+
}
1239+
case Kind::Discard:
1240+
llvm_unreachable("don't need to discard function abstractions yet");
1241+
case Kind::ClangType:
1242+
case Kind::CFunctionAsMethodType:
1243+
case Kind::PartialCurriedCFunctionAsMethodType:
1244+
case Kind::CXXMethodType:
1245+
case Kind::PartialCurriedCXXMethodType:
1246+
case Kind::CurriedObjCMethodType:
1247+
case Kind::CurriedCFunctionAsMethodType:
1248+
case Kind::CurriedCXXMethodType:
1249+
case Kind::PartialCurriedObjCMethodType:
1250+
case Kind::ObjCMethodType:
1251+
llvm_unreachable("implement me");
1252+
case Kind::OpaqueFunction:
1253+
case Kind::OpaqueDerivativeFunction:
1254+
return llvm::None;
1255+
}
1256+
llvm_unreachable("bad kind");
1257+
}
1258+
1259+
llvm::Optional<std::pair<AbstractionPattern, CanType>>
1260+
AbstractionPattern::getFunctionThrownErrorType(
1261+
CanAnyFunctionType substFnInterfaceType) const {
1262+
auto optOrigErrorType = getFunctionThrownErrorType();
1263+
if (!optOrigErrorType)
1264+
return llvm::None;
1265+
1266+
auto &ctx = substFnInterfaceType->getASTContext();
1267+
auto optErrorType = substFnInterfaceType->getEffectiveThrownErrorType();
1268+
1269+
if (isTypeParameterOrOpaqueArchetype()) {
1270+
if (!optErrorType)
1271+
return llvm::None;
1272+
1273+
if (!(*optErrorType)->isEqual(ctx.getErrorExistentialType())) {
1274+
llvm::errs() << "unsupported reabstraction\n";
1275+
abort();
1276+
}
1277+
1278+
return std::make_pair(AbstractionPattern(*optErrorType),
1279+
(*optErrorType)->getCanonicalType());
1280+
}
1281+
1282+
if (!optErrorType)
1283+
optErrorType = ctx.getErrorExistentialType();
1284+
1285+
return std::make_pair(*optOrigErrorType,
1286+
(*optErrorType)->getCanonicalType());
1287+
}
1288+
12171289
AbstractionPattern
12181290
AbstractionPattern::getObjCMethodAsyncCompletionHandlerType(
12191291
CanType swiftCompletionHandlerType) const {
@@ -1939,7 +2011,7 @@ AbstractionPattern::getParameterConvention(TypeConverter &TC) const {
19392011
case Kind::Opaque:
19402012
// Maximally abstracted values are always passed indirectly.
19412013
return Indirect;
1942-
2014+
19432015
case Kind::OpaqueFunction:
19442016
case Kind::OpaqueDerivativeFunction:
19452017
case Kind::PartialCurriedObjCMethodType:
@@ -1953,16 +2025,57 @@ AbstractionPattern::getParameterConvention(TypeConverter &TC) const {
19532025
case Kind::PartialCurriedCXXMethodType:
19542026
// Function types are always passed directly
19552027
return Direct;
1956-
2028+
19572029
case Kind::ClangType:
19582030
case Kind::Type:
19592031
case Kind::Discard:
19602032
// Pass according to the formal type.
19612033
return SILType::isFormallyPassedIndirectly(getType(),
1962-
TC,
1963-
getGenericSignatureOrNull())
2034+
TC,
2035+
getGenericSignatureOrNull())
19642036
? Indirect : Direct;
1965-
2037+
2038+
case Kind::Invalid:
2039+
case Kind::Tuple:
2040+
case Kind::ObjCCompletionHandlerArgumentsType:
2041+
llvm_unreachable("should not get here");
2042+
}
2043+
}
2044+
2045+
AbstractionPattern::CallingConventionKind
2046+
AbstractionPattern::getErrorConvention(TypeConverter &TC) const {
2047+
// Tuples should be destructured.
2048+
if (isTuple()) {
2049+
return Destructured;
2050+
}
2051+
switch (getKind()) {
2052+
case Kind::Opaque:
2053+
// Maximally abstracted values are always thrown indirectly.
2054+
return Indirect;
2055+
2056+
case Kind::OpaqueFunction:
2057+
case Kind::OpaqueDerivativeFunction:
2058+
case Kind::PartialCurriedObjCMethodType:
2059+
case Kind::CurriedObjCMethodType:
2060+
case Kind::PartialCurriedCFunctionAsMethodType:
2061+
case Kind::CurriedCFunctionAsMethodType:
2062+
case Kind::CFunctionAsMethodType:
2063+
case Kind::ObjCMethodType:
2064+
case Kind::CXXMethodType:
2065+
case Kind::CurriedCXXMethodType:
2066+
case Kind::PartialCurriedCXXMethodType:
2067+
// Function types are always thrown directly
2068+
return Direct;
2069+
2070+
case Kind::ClangType:
2071+
case Kind::Type:
2072+
case Kind::Discard:
2073+
// Pass according to the formal type.
2074+
return SILType::isFormallyThrownIndirectly(getType(),
2075+
TC,
2076+
getGenericSignatureOrNull())
2077+
? Indirect : Direct;
2078+
19662079
case Kind::Invalid:
19672080
case Kind::Tuple:
19682081
case Kind::ObjCCompletionHandlerArgumentsType:
@@ -2562,7 +2675,7 @@ const {
25622675
auto substTy = visitor.handleUnabstractedFunctionType(substType, *this,
25632676
substYieldType,
25642677
origYieldType);
2565-
2678+
25662679
auto substSig = buildGenericSignature(TC.Context, GenericSignature(),
25672680
std::move(visitor.substGenericParams),
25682681
std::move(visitor.substRequirements))

lib/SIL/IR/SILType.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,15 @@ bool SILModuleConventions::isPassedIndirectlyInSIL(SILType type, SILModule &M) {
713713
return false;
714714
}
715715

716+
bool SILModuleConventions::isThrownIndirectlyInSIL(SILType type, SILModule &M) {
717+
if (SILModuleConventions(M).loweredAddresses) {
718+
return M.Types.getTypeLowering(type, TypeExpansionContext::minimal())
719+
.isAddressOnly();
720+
}
721+
722+
return false;
723+
}
724+
716725
bool SILFunctionType::isNoReturnFunction(SILModule &M,
717726
TypeExpansionContext context) const {
718727
for (unsigned i = 0, e = getNumResults(); i < e; ++i) {

0 commit comments

Comments
 (0)