@@ -487,6 +487,16 @@ namespace {
487487 }
488488 RValue visitFunctionConversionExpr (FunctionConversionExpr *E,
489489 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);
490500 RValue visitActorIsolationErasureExpr (ActorIsolationErasureExpr *E,
491501 SGFContext C);
492502 RValue visitExtractFunctionIsolationExpr (ExtractFunctionIsolationExpr *E,
@@ -1942,9 +1952,159 @@ static ManagedValue convertFunctionRepresentation(SILGenFunction &SGF,
19421952 llvm_unreachable (" bad representation" );
19431953}
19441954
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+
19452106RValue RValueEmitter::visitFunctionConversionExpr (FunctionConversionExpr *e,
1946- SGFContext C)
1947- {
2107+ SGFContext C) {
19482108 CanAnyFunctionType srcType =
19492109 cast<FunctionType>(e->getSubExpr ()->getType ()->getCanonicalType ());
19502110 CanAnyFunctionType destType =
@@ -2041,6 +2201,24 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
20412201 }
20422202 }
20432203
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+
20442222 // Break the conversion into three stages:
20452223 // 1) changing the representation from foreign to native
20462224 // 2) changing the signature within the representation
0 commit comments