@@ -487,6 +487,16 @@ namespace {
487
487
}
488
488
RValue visitFunctionConversionExpr (FunctionConversionExpr *E,
489
489
SGFContext C);
490
+
491
+ // / Helper method for handling function conversion expr to
492
+ // / @execution(caller). Returns an empty RValue on failure.
493
+ RValue emitFunctionCvtToExecutionCaller (FunctionConversionExpr *E,
494
+ SGFContext C);
495
+ // / Helper method for handling function conversion expr to a global actor
496
+ // / from an @execution(caller) function.
497
+ RValue
498
+ emitFunctionCvtFromExecutionCallerToGlobalActor (FunctionConversionExpr *E,
499
+ SGFContext C);
490
500
RValue visitActorIsolationErasureExpr (ActorIsolationErasureExpr *E,
491
501
SGFContext C);
492
502
RValue visitExtractFunctionIsolationExpr (ExtractFunctionIsolationExpr *E,
@@ -1942,9 +1952,159 @@ static ManagedValue convertFunctionRepresentation(SILGenFunction &SGF,
1942
1952
llvm_unreachable (" bad representation" );
1943
1953
}
1944
1954
1955
+ RValue
1956
+ RValueEmitter::emitFunctionCvtToExecutionCaller (FunctionConversionExpr *e,
1957
+ SGFContext C) {
1958
+ CanAnyFunctionType destType =
1959
+ cast<FunctionType>(e->getType ()->getCanonicalType ());
1960
+ assert (destType->getIsolation ().isNonIsolatedCaller () &&
1961
+ " Should only call this if destType is non isolated caller" );
1962
+
1963
+ auto *subExpr = e->getSubExpr ();
1964
+ CanAnyFunctionType subExprType =
1965
+ cast<FunctionType>(subExpr->getType ()->getCanonicalType ());
1966
+
1967
+ // We are pattern matching the following two patterns:
1968
+ //
1969
+ // Swift 6:
1970
+ //
1971
+ // (fn_cvt_expr type="@execution(caller) () async -> ()"
1972
+ // (fn_cvt_expr type="@execution(caller) @Sendable () async -> ()"
1973
+ // (declref_expr type="() async -> ()"
1974
+ //
1975
+ // Swift 5:
1976
+ //
1977
+ // (fn_cvt_expr type="@execution(caller) () async -> ()"
1978
+ // (declref_expr type="() async -> ()"
1979
+ //
1980
+ // The @Sendable in Swift 6 mode is due to us not representing
1981
+ // @execution(caller) or @Sendable in the constraint evaluator.
1982
+ //
1983
+ // The reason why we need to evaluate this especially is that otherwise we
1984
+ // generate multiple
1985
+
1986
+ bool needsSendableConversion = false ;
1987
+ if (auto *subCvt = dyn_cast<FunctionConversionExpr>(subExpr)) {
1988
+ auto *subSubExpr = subCvt->getSubExpr ();
1989
+ CanAnyFunctionType subSubExprType =
1990
+ cast<FunctionType>(subSubExpr->getType ()->getCanonicalType ());
1991
+
1992
+ if (subExprType->hasExtInfo () && subExprType->getExtInfo ().isSendable () &&
1993
+ subSubExprType->hasExtInfo () &&
1994
+ !subExprType->getExtInfo ().isSendable () &&
1995
+ subExprType->withSendable (true ) == subSubExprType) {
1996
+ subExpr = subSubExpr;
1997
+
1998
+ // We changed our subExpr... so recompute our srcType.
1999
+ subExprType = cast<FunctionType>(subExpr->getType ()->getCanonicalType ());
2000
+ needsSendableConversion = true ;
2001
+ }
2002
+ }
2003
+
2004
+ // Check if the only difference in between our destType and srcType is our
2005
+ // isolation.
2006
+ if (!subExprType->hasExtInfo () || !destType->hasExtInfo () ||
2007
+ destType->withIsolation (subExprType->getIsolation ()) != subExprType) {
2008
+ return RValue ();
2009
+ }
2010
+
2011
+ // Ok, we know that our underlying types are the same. Lets try to emit.
2012
+ auto *declRef = dyn_cast<DeclRefExpr>(subExpr);
2013
+ if (!declRef)
2014
+ return RValue ();
2015
+
2016
+ auto *decl = dyn_cast<FuncDecl>(declRef->getDecl ());
2017
+ if (!decl || !getActorIsolation (decl).isCallerIsolationInheriting ())
2018
+ return RValue ();
2019
+
2020
+ // Ok, we found our target.
2021
+ SILDeclRef silDeclRef (decl);
2022
+ assert (silDeclRef.getParameterListCount () == 1 );
2023
+ auto substType = cast<AnyFunctionType>(destType);
2024
+ auto typeContext = SGF.getFunctionTypeInfo (substType);
2025
+ ManagedValue result = SGF.emitClosureValue (
2026
+ e, silDeclRef, typeContext, declRef->getDeclRef ().getSubstitutions ());
2027
+ if (needsSendableConversion) {
2028
+ auto funcType = cast<SILFunctionType>(result.getType ().getASTType ());
2029
+ result = SGF.B .createConvertFunction (
2030
+ e, result,
2031
+ SILType::getPrimitiveObjectType (funcType->withSendable (true )));
2032
+ }
2033
+ return RValue (SGF, e, destType, result);
2034
+ }
2035
+
2036
+ RValue RValueEmitter::emitFunctionCvtFromExecutionCallerToGlobalActor (
2037
+ FunctionConversionExpr *e, SGFContext C) {
2038
+ // We are pattern matching a conversion sequence like the following:
2039
+ //
2040
+ // (fn_cvt_expr implicit type="@GlobalActor @Sendable () async -> ()
2041
+ // (fn_cvt_expr implicit type="@execution(caller) @Sendable () async -> ()"
2042
+ // (declref_expr type="() async -> ()"
2043
+ //
2044
+ // Where the declref referred to by the declref_expr has execution(caller)
2045
+ // attached to it but lacks it in its interface type since we do not put
2046
+ // execution(attr) in interface types when we run the constraint solver but
2047
+ // fix it up later.
2048
+ //
2049
+ // What we want to emit first a direct reference to the caller as an
2050
+ // @execution(caller) function, then we convert it to @execution(caller)
2051
+ // @Sendable. Finally, we thunk @execution(caller) to @GlobalActor. The
2052
+ // thunking is important so that we can ensure that @execution(caller) runs on
2053
+ // that specific @GlobalActor.
2054
+
2055
+ CanAnyFunctionType destType =
2056
+ cast<FunctionType>(e->getType ()->getCanonicalType ());
2057
+ assert (destType->getIsolation ().isGlobalActor () &&
2058
+ " Should only call this if destType is a global actor" );
2059
+
2060
+ auto *subCvt = dyn_cast<FunctionConversionExpr>(e->getSubExpr ());
2061
+ if (!subCvt)
2062
+ return RValue ();
2063
+
2064
+ CanAnyFunctionType subCvtType =
2065
+ cast<FunctionType>(subCvt->getType ()->getCanonicalType ());
2066
+
2067
+ // Src type should be isNonIsolatedCaller and they should only differ in
2068
+ // isolation.
2069
+ if (!subCvtType->getIsolation ().isNonIsolatedCaller () ||
2070
+ subCvtType->withIsolation (destType->getIsolation ()) != destType)
2071
+ return RValue ();
2072
+
2073
+ // Grab our decl ref/its decl and make sure that our decl is actually caller
2074
+ // isolation inheriting (ignoring what it's interface type is).
2075
+ auto *declRef = dyn_cast<DeclRefExpr>(subCvt->getSubExpr ());
2076
+ if (!declRef)
2077
+ return RValue ();
2078
+ auto *decl = dyn_cast<FuncDecl>(declRef->getDecl ());
2079
+ if (!decl || !getActorIsolation (decl).isCallerIsolationInheriting ())
2080
+ return RValue ();
2081
+
2082
+ // Make sure that subCvt/declRefType only differ by isolation and sendability.
2083
+ CanAnyFunctionType declRefType =
2084
+ cast<FunctionType>(declRef->getType ()->getCanonicalType ());
2085
+ assert (!declRefType->getIsolation ().isNonIsolatedCaller () &&
2086
+ " This should not be represented in interface types" );
2087
+ if (declRefType->isSendable () || !subCvtType->isSendable ())
2088
+ return RValue ();
2089
+
2090
+ // Ok, we found our target.
2091
+ SILDeclRef silDeclRef (decl);
2092
+ assert (silDeclRef.getParameterListCount () == 1 );
2093
+ auto substType = cast<AnyFunctionType>(destType);
2094
+ auto typeContext = SGF.getFunctionTypeInfo (substType);
2095
+ ManagedValue result = SGF.emitClosureValue (
2096
+ e, silDeclRef, typeContext, declRef->getDeclRef ().getSubstitutions ());
2097
+ if (!result.getType ().isSendable (&SGF.F )) {
2098
+ auto funcType = cast<SILFunctionType>(result.getType ().getASTType ());
2099
+ result = SGF.B .createConvertFunction (
2100
+ e, result,
2101
+ SILType::getPrimitiveObjectType (funcType->withSendable (true )));
2102
+ }
2103
+ return RValue (SGF, e, destType, result);
2104
+ }
2105
+
1945
2106
RValue RValueEmitter::visitFunctionConversionExpr (FunctionConversionExpr *e,
1946
- SGFContext C)
1947
- {
2107
+ SGFContext C) {
1948
2108
CanAnyFunctionType srcType =
1949
2109
cast<FunctionType>(e->getSubExpr ()->getType ()->getCanonicalType ());
1950
2110
CanAnyFunctionType destType =
@@ -2041,6 +2201,24 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
2041
2201
}
2042
2202
}
2043
2203
2204
+ // Check if we are converting a function to an @execution(caller) from a
2205
+ // declref that is also @execution(caller). In such a case, this was a case
2206
+ // that was put in by Sema. We do not need a thunk, but just need to recognize
2207
+ // this case and elide the conversion. The reason why we need to do this is
2208
+ // that otherwise, we put in extra thunks that convert @execution(caller) to
2209
+ // @execution(concurrent) back to @execution(caller). This is done b/c we do
2210
+ // not represent @execution(caller) in interface types, so the actual decl ref
2211
+ // will be viewed as @async () -> ().
2212
+ if (destType->getIsolation ().isNonIsolatedCaller ()) {
2213
+ if (RValue rv = emitFunctionCvtToExecutionCaller (e, C))
2214
+ return rv;
2215
+ }
2216
+
2217
+ if (destType->getIsolation ().isGlobalActor ()) {
2218
+ if (RValue rv = emitFunctionCvtFromExecutionCallerToGlobalActor (e, C))
2219
+ return rv;
2220
+ }
2221
+
2044
2222
// Break the conversion into three stages:
2045
2223
// 1) changing the representation from foreign to native
2046
2224
// 2) changing the signature within the representation
0 commit comments