@@ -1867,12 +1867,15 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
18671867 FunctionPointer functionPointer, llvm::Value *thickContext,
18681868 std::pair<bool , bool > values, Size initialContextSize) {
18691869 assert (values.first || values.second );
1870+ assert (functionPointer.getKind () ==
1871+ FunctionPointer::KindTy::AsyncFunctionPointer);
18701872 bool emitFunction = values.first ;
18711873 bool emitSize = values.second ;
18721874 // TODO: This calculation should be extracted out into standalone functions
18731875 // emitted on-demand per-module to improve codesize.
18741876 switch (representation) {
18751877 case SILFunctionTypeRepresentation::Thick: {
1878+ assert (!functionPointer.useStaticContextSize ());
18761879 // If the called function is thick, the size of the called function's
18771880 // async context is not statically knowable.
18781881 //
@@ -1941,16 +1944,25 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
19411944 SmallVector<std::pair<llvm::BasicBlock *, llvm::Value *>, 2 > sizePhiValues;
19421945 { // thin
19431946 IGF.Builder .emitBlock (thinBlock);
1947+ auto *ptr = functionPointer.getRawPointer ();
1948+ if (auto authInfo = functionPointer.getAuthInfo ()) {
1949+ ptr = emitPointerAuthAuth (IGF, ptr, authInfo);
1950+ }
1951+ auto *afpPtr =
1952+ IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
19441953 if (emitFunction) {
1945- auto *uncastFnPtr = functionPointer.getPointer (IGF);
1954+ llvm::Value *addrPtr = IGF.Builder .CreateStructGEP (afpPtr, 0 );
1955+ auto *uncastFnPtr = IGF.emitLoadOfRelativePointer (
1956+ Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
1957+ /* expectedType*/ functionPointer.getFunctionType ()->getPointerTo ());
19461958 auto *fnPtr = IGF.Builder .CreateBitCast (uncastFnPtr, IGF.IGM .Int8PtrTy );
1959+ if (auto authInfo = functionPointer.getAuthInfo ()) {
1960+ fnPtr = emitPointerAuthSign (IGF, fnPtr, authInfo);
1961+ }
19471962 fnPhiValues.push_back ({thinBlock, fnPtr});
19481963 }
19491964 if (emitSize) {
1950- auto *ptr = functionPointer.getRawPointer ();
1951- auto *descriptorPtr =
1952- IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
1953- auto *sizePtr = IGF.Builder .CreateStructGEP (descriptorPtr, 1 );
1965+ auto *sizePtr = IGF.Builder .CreateStructGEP (afpPtr, 1 );
19541966 auto *size =
19551967 IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
19561968 sizePhiValues.push_back ({thinBlock, size});
@@ -2026,20 +2038,34 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
20262038 case SILFunctionTypeRepresentation::WitnessMethod:
20272039 case SILFunctionTypeRepresentation::Closure:
20282040 case SILFunctionTypeRepresentation::Block: {
2041+ auto *ptr = functionPointer.getRawPointer ();
2042+ if (auto authInfo = functionPointer.getAuthInfo ()) {
2043+ ptr = emitPointerAuthAuth (IGF, ptr, authInfo);
2044+ }
2045+ auto *afpPtr =
2046+ IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
20292047 llvm::Value *fn = nullptr ;
20302048 if (emitFunction) {
2031- fn = functionPointer.getPointer (IGF);
2049+ if (functionPointer.useStaticContextSize ()) {
2050+ fn = functionPointer.getRawPointer ();
2051+ } else {
2052+ llvm::Value *addrPtr = IGF.Builder .CreateStructGEP (afpPtr, 0 );
2053+ fn = IGF.emitLoadOfRelativePointer (
2054+ Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
2055+ /* expectedType*/ functionPointer.getFunctionType ()->getPointerTo ());
2056+ }
2057+ if (auto authInfo = functionPointer.getAuthInfo ()) {
2058+ fn = emitPointerAuthSign (IGF, fn, authInfo);
2059+ }
20322060 }
20332061 llvm::Value *size = nullptr ;
20342062 if (emitSize) {
20352063 if (functionPointer.useStaticContextSize ()) {
20362064 size = llvm::ConstantInt::get (IGF.IGM .Int32Ty ,
20372065 initialContextSize.getValue ());
2038- } else {
2039- auto *ptr = functionPointer.getRawPointer ();
2040- auto *descriptorPtr =
2041- IGF.Builder .CreateBitCast (ptr, IGF.IGM .AsyncFunctionPointerPtrTy );
2042- auto *sizePtr = IGF.Builder .CreateStructGEP (descriptorPtr, 1 );
2066+ } else {
2067+ assert (!functionPointer.useStaticContextSize ());
2068+ auto *sizePtr = IGF.Builder .CreateStructGEP (afpPtr, 1 );
20432069 size = IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
20442070 }
20452071 }
@@ -2336,7 +2362,8 @@ class AsyncCallEmission final : public CallEmission {
23362362 }
23372363 FunctionPointer getCalleeFunctionPointer () override {
23382364 return FunctionPointer (
2339- FunctionPointer::KindTy::Function, calleeFunction, PointerAuthInfo (),
2365+ FunctionPointer::KindTy::Function, calleeFunction,
2366+ CurCallee.getFunctionPointer ().getAuthInfo (),
23402367 IGF.IGM .getSignature (getCallee ().getSubstFunctionType ()));
23412368 }
23422369 SILType getParameterType (unsigned index) override {
@@ -2374,8 +2401,7 @@ class AsyncCallEmission final : public CallEmission {
23742401 llvm::Intrinsic::coro_async_resume, {});
23752402 auto fnVal = currentResumeFn;
23762403 // Sign the pointer.
2377- // TODO: use a distinct schema.
2378- if (auto schema = IGF.IGM .getOptions ().PointerAuth .AsyncContextParent ) {
2404+ if (auto schema = IGF.IGM .getOptions ().PointerAuth .AsyncContextResume ) {
23792405 Address fieldAddr =
23802406 fieldLayout.project (IGF, this ->context , /* offsets*/ llvm::None);
23812407 auto authInfo = PointerAuthInfo::emit (
@@ -2454,6 +2480,9 @@ class AsyncCallEmission final : public CallEmission {
24542480 Builder.CreateBitOrPointerCast (dispatchFn, IGM.Int8PtrTy ));
24552481 arguments.push_back (
24562482 Builder.CreateBitOrPointerCast (fn.getRawPointer (), IGM.Int8PtrTy ));
2483+ if (auto authInfo = fn.getAuthInfo ()) {
2484+ arguments.push_back (fn.getAuthInfo ().getDiscriminator ());
2485+ }
24572486 for (auto arg: args)
24582487 arguments.push_back (arg);
24592488 return IGF.emitSuspendAsyncCall (arguments);
@@ -3640,14 +3669,34 @@ llvm::Value *irgen::emitTaskCreate(
36403669 auto layout = getAsyncContextLayout (
36413670 IGF.IGM , taskFunctionCanSILType, taskFunctionCanSILType, subs);
36423671
3672+ CanSILFunctionType taskContinuationFunctionTy = [&]() {
3673+ ASTContext &ctx = IGF.IGM .IRGen .SIL .getASTContext ();
3674+ auto extInfo =
3675+ ASTExtInfoBuilder ()
3676+ .withRepresentation (FunctionTypeRepresentation::CFunctionPointer)
3677+ .build ();
3678+ // FIXME: Use the appropriate signature for TaskContinuationFunction:
3679+ //
3680+ // using TaskContinuationFunction =
3681+ // SWIFT_CC(swift)
3682+ // void (AsyncTask *, ExecutorRef, AsyncContext *);
3683+ auto ty = FunctionType::get ({}, ctx.TheEmptyTupleType , extInfo);
3684+ return IGF.IGM .getLoweredType (ty).castTo <SILFunctionType>();
3685+ }();
3686+
36433687 // Call the function.
36443688 llvm::CallInst *result;
36453689 llvm::Value *theSize, *theFunction;
3690+ auto taskFunctionPointer = FunctionPointer::forExplosionValue (
3691+ IGF, taskFunction, taskFunctionCanSILType);
36463692 std::tie (theFunction, theSize) =
36473693 getAsyncFunctionAndSize (IGF, SILFunctionTypeRepresentation::Thick,
3648- FunctionPointer::forExplosionValue (
3649- IGF, taskFunction, taskFunctionCanSILType),
3650- localContextInfo);
3694+ taskFunctionPointer, localContextInfo);
3695+ if (auto authInfo = PointerAuthInfo::forFunctionPointer (
3696+ IGF.IGM , taskContinuationFunctionTy)) {
3697+ theFunction = emitPointerAuthResign (
3698+ IGF, theFunction, taskFunctionPointer.getAuthInfo (), authInfo);
3699+ }
36513700 theFunction = IGF.Builder .CreateBitOrPointerCast (
36523701 theFunction, IGF.IGM .TaskContinuationFunctionPtrTy );
36533702 theSize = IGF.Builder .CreateZExtOrBitCast (theSize, IGF.IGM .SizeTy );
@@ -4519,18 +4568,25 @@ llvm::Value *FunctionPointer::getPointer(IRGenFunction &IGF) const {
45194568 return Value;
45204569 case KindTy::Value::AsyncFunctionPointer: {
45214570 if (!isFunctionPointerWithoutContext) {
4571+ auto *fnPtr = Value;
4572+ if (auto authInfo = AuthInfo) {
4573+ fnPtr = emitPointerAuthAuth (IGF, fnPtr, authInfo);
4574+ }
45224575 auto *descriptorPtr =
4523- IGF.Builder .CreateBitCast (Value , IGF.IGM .AsyncFunctionPointerPtrTy );
4576+ IGF.Builder .CreateBitCast (fnPtr , IGF.IGM .AsyncFunctionPointerPtrTy );
45244577 auto *addrPtr = IGF.Builder .CreateStructGEP (descriptorPtr, 0 );
4525- return IGF.emitLoadOfRelativePointer (
4578+ auto *result = IGF.emitLoadOfRelativePointer (
45264579 Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
45274580 /* expectedType*/ getFunctionType ()->getPointerTo ());
4581+ if (auto authInfo = AuthInfo) {
4582+ result = emitPointerAuthSign (IGF, result, authInfo);
4583+ }
4584+ return result;
45284585 } else {
45294586 return IGF.Builder .CreateBitOrPointerCast (
45304587 Value, getFunctionType ()->getPointerTo ());
45314588 }
45324589 }
4533-
45344590 }
45354591}
45364592
@@ -4577,8 +4633,7 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
45774633 .loadAsCopy (IGF, returnToCallerAddr, fn);
45784634 llvm::Value *fnVal = fn.claimNext ();
45794635
4580- // TODO: use distinct schema
4581- if (auto schema = IGF.IGM .getOptions ().PointerAuth .AsyncContextParent ) {
4636+ if (auto schema = IGF.IGM .getOptions ().PointerAuth .AsyncContextResume ) {
45824637 Address fieldAddr =
45834638 returnToCallerLayout.project (IGF, contextAddr, /* offsets*/ llvm::None);
45844639 auto authInfo = PointerAuthInfo::emit (IGF, schema, fieldAddr.getAddress (),
0 commit comments