@@ -159,27 +159,38 @@ irgen::getAsyncContextLayout(IRGenModule &IGM, CanSILFunctionType originalType,
159
159
switch (kind.getSpecialKind ()) {
160
160
case FunctionPointer::SpecialKind::TaskFutureWait:
161
161
case FunctionPointer::SpecialKind::TaskFutureWaitThrowing: {
162
+ // This needs to match the layout of TaskFutureWaitAsyncContext.
162
163
// Add storage for the waiting future's result pointer (OpaqueValue *).
163
164
auto ty = SILType ();
164
165
auto &ti = IGM.getSwiftContextPtrTypeInfo ();
166
+ // SwiftError *
167
+ valTypes.push_back (ty);
168
+ typeInfos.push_back (&ti);
165
169
// OpaqueValue *successResultPointer
166
170
valTypes.push_back (ty);
167
171
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);
171
175
} break ;
172
176
case FunctionPointer::SpecialKind::TaskGroupWaitNext: {
177
+ // This needs to match the layout of TaskGroupNextAsyncContext.
173
178
// Add storage for the waiting future's result pointer (OpaqueValue *).
174
179
auto ty = SILType ();
175
180
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;
177
188
valTypes.push_back (ty);
178
189
typeInfos.push_back (&ti);
179
190
// TaskGroup *group;
180
191
valTypes.push_back (ty);
181
192
typeInfos.push_back (&ti);
182
- // const Metadata *successType;
193
+ // Metata *successType;
183
194
valTypes.push_back (ty);
184
195
typeInfos.push_back (&ti);
185
196
} break ;
@@ -427,6 +438,7 @@ namespace {
427
438
bool CanUseSelf = true ;
428
439
bool SuppressGenerics;
429
440
unsigned AsyncContextIdx;
441
+ unsigned AsyncResumeFunctionSwiftSelfIdx = 0 ;
430
442
431
443
SignatureExpansion (IRGenModule &IGM, CanSILFunctionType fnType,
432
444
bool suppressGenerics)
@@ -1722,24 +1734,41 @@ void SignatureExpansion::expandCoroutineContinuationType() {
1722
1734
void SignatureExpansion::expandAsyncReturnType () {
1723
1735
// Build up the signature of the return continuation function.
1724
1736
// void (AsyncTask *, ExecutorRef, AsyncContext *, DirectResult0, ...,
1725
- // DirectResultN);
1737
+ // DirectResultN, Error* );
1726
1738
ResultIRType = IGM.VoidTy ;
1727
1739
addAsyncParameters ();
1728
1740
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
+
1729
1756
auto resultType = getSILFuncConventions ().getSILResultType (
1730
1757
IGM.getMaximalTypeExpansionContext ());
1731
1758
auto &ti = IGM.getTypeInfo (resultType);
1732
1759
auto &native = ti.nativeReturnValueSchema (IGM);
1733
- if (native.requiresIndirect ())
1734
- return ;
1735
- if (native.empty ())
1760
+ if (native.requiresIndirect () || native.empty ()) {
1761
+ addErrorResult ();
1736
1762
return ;
1763
+ }
1737
1764
1738
1765
// Add the result type components as trailing parameters.
1739
1766
native.enumerateComponents (
1740
1767
[&](clang::CharUnits offset, clang::CharUnits end, llvm::Type *type) {
1741
1768
ParamIRTypes.push_back (type);
1742
1769
});
1770
+
1771
+ addErrorResult ();
1743
1772
}
1744
1773
1745
1774
void SignatureExpansion::expandAsyncEntryType () {
@@ -1834,12 +1863,24 @@ void SignatureExpansion::expandAsyncAwaitType() {
1834
1863
AsyncContextIdx = 0 ;
1835
1864
components.push_back (IGM.Int8PtrTy );
1836
1865
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
+
1837
1877
// Direct result type as arguments.
1838
1878
auto resultType = getSILFuncConventions ().getSILResultType (
1839
1879
IGM.getMaximalTypeExpansionContext ());
1840
1880
auto &ti = IGM.getTypeInfo (resultType);
1841
1881
auto &native = ti.nativeReturnValueSchema (IGM);
1842
1882
if (native.requiresIndirect () || native.empty ()) {
1883
+ addErrorResult ();
1843
1884
ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
1844
1885
return ;
1845
1886
}
@@ -1849,6 +1890,9 @@ void SignatureExpansion::expandAsyncAwaitType() {
1849
1890
[&](clang::CharUnits offset, clang::CharUnits end, llvm::Type *type) {
1850
1891
components.push_back (type);
1851
1892
});
1893
+
1894
+ addErrorResult ();
1895
+
1852
1896
ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
1853
1897
}
1854
1898
@@ -1881,6 +1925,7 @@ Signature SignatureExpansion::getSignature() {
1881
1925
result.ExtraDataKind = ExtraData::kindForMember<AsyncInfo>();
1882
1926
AsyncInfo info;
1883
1927
info.AsyncContextIdx = AsyncContextIdx;
1928
+ info.AsyncResumeFunctionSwiftSelfIdx = AsyncResumeFunctionSwiftSelfIdx;
1884
1929
result.ExtraDataStorage .emplace <AsyncInfo>(result.ExtraDataKind , info);
1885
1930
} else {
1886
1931
result.ExtraDataKind = ExtraData::kindForMember<void >();
@@ -2451,16 +2496,43 @@ class AsyncCallEmission final : public CallEmission {
2451
2496
auto resultTys =
2452
2497
makeArrayRef (suspendResultTy->element_begin () + numAsyncContextParams,
2453
2498
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
+
2454
2508
if (resultTys.size () == 1 ) {
2455
2509
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);
2456
2521
} 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);
2458
2524
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) {
2460
2526
llvm::Value *elt =
2461
2527
Builder.CreateExtractValue (result, numAsyncContextParams + i);
2462
2528
resultAgg = Builder.CreateInsertValue (resultAgg, elt, i);
2463
2529
}
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
+ }
2464
2536
result = resultAgg;
2465
2537
}
2466
2538
@@ -2496,17 +2568,7 @@ class AsyncCallEmission final : public CallEmission {
2496
2568
out = nativeSchema.mapFromNative (IGF.IGM , IGF, nativeExplosion, resultType);
2497
2569
}
2498
2570
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);
2510
2572
}
2511
2573
2512
2574
FunctionPointer getFunctionPointerForDispatchCall (const FunctionPointer &fn) {
@@ -2530,9 +2592,14 @@ class AsyncCallEmission final : public CallEmission {
2530
2592
// Setup the suspend point.
2531
2593
SmallVector<llvm::Value *, 8 > arguments;
2532
2594
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).
2534
2601
arguments.push_back (
2535
- IGM.getInt32 (asyncContextIndex )); // Index of swiftasync context.
2602
+ IGM.getInt32 (paramAttributeFlags ));
2536
2603
arguments.push_back (currentResumeFn);
2537
2604
auto resumeProjFn = IGF.getOrCreateResumePrjFn ();
2538
2605
arguments.push_back (
@@ -4750,7 +4817,11 @@ void irgen::emitAsyncReturn(
4750
4817
4751
4818
void irgen::emitAsyncReturn (IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
4752
4819
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
+
4754
4825
auto &IGM = IGF.IGM ;
4755
4826
4756
4827
// Map the explosion to the native result type.
@@ -4766,6 +4837,8 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
4766
4837
llvm::Type *componentTy) {
4767
4838
nativeResultsStorage.push_back (llvm::UndefValue::get (componentTy));
4768
4839
});
4840
+ if (!error.empty ())
4841
+ nativeResultsStorage.push_back (error.claimNext ());
4769
4842
nativeResults = nativeResultsStorage;
4770
4843
} else if (!result.empty ()) {
4771
4844
assert (!nativeSchema.empty ());
@@ -4775,6 +4848,11 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
4775
4848
while (!native.empty ()) {
4776
4849
nativeResultsStorage.push_back (native.claimNext ());
4777
4850
}
4851
+ if (!error.empty ())
4852
+ nativeResultsStorage.push_back (error.claimNext ());
4853
+ nativeResults = nativeResultsStorage;
4854
+ } else if (!error.empty ()) {
4855
+ nativeResultsStorage.push_back (error.claimNext ());
4778
4856
nativeResults = nativeResultsStorage;
4779
4857
}
4780
4858
emitAsyncReturn (IGF, asyncLayout, fnType, nativeResults);
0 commit comments