@@ -159,27 +159,38 @@ irgen::getAsyncContextLayout(IRGenModule &IGM, CanSILFunctionType originalType,
159159 switch (kind.getSpecialKind ()) {
160160 case FunctionPointer::SpecialKind::TaskFutureWait:
161161 case FunctionPointer::SpecialKind::TaskFutureWaitThrowing: {
162+ // This needs to match the layout of TaskFutureWaitAsyncContext.
162163 // Add storage for the waiting future's result pointer (OpaqueValue *).
163164 auto ty = SILType ();
164165 auto &ti = IGM.getSwiftContextPtrTypeInfo ();
166+ // SwiftError *
167+ valTypes.push_back (ty);
168+ typeInfos.push_back (&ti);
165169 // OpaqueValue *successResultPointer
166170 valTypes.push_back (ty);
167171 typeInfos.push_back (&ti);
168- // AsyncTask *task ;
169- // valTypes.push_back(ty);
170- // typeInfos.push_back(&ti);
172+ // void (*, *) async *asyncResumeEntryPoint ;
173+ valTypes.push_back (ty);
174+ typeInfos.push_back (&ti);
171175 } break ;
172176 case FunctionPointer::SpecialKind::TaskGroupWaitNext: {
177+ // This needs to match the layout of TaskGroupNextAsyncContext.
173178 // Add storage for the waiting future's result pointer (OpaqueValue *).
174179 auto ty = SILType ();
175180 auto &ti = IGM.getSwiftContextPtrTypeInfo ();
176- // OpaqueValue *successResultPointer
181+ // SwiftError * errorResult;
182+ valTypes.push_back (ty);
183+ typeInfos.push_back (&ti);
184+ // OpaqueValue *successResultPointer;
185+ valTypes.push_back (ty);
186+ typeInfos.push_back (&ti);
187+ // void (*, *) async *asyncResumeEntryPoint;
177188 valTypes.push_back (ty);
178189 typeInfos.push_back (&ti);
179190 // TaskGroup *group;
180191 valTypes.push_back (ty);
181192 typeInfos.push_back (&ti);
182- // const Metadata *successType;
193+ // Metata *successType;
183194 valTypes.push_back (ty);
184195 typeInfos.push_back (&ti);
185196 } break ;
@@ -427,6 +438,7 @@ namespace {
427438 bool CanUseSelf = true ;
428439 bool SuppressGenerics;
429440 unsigned AsyncContextIdx;
441+ unsigned AsyncResumeFunctionSwiftSelfIdx = 0 ;
430442
431443 SignatureExpansion (IRGenModule &IGM, CanSILFunctionType fnType,
432444 bool suppressGenerics)
@@ -1722,24 +1734,41 @@ void SignatureExpansion::expandCoroutineContinuationType() {
17221734void SignatureExpansion::expandAsyncReturnType () {
17231735 // Build up the signature of the return continuation function.
17241736 // void (AsyncTask *, ExecutorRef, AsyncContext *, DirectResult0, ...,
1725- // DirectResultN);
1737+ // DirectResultN, Error* );
17261738 ResultIRType = IGM.VoidTy ;
17271739 addAsyncParameters ();
17281740 SmallVector<llvm::Type *, 8 > components;
1741+
1742+ auto addErrorResult = [&]() {
1743+ // Add the error pointer at the end.
1744+ if (FnType->hasErrorResult ()) {
1745+ llvm::Type *errorType =
1746+ IGM.getStorageType (getSILFuncConventions ().getSILType (
1747+ FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1748+ claimSelf ();
1749+ auto selfIdx = ParamIRTypes.size ();
1750+ IGM.addSwiftSelfAttributes (Attrs, selfIdx);
1751+ AsyncResumeFunctionSwiftSelfIdx = selfIdx;
1752+ ParamIRTypes.push_back (errorType);
1753+ }
1754+ };
1755+
17291756 auto resultType = getSILFuncConventions ().getSILResultType (
17301757 IGM.getMaximalTypeExpansionContext ());
17311758 auto &ti = IGM.getTypeInfo (resultType);
17321759 auto &native = ti.nativeReturnValueSchema (IGM);
1733- if (native.requiresIndirect ())
1734- return ;
1735- if (native.empty ())
1760+ if (native.requiresIndirect () || native.empty ()) {
1761+ addErrorResult ();
17361762 return ;
1763+ }
17371764
17381765 // Add the result type components as trailing parameters.
17391766 native.enumerateComponents (
17401767 [&](clang::CharUnits offset, clang::CharUnits end, llvm::Type *type) {
17411768 ParamIRTypes.push_back (type);
17421769 });
1770+
1771+ addErrorResult ();
17431772}
17441773
17451774void SignatureExpansion::expandAsyncEntryType () {
@@ -1834,12 +1863,24 @@ void SignatureExpansion::expandAsyncAwaitType() {
18341863 AsyncContextIdx = 0 ;
18351864 components.push_back (IGM.Int8PtrTy );
18361865
1866+ auto addErrorResult = [&]() {
1867+ if (FnType->hasErrorResult ()) {
1868+ llvm::Type *errorType =
1869+ IGM.getStorageType (getSILFuncConventions ().getSILType (
1870+ FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1871+ auto selfIdx = components.size ();
1872+ AsyncResumeFunctionSwiftSelfIdx = selfIdx;
1873+ components.push_back (errorType);
1874+ }
1875+ };
1876+
18371877 // Direct result type as arguments.
18381878 auto resultType = getSILFuncConventions ().getSILResultType (
18391879 IGM.getMaximalTypeExpansionContext ());
18401880 auto &ti = IGM.getTypeInfo (resultType);
18411881 auto &native = ti.nativeReturnValueSchema (IGM);
18421882 if (native.requiresIndirect () || native.empty ()) {
1883+ addErrorResult ();
18431884 ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
18441885 return ;
18451886 }
@@ -1849,6 +1890,9 @@ void SignatureExpansion::expandAsyncAwaitType() {
18491890 [&](clang::CharUnits offset, clang::CharUnits end, llvm::Type *type) {
18501891 components.push_back (type);
18511892 });
1893+
1894+ addErrorResult ();
1895+
18521896 ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
18531897}
18541898
@@ -1881,6 +1925,7 @@ Signature SignatureExpansion::getSignature() {
18811925 result.ExtraDataKind = ExtraData::kindForMember<AsyncInfo>();
18821926 AsyncInfo info;
18831927 info.AsyncContextIdx = AsyncContextIdx;
1928+ info.AsyncResumeFunctionSwiftSelfIdx = AsyncResumeFunctionSwiftSelfIdx;
18841929 result.ExtraDataStorage .emplace <AsyncInfo>(result.ExtraDataKind , info);
18851930 } else {
18861931 result.ExtraDataKind = ExtraData::kindForMember<void >();
@@ -2451,16 +2496,43 @@ class AsyncCallEmission final : public CallEmission {
24512496 auto resultTys =
24522497 makeArrayRef (suspendResultTy->element_begin () + numAsyncContextParams,
24532498 suspendResultTy->element_end ());
2499+
2500+ auto substCalleeType = getCallee ().getSubstFunctionType ();
2501+ SILFunctionConventions substConv (substCalleeType, IGF.getSILModule ());
2502+ auto hasError = substCalleeType->hasErrorResult ();
2503+ SILType errorType;
2504+ if (hasError)
2505+ errorType =
2506+ substConv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
2507+
24542508 if (resultTys.size () == 1 ) {
24552509 result = Builder.CreateExtractValue (result, numAsyncContextParams);
2510+ if (hasError) {
2511+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2512+ Builder.CreateStore (result, errorAddr);
2513+ return ;
2514+ }
2515+ } else if (resultTys.size () == 2 && hasError) {
2516+ auto tmp = result;
2517+ result = Builder.CreateExtractValue (result, numAsyncContextParams);
2518+ auto errorResult = Builder.CreateExtractValue (tmp, numAsyncContextParams + 1 );
2519+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2520+ Builder.CreateStore (errorResult, errorAddr);
24562521 } else {
2457- auto resultTy = llvm::StructType::get (IGM.getLLVMContext (), resultTys);
2522+ auto directResultTys = hasError ? resultTys.drop_back () : resultTys;
2523+ auto resultTy = llvm::StructType::get (IGM.getLLVMContext (), directResultTys);
24582524 llvm::Value *resultAgg = llvm::UndefValue::get (resultTy);
2459- for (unsigned i = 0 , e = resultTys .size (); i != e; ++i) {
2525+ for (unsigned i = 0 , e = directResultTys .size (); i != e; ++i) {
24602526 llvm::Value *elt =
24612527 Builder.CreateExtractValue (result, numAsyncContextParams + i);
24622528 resultAgg = Builder.CreateInsertValue (resultAgg, elt, i);
24632529 }
2530+ if (hasError) {
2531+ auto errorResult = Builder.CreateExtractValue (
2532+ result, numAsyncContextParams + directResultTys.size ());
2533+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2534+ Builder.CreateStore (errorResult, errorAddr);
2535+ }
24642536 result = resultAgg;
24652537 }
24662538
@@ -2496,17 +2568,7 @@ class AsyncCallEmission final : public CallEmission {
24962568 out = nativeSchema.mapFromNative (IGF.IGM , IGF, nativeExplosion, resultType);
24972569 }
24982570 Address getCalleeErrorSlot (SILType errorType, bool isCalleeAsync) override {
2499- if (isCalleeAsync) {
2500- auto layout = getAsyncContextLayout ();
2501- auto errorLayout = layout.getErrorLayout ();
2502- auto pointerToAddress =
2503- errorLayout.project (IGF, context, /* offsets*/ llvm::None);
2504- auto load = IGF.Builder .CreateLoad (pointerToAddress);
2505- auto address = Address (load, IGF.IGM .getPointerAlignment ());
2506- return address;
2507- } else {
2508- return IGF.getCalleeErrorResultSlot (errorType);
2509- }
2571+ return IGF.getCalleeErrorResultSlot (errorType);
25102572 }
25112573
25122574 FunctionPointer getFunctionPointerForDispatchCall (const FunctionPointer &fn) {
@@ -2530,9 +2592,14 @@ class AsyncCallEmission final : public CallEmission {
25302592 // Setup the suspend point.
25312593 SmallVector<llvm::Value *, 8 > arguments;
25322594 auto signature = fn.getSignature ();
2533- auto asyncContextIndex = signature.getAsyncContextIndex ();
2595+ auto asyncContextIndex =
2596+ signature.getAsyncContextIndex ();
2597+ auto paramAttributeFlags =
2598+ asyncContextIndex |
2599+ (signature.getAsyncResumeFunctionSwiftSelfIndex () << 8 );
2600+ // Index of swiftasync context | ((index of swiftself) << 8).
25342601 arguments.push_back (
2535- IGM.getInt32 (asyncContextIndex )); // Index of swiftasync context.
2602+ IGM.getInt32 (paramAttributeFlags ));
25362603 arguments.push_back (currentResumeFn);
25372604 auto resumeProjFn = IGF.getOrCreateResumePrjFn ();
25382605 arguments.push_back (
@@ -4750,7 +4817,11 @@ void irgen::emitAsyncReturn(
47504817
47514818void irgen::emitAsyncReturn (IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
47524819 SILType funcResultTypeInContext,
4753- CanSILFunctionType fnType, Explosion &result) {
4820+ CanSILFunctionType fnType, Explosion &result,
4821+ Explosion &error) {
4822+ assert ((fnType->hasErrorResult () && !error.empty ()) ||
4823+ (!fnType->hasErrorResult () && error.empty ()));
4824+
47544825 auto &IGM = IGF.IGM ;
47554826
47564827 // Map the explosion to the native result type.
@@ -4766,6 +4837,8 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
47664837 llvm::Type *componentTy) {
47674838 nativeResultsStorage.push_back (llvm::UndefValue::get (componentTy));
47684839 });
4840+ if (!error.empty ())
4841+ nativeResultsStorage.push_back (error.claimNext ());
47694842 nativeResults = nativeResultsStorage;
47704843 } else if (!result.empty ()) {
47714844 assert (!nativeSchema.empty ());
@@ -4775,6 +4848,11 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
47754848 while (!native.empty ()) {
47764849 nativeResultsStorage.push_back (native.claimNext ());
47774850 }
4851+ if (!error.empty ())
4852+ nativeResultsStorage.push_back (error.claimNext ());
4853+ nativeResults = nativeResultsStorage;
4854+ } else if (!error.empty ()) {
4855+ nativeResultsStorage.push_back (error.claimNext ());
47784856 nativeResults = nativeResultsStorage;
47794857 }
47804858 emitAsyncReturn (IGF, asyncLayout, fnType, nativeResults);
0 commit comments