@@ -2114,10 +2114,40 @@ void SignatureExpansion::expandAsyncReturnType() {
2114
2114
}
2115
2115
};
2116
2116
2117
- auto resultType = getSILFuncConventions ().getSILResultType (
2118
- IGM.getMaximalTypeExpansionContext ());
2117
+ auto fnConv = getSILFuncConventions ();
2118
+
2119
+ auto resultType =
2120
+ fnConv.getSILResultType (IGM.getMaximalTypeExpansionContext ());
2119
2121
auto &ti = IGM.getTypeInfo (resultType);
2120
2122
auto &native = ti.nativeReturnValueSchema (IGM);
2123
+
2124
+ if (!fnConv.hasIndirectSILResults () && !fnConv.hasIndirectSILErrorResults () &&
2125
+ !native.requiresIndirect () && fnConv.funcTy ->hasErrorResult () &&
2126
+ fnConv.isTypedError ()) {
2127
+ auto errorType = getSILFuncConventions ().getSILErrorType (
2128
+ IGM.getMaximalTypeExpansionContext ());
2129
+ auto &errorTi = IGM.getTypeInfo (errorType);
2130
+ auto &nativeError = errorTi.nativeReturnValueSchema (IGM);
2131
+ if (!nativeError.shouldReturnTypedErrorIndirectly ()) {
2132
+ auto combined = combineResultAndTypedErrorType (IGM, native, nativeError);
2133
+
2134
+ if (combined.combinedTy ->isVoidTy ()) {
2135
+ addErrorResult ();
2136
+ return ;
2137
+ }
2138
+
2139
+ if (auto *structTy = dyn_cast<llvm::StructType>(combined.combinedTy )) {
2140
+ for (auto *elem : structTy->elements ()) {
2141
+ ParamIRTypes.push_back (elem);
2142
+ }
2143
+ } else {
2144
+ ParamIRTypes.push_back (combined.combinedTy );
2145
+ }
2146
+ }
2147
+ addErrorResult ();
2148
+ return ;
2149
+ }
2150
+
2121
2151
if (native.requiresIndirect () || native.empty ()) {
2122
2152
addErrorResult ();
2123
2153
return ;
@@ -2135,11 +2165,23 @@ void SignatureExpansion::expandAsyncReturnType() {
2135
2165
void SignatureExpansion::addIndirectThrowingResult () {
2136
2166
if (getSILFuncConventions ().funcTy ->hasErrorResult () &&
2137
2167
getSILFuncConventions ().isTypedError ()) {
2138
- auto resultType = getSILFuncConventions ().getSILErrorType (
2139
- IGM.getMaximalTypeExpansionContext ());
2140
- const TypeInfo &resultTI = IGM.getTypeInfo (resultType);
2141
- auto storageTy = resultTI.getStorageType ();
2142
- ParamIRTypes.push_back (storageTy->getPointerTo ());
2168
+ auto resultType = getSILFuncConventions ().getSILResultType (
2169
+ IGM.getMaximalTypeExpansionContext ());
2170
+ auto &ti = IGM.getTypeInfo (resultType);
2171
+ auto &native = ti.nativeReturnValueSchema (IGM);
2172
+
2173
+ auto errorType = getSILFuncConventions ().getSILErrorType (
2174
+ IGM.getMaximalTypeExpansionContext ());
2175
+ const TypeInfo &errorTI = IGM.getTypeInfo (errorType);
2176
+ auto &nativeError = errorTI.nativeReturnValueSchema (IGM);
2177
+
2178
+ if (getSILFuncConventions ().hasIndirectSILResults () ||
2179
+ getSILFuncConventions ().hasIndirectSILErrorResults () ||
2180
+ native.requiresIndirect () ||
2181
+ nativeError.shouldReturnTypedErrorIndirectly ()) {
2182
+ auto errorStorageTy = errorTI.getStorageType ();
2183
+ ParamIRTypes.push_back (errorStorageTy->getPointerTo ());
2184
+ }
2143
2185
}
2144
2186
2145
2187
}
@@ -2265,6 +2307,35 @@ void SignatureExpansion::expandAsyncAwaitType() {
2265
2307
IGM.getMaximalTypeExpansionContext ());
2266
2308
auto &ti = IGM.getTypeInfo (resultType);
2267
2309
auto &native = ti.nativeReturnValueSchema (IGM);
2310
+
2311
+ if (!getSILFuncConventions ().hasIndirectSILResults () &&
2312
+ !getSILFuncConventions ().hasIndirectSILErrorResults () &&
2313
+ !native.requiresIndirect () && getSILFuncConventions ().isTypedError ()) {
2314
+ auto errorType = getSILFuncConventions ().getSILErrorType (
2315
+ IGM.getMaximalTypeExpansionContext ());
2316
+ auto &errorTi = IGM.getTypeInfo (errorType);
2317
+ auto &nativeError = errorTi.nativeReturnValueSchema (IGM);
2318
+ if (!nativeError.shouldReturnTypedErrorIndirectly ()) {
2319
+ auto combined = combineResultAndTypedErrorType (IGM, native, nativeError);
2320
+
2321
+ if (combined.combinedTy ->isVoidTy ()) {
2322
+ addErrorResult ();
2323
+ return ;
2324
+ }
2325
+
2326
+ if (auto *structTy = dyn_cast<llvm::StructType>(combined.combinedTy )) {
2327
+ for (auto *elem : structTy->elements ()) {
2328
+ components.push_back (elem);
2329
+ }
2330
+ } else {
2331
+ components.push_back (combined.combinedTy );
2332
+ }
2333
+ addErrorResult ();
2334
+ ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
2335
+ return ;
2336
+ }
2337
+ }
2338
+
2268
2339
if (native.requiresIndirect () || native.empty ()) {
2269
2340
addErrorResult ();
2270
2341
ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
@@ -2278,7 +2349,6 @@ void SignatureExpansion::expandAsyncAwaitType() {
2278
2349
});
2279
2350
2280
2351
addErrorResult ();
2281
-
2282
2352
ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
2283
2353
}
2284
2354
@@ -2950,9 +3020,22 @@ class AsyncCallEmission final : public CallEmission {
2950
3020
setIndirectTypedErrorResultSlotArgsIndex (--LastArgWritten);
2951
3021
Args[LastArgWritten] = nullptr ;
2952
3022
} else {
2953
- auto buf = IGF.getCalleeTypedErrorResultSlot (
2954
- fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()));
2955
- Args[--LastArgWritten] = buf.getAddress ();
3023
+ auto silResultTy =
3024
+ fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
3025
+ auto silErrorTy =
3026
+ fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ());
3027
+
3028
+ auto &nativeSchema =
3029
+ IGF.IGM .getTypeInfo (silResultTy).nativeReturnValueSchema (IGF.IGM );
3030
+ auto &errorSchema =
3031
+ IGF.IGM .getTypeInfo (silErrorTy).nativeReturnValueSchema (IGF.IGM );
3032
+
3033
+ if (nativeSchema.requiresIndirect () ||
3034
+ errorSchema.shouldReturnTypedErrorIndirectly ()) {
3035
+ // Return the error indirectly.
3036
+ auto buf = IGF.getCalleeTypedErrorResultSlot (silErrorTy);
3037
+ Args[--LastArgWritten] = buf.getAddress ();
3038
+ }
2956
3039
}
2957
3040
}
2958
3041
@@ -3134,7 +3217,22 @@ class AsyncCallEmission final : public CallEmission {
3134
3217
errorType =
3135
3218
substConv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
3136
3219
3137
- if (resultTys.size () == 1 ) {
3220
+ SILFunctionConventions fnConv (getCallee ().getOrigFunctionType (),
3221
+ IGF.getSILModule ());
3222
+
3223
+ // Get the natural IR type in the body of the function that makes
3224
+ // the call. This may be different than the IR type returned by the
3225
+ // call itself due to ABI type coercion.
3226
+ auto resultType =
3227
+ fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
3228
+ auto &nativeSchema =
3229
+ IGF.IGM .getTypeInfo (resultType).nativeReturnValueSchema (IGF.IGM );
3230
+
3231
+ bool mayReturnErrorDirectly = mayReturnTypedErrorDirectly ();
3232
+ if (mayReturnErrorDirectly && !nativeSchema.requiresIndirect ()) {
3233
+ return emitToUnmappedExplosionWithDirectTypedError (resultType, result,
3234
+ out);
3235
+ } else if (resultTys.size () == 1 ) {
3138
3236
result = Builder.CreateExtractValue (result, numAsyncContextParams);
3139
3237
if (hasError) {
3140
3238
Address errorAddr = IGF.getCalleeErrorResultSlot (errorType,
@@ -3166,17 +3264,6 @@ class AsyncCallEmission final : public CallEmission {
3166
3264
result = resultAgg;
3167
3265
}
3168
3266
3169
- SILFunctionConventions fnConv (getCallee ().getOrigFunctionType (),
3170
- IGF.getSILModule ());
3171
-
3172
- // Get the natural IR type in the body of the function that makes
3173
- // the call. This may be different than the IR type returned by the
3174
- // call itself due to ABI type coercion.
3175
- auto resultType =
3176
- fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
3177
- auto &nativeSchema =
3178
- IGF.IGM .getTypeInfo (resultType).nativeReturnValueSchema (IGF.IGM );
3179
-
3180
3267
// For ABI reasons the result type of the call might not actually match the
3181
3268
// expected result type.
3182
3269
//
@@ -3315,7 +3402,7 @@ void CallEmission::emitToUnmappedMemory(Address result) {
3315
3402
#ifndef NDEBUG
3316
3403
LastArgWritten = 0 ; // appease an assert
3317
3404
#endif
3318
-
3405
+
3319
3406
auto call = emitCallSite ();
3320
3407
3321
3408
// Async calls need to store the error result that is passed as a parameter.
@@ -4403,32 +4490,21 @@ void CallEmission::emitToUnmappedExplosionWithDirectTypedError(
4403
4490
extractScalarResults (IGF, result->getType (), result, nativeExplosion);
4404
4491
auto values = nativeExplosion.claimAll ();
4405
4492
4406
- auto convertIfNecessary = [&](llvm::Type *nativeTy,
4407
- llvm::Value *elt) -> llvm::Value * {
4408
- auto *eltTy = elt->getType ();
4409
- if (nativeTy->isIntOrPtrTy () && eltTy->isIntOrPtrTy () &&
4410
- nativeTy->getPrimitiveSizeInBits () != eltTy->getPrimitiveSizeInBits ()) {
4411
- if (nativeTy->isPointerTy () && eltTy == IGF.IGM .IntPtrTy ) {
4412
- return IGF.Builder .CreateIntToPtr (elt, nativeTy);
4413
- }
4414
- return IGF.Builder .CreateTruncOrBitCast (elt, nativeTy);
4415
- }
4416
- return elt;
4417
- };
4418
-
4419
4493
Explosion errorExplosion;
4420
4494
if (!errorSchema.empty ()) {
4421
4495
if (auto *structTy =
4422
4496
dyn_cast<llvm::StructType>(errorSchema.getExpandedType (IGF.IGM ))) {
4423
4497
for (unsigned i = 0 , e = structTy->getNumElements (); i < e; ++i) {
4424
4498
llvm::Value *elt = values[combined.errorValueMapping [i]];
4425
4499
auto *nativeTy = structTy->getElementType (i);
4426
- elt = convertIfNecessary (nativeTy , elt);
4500
+ elt = convertForAsyncDirect (IGF , elt, nativeTy, /* forExtraction */ true );
4427
4501
errorExplosion.add (elt);
4428
4502
}
4429
4503
} else {
4430
- errorExplosion.add (convertIfNecessary (
4431
- combined.combinedTy , values[combined.errorValueMapping [0 ]]));
4504
+ auto *converted =
4505
+ convertForAsyncDirect (IGF, values[combined.errorValueMapping [0 ]],
4506
+ combined.combinedTy , /* forExtraction*/ true );
4507
+ errorExplosion.add (converted);
4432
4508
}
4433
4509
4434
4510
typedErrorExplosion =
@@ -4444,10 +4520,14 @@ void CallEmission::emitToUnmappedExplosionWithDirectTypedError(
4444
4520
dyn_cast<llvm::StructType>(nativeSchema.getExpandedType (IGF.IGM ))) {
4445
4521
for (unsigned i = 0 , e = structTy->getNumElements (); i < e; ++i) {
4446
4522
auto *nativeTy = structTy->getElementType (i);
4447
- resultExplosion.add (convertIfNecessary (nativeTy, values[i]));
4523
+ auto *converted = convertForAsyncDirect (IGF, values[i], nativeTy,
4524
+ /* forExtraction*/ true );
4525
+ resultExplosion.add (converted);
4448
4526
}
4449
4527
} else {
4450
- resultExplosion.add (convertIfNecessary (combined.combinedTy , values[0 ]));
4528
+ auto *converted = convertForAsyncDirect (
4529
+ IGF, values[0 ], combined.combinedTy , /* forExtraction*/ true );
4530
+ resultExplosion.add (converted);
4451
4531
}
4452
4532
out = nativeSchema.mapFromNative (IGF.IGM , IGF, resultExplosion, resultType);
4453
4533
}
@@ -5313,6 +5393,33 @@ llvm::Value* IRGenFunction::coerceValue(llvm::Value *value, llvm::Type *toTy,
5313
5393
return loaded;
5314
5394
}
5315
5395
5396
+ llvm::Value *irgen::convertForAsyncDirect (IRGenFunction &IGF,
5397
+ llvm::Value *value, llvm::Type *toTy,
5398
+ bool forExtraction) {
5399
+ auto &Builder = IGF.Builder ;
5400
+ auto *fromTy = value->getType ();
5401
+ if (toTy->isIntOrPtrTy () && fromTy->isIntOrPtrTy () && toTy != fromTy) {
5402
+
5403
+ if (toTy->isPointerTy ()) {
5404
+ if (fromTy->isPointerTy ())
5405
+ return Builder.CreateBitCast (value, toTy);
5406
+ if (fromTy == IGF.IGM .IntPtrTy )
5407
+ return Builder.CreateIntToPtr (value, toTy);
5408
+ } else if (fromTy->isPointerTy ()) {
5409
+ if (toTy == IGF.IGM .IntPtrTy ) {
5410
+ return Builder.CreatePtrToInt (value, toTy);
5411
+ }
5412
+ }
5413
+
5414
+ if (forExtraction) {
5415
+ return Builder.CreateTruncOrBitCast (value, toTy);
5416
+ } else {
5417
+ return Builder.CreateZExtOrBitCast (value, toTy);
5418
+ }
5419
+ }
5420
+ return value;
5421
+ }
5422
+
5316
5423
void IRGenFunction::emitScalarReturn (llvm::Type *resultType,
5317
5424
Explosion &result) {
5318
5425
if (result.empty ()) {
@@ -5754,32 +5861,18 @@ void IRGenFunction::emitScalarReturn(SILType returnResultType,
5754
5861
return ;
5755
5862
}
5756
5863
5757
- auto convertIfNecessary = [&](llvm::Type *nativeTy,
5758
- llvm::Value *elt) -> llvm::Value * {
5759
- auto *eltTy = elt->getType ();
5760
- if (nativeTy->isIntOrPtrTy () && eltTy->isIntOrPtrTy () &&
5761
- nativeTy->getPrimitiveSizeInBits () !=
5762
- eltTy->getPrimitiveSizeInBits ()) {
5763
- assert (nativeTy->getPrimitiveSizeInBits () >
5764
- eltTy->getPrimitiveSizeInBits ());
5765
- if (eltTy->isPointerTy ()) {
5766
- return Builder.CreatePtrToInt (elt, nativeTy);
5767
- }
5768
- return Builder.CreateZExt (elt, nativeTy);
5769
- }
5770
- return elt;
5771
- };
5772
-
5773
5864
if (auto *structTy = dyn_cast<llvm::StructType>(combinedTy)) {
5774
5865
nativeAgg = llvm::UndefValue::get (combinedTy);
5775
5866
for (unsigned i = 0 , e = native.size (); i != e; ++i) {
5776
5867
llvm::Value *elt = native.claimNext ();
5777
5868
auto *nativeTy = structTy->getElementType (i);
5778
- elt = convertIfNecessary (nativeTy, elt);
5869
+ elt = convertForAsyncDirect (*this , elt, nativeTy,
5870
+ /* forExtraction*/ false );
5779
5871
nativeAgg = Builder.CreateInsertValue (nativeAgg, elt, i);
5780
5872
}
5781
5873
} else {
5782
- nativeAgg = convertIfNecessary (combinedTy, native.claimNext ());
5874
+ nativeAgg = convertForAsyncDirect (*this , native.claimNext (), combinedTy,
5875
+ /* forExtraction*/ false );
5783
5876
}
5784
5877
}
5785
5878
@@ -6089,6 +6182,51 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
6089
6182
SILFunctionConventions conv (fnType, IGF.getSILModule ());
6090
6183
auto &nativeSchema =
6091
6184
IGM.getTypeInfo (funcResultTypeInContext).nativeReturnValueSchema (IGM);
6185
+
6186
+ if (fnType->hasErrorResult () && !conv.hasIndirectSILResults () &&
6187
+ !conv.hasIndirectSILErrorResults () && !nativeSchema.requiresIndirect () &&
6188
+ conv.isTypedError ()) {
6189
+ auto errorType = conv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
6190
+ auto &errorTI = IGM.getTypeInfo (errorType);
6191
+ auto &nativeError = errorTI.nativeReturnValueSchema (IGM);
6192
+ if (!nativeError.shouldReturnTypedErrorIndirectly ()) {
6193
+ assert (!error.empty () && " Direct error return must have error value" );
6194
+ auto *combinedTy =
6195
+ combineResultAndTypedErrorType (IGM, nativeSchema, nativeError)
6196
+ .combinedTy ;
6197
+
6198
+ if (combinedTy->isVoidTy ()) {
6199
+ assert (result.empty () && " Unexpected result values" );
6200
+ } else {
6201
+ if (auto *structTy = dyn_cast<llvm::StructType>(combinedTy)) {
6202
+ llvm::Value *nativeAgg = llvm::UndefValue::get (structTy);
6203
+ for (unsigned i = 0 , e = result.size (); i != e; ++i) {
6204
+ llvm::Value *elt = result.claimNext ();
6205
+ auto *nativeTy = structTy->getElementType (i);
6206
+ elt = convertForAsyncDirect (IGF, elt, nativeTy,
6207
+ /* forExtraction*/ false );
6208
+ nativeAgg = IGF.Builder .CreateInsertValue (nativeAgg, elt, i);
6209
+ }
6210
+ Explosion out;
6211
+ IGF.emitAllExtractValues (nativeAgg, structTy, out);
6212
+ while (!out.empty ()) {
6213
+ nativeResultsStorage.push_back (out.claimNext ());
6214
+ }
6215
+ } else {
6216
+ auto *converted = convertForAsyncDirect (
6217
+ IGF, result.claimNext (), combinedTy, /* forExtraction*/ false );
6218
+ nativeResultsStorage.push_back (converted);
6219
+ }
6220
+ }
6221
+
6222
+ nativeResultsStorage.push_back (error.claimNext ());
6223
+ nativeResults = nativeResultsStorage;
6224
+
6225
+ emitAsyncReturn (IGF, asyncLayout, fnType, nativeResults);
6226
+ return ;
6227
+ }
6228
+ }
6229
+
6092
6230
if (result.empty () && !nativeSchema.empty ()) {
6093
6231
if (!nativeSchema.requiresIndirect ())
6094
6232
// When we throw, we set the return values to undef.
0 commit comments