@@ -1867,12 +1867,15 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
1867
1867
FunctionPointer functionPointer, llvm::Value *thickContext,
1868
1868
std::pair<bool , bool > values, Size initialContextSize) {
1869
1869
assert (values.first || values.second );
1870
+ assert (functionPointer.getKind () ==
1871
+ FunctionPointer::KindTy::AsyncFunctionPointer);
1870
1872
bool emitFunction = values.first ;
1871
1873
bool emitSize = values.second ;
1872
1874
// TODO: This calculation should be extracted out into standalone functions
1873
1875
// emitted on-demand per-module to improve codesize.
1874
1876
switch (representation) {
1875
1877
case SILFunctionTypeRepresentation::Thick: {
1878
+ assert (!functionPointer.useStaticContextSize ());
1876
1879
// If the called function is thick, the size of the called function's
1877
1880
// async context is not statically knowable.
1878
1881
//
@@ -1941,16 +1944,25 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
1941
1944
SmallVector<std::pair<llvm::BasicBlock *, llvm::Value *>, 2 > sizePhiValues;
1942
1945
{ // thin
1943
1946
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 );
1944
1953
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 ());
1946
1958
auto *fnPtr = IGF.Builder .CreateBitCast (uncastFnPtr, IGF.IGM .Int8PtrTy );
1959
+ if (auto authInfo = functionPointer.getAuthInfo ()) {
1960
+ fnPtr = emitPointerAuthSign (IGF, fnPtr, authInfo);
1961
+ }
1947
1962
fnPhiValues.push_back ({thinBlock, fnPtr});
1948
1963
}
1949
1964
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 );
1954
1966
auto *size =
1955
1967
IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
1956
1968
sizePhiValues.push_back ({thinBlock, size});
@@ -2026,20 +2038,34 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
2026
2038
case SILFunctionTypeRepresentation::WitnessMethod:
2027
2039
case SILFunctionTypeRepresentation::Closure:
2028
2040
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 );
2029
2047
llvm::Value *fn = nullptr ;
2030
2048
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
+ }
2032
2060
}
2033
2061
llvm::Value *size = nullptr ;
2034
2062
if (emitSize) {
2035
2063
if (functionPointer.useStaticContextSize ()) {
2036
2064
size = llvm::ConstantInt::get (IGF.IGM .Int32Ty ,
2037
2065
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 );
2043
2069
size = IGF.Builder .CreateLoad (sizePtr, IGF.IGM .getPointerAlignment ());
2044
2070
}
2045
2071
}
@@ -2336,7 +2362,8 @@ class AsyncCallEmission final : public CallEmission {
2336
2362
}
2337
2363
FunctionPointer getCalleeFunctionPointer () override {
2338
2364
return FunctionPointer (
2339
- FunctionPointer::KindTy::Function, calleeFunction, PointerAuthInfo (),
2365
+ FunctionPointer::KindTy::Function, calleeFunction,
2366
+ CurCallee.getFunctionPointer ().getAuthInfo (),
2340
2367
IGF.IGM .getSignature (getCallee ().getSubstFunctionType ()));
2341
2368
}
2342
2369
SILType getParameterType (unsigned index) override {
@@ -2374,8 +2401,7 @@ class AsyncCallEmission final : public CallEmission {
2374
2401
llvm::Intrinsic::coro_async_resume, {});
2375
2402
auto fnVal = currentResumeFn;
2376
2403
// 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 ) {
2379
2405
Address fieldAddr =
2380
2406
fieldLayout.project (IGF, this ->context , /* offsets*/ llvm::None);
2381
2407
auto authInfo = PointerAuthInfo::emit (
@@ -2454,6 +2480,9 @@ class AsyncCallEmission final : public CallEmission {
2454
2480
Builder.CreateBitOrPointerCast (dispatchFn, IGM.Int8PtrTy ));
2455
2481
arguments.push_back (
2456
2482
Builder.CreateBitOrPointerCast (fn.getRawPointer (), IGM.Int8PtrTy ));
2483
+ if (auto authInfo = fn.getAuthInfo ()) {
2484
+ arguments.push_back (fn.getAuthInfo ().getDiscriminator ());
2485
+ }
2457
2486
for (auto arg: args)
2458
2487
arguments.push_back (arg);
2459
2488
return IGF.emitSuspendAsyncCall (arguments);
@@ -3640,14 +3669,34 @@ llvm::Value *irgen::emitTaskCreate(
3640
3669
auto layout = getAsyncContextLayout (
3641
3670
IGF.IGM , taskFunctionCanSILType, taskFunctionCanSILType, subs);
3642
3671
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
+
3643
3687
// Call the function.
3644
3688
llvm::CallInst *result;
3645
3689
llvm::Value *theSize, *theFunction;
3690
+ auto taskFunctionPointer = FunctionPointer::forExplosionValue (
3691
+ IGF, taskFunction, taskFunctionCanSILType);
3646
3692
std::tie (theFunction, theSize) =
3647
3693
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
+ }
3651
3700
theFunction = IGF.Builder .CreateBitOrPointerCast (
3652
3701
theFunction, IGF.IGM .TaskContinuationFunctionPtrTy );
3653
3702
theSize = IGF.Builder .CreateZExtOrBitCast (theSize, IGF.IGM .SizeTy );
@@ -4519,18 +4568,25 @@ llvm::Value *FunctionPointer::getPointer(IRGenFunction &IGF) const {
4519
4568
return Value;
4520
4569
case KindTy::Value::AsyncFunctionPointer: {
4521
4570
if (!isFunctionPointerWithoutContext) {
4571
+ auto *fnPtr = Value;
4572
+ if (auto authInfo = AuthInfo) {
4573
+ fnPtr = emitPointerAuthAuth (IGF, fnPtr, authInfo);
4574
+ }
4522
4575
auto *descriptorPtr =
4523
- IGF.Builder .CreateBitCast (Value , IGF.IGM .AsyncFunctionPointerPtrTy );
4576
+ IGF.Builder .CreateBitCast (fnPtr , IGF.IGM .AsyncFunctionPointerPtrTy );
4524
4577
auto *addrPtr = IGF.Builder .CreateStructGEP (descriptorPtr, 0 );
4525
- return IGF.emitLoadOfRelativePointer (
4578
+ auto *result = IGF.emitLoadOfRelativePointer (
4526
4579
Address (addrPtr, IGF.IGM .getPointerAlignment ()), /* isFar*/ false ,
4527
4580
/* expectedType*/ getFunctionType ()->getPointerTo ());
4581
+ if (auto authInfo = AuthInfo) {
4582
+ result = emitPointerAuthSign (IGF, result, authInfo);
4583
+ }
4584
+ return result;
4528
4585
} else {
4529
4586
return IGF.Builder .CreateBitOrPointerCast (
4530
4587
Value, getFunctionType ()->getPointerTo ());
4531
4588
}
4532
4589
}
4533
-
4534
4590
}
4535
4591
}
4536
4592
@@ -4577,8 +4633,7 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
4577
4633
.loadAsCopy (IGF, returnToCallerAddr, fn);
4578
4634
llvm::Value *fnVal = fn.claimNext ();
4579
4635
4580
- // TODO: use distinct schema
4581
- if (auto schema = IGF.IGM .getOptions ().PointerAuth .AsyncContextParent ) {
4636
+ if (auto schema = IGF.IGM .getOptions ().PointerAuth .AsyncContextResume ) {
4582
4637
Address fieldAddr =
4583
4638
returnToCallerLayout.project (IGF, contextAddr, /* offsets*/ llvm::None);
4584
4639
auto authInfo = PointerAuthInfo::emit (IGF, schema, fieldAddr.getAddress (),
0 commit comments