@@ -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,36 @@ 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
+ getSILFuncConventions ().funcTy ->hasErrorResult () &&
2314
+ !native.requiresIndirect () && getSILFuncConventions ().isTypedError ()) {
2315
+ auto errorType = getSILFuncConventions ().getSILErrorType (
2316
+ IGM.getMaximalTypeExpansionContext ());
2317
+ auto &errorTi = IGM.getTypeInfo (errorType);
2318
+ auto &nativeError = errorTi.nativeReturnValueSchema (IGM);
2319
+ if (!nativeError.shouldReturnTypedErrorIndirectly ()) {
2320
+ auto combined = combineResultAndTypedErrorType (IGM, native, nativeError);
2321
+
2322
+ if (combined.combinedTy ->isVoidTy ()) {
2323
+ addErrorResult ();
2324
+ return ;
2325
+ }
2326
+
2327
+ if (auto *structTy = dyn_cast<llvm::StructType>(combined.combinedTy )) {
2328
+ for (auto *elem : structTy->elements ()) {
2329
+ components.push_back (elem);
2330
+ }
2331
+ } else {
2332
+ components.push_back (combined.combinedTy );
2333
+ }
2334
+ addErrorResult ();
2335
+ ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
2336
+ return ;
2337
+ }
2338
+ }
2339
+
2268
2340
if (native.requiresIndirect () || native.empty ()) {
2269
2341
addErrorResult ();
2270
2342
ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
@@ -2278,7 +2350,6 @@ void SignatureExpansion::expandAsyncAwaitType() {
2278
2350
});
2279
2351
2280
2352
addErrorResult ();
2281
-
2282
2353
ResultIRType = llvm::StructType::get (IGM.getLLVMContext (), components);
2283
2354
}
2284
2355
@@ -2950,9 +3021,22 @@ class AsyncCallEmission final : public CallEmission {
2950
3021
setIndirectTypedErrorResultSlotArgsIndex (--LastArgWritten);
2951
3022
Args[LastArgWritten] = nullptr ;
2952
3023
} else {
2953
- auto buf = IGF.getCalleeTypedErrorResultSlot (
2954
- fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()));
2955
- Args[--LastArgWritten] = buf.getAddress ();
3024
+ auto silResultTy =
3025
+ fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
3026
+ auto silErrorTy =
3027
+ fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ());
3028
+
3029
+ auto &nativeSchema =
3030
+ IGF.IGM .getTypeInfo (silResultTy).nativeReturnValueSchema (IGF.IGM );
3031
+ auto &errorSchema =
3032
+ IGF.IGM .getTypeInfo (silErrorTy).nativeReturnValueSchema (IGF.IGM );
3033
+
3034
+ if (nativeSchema.requiresIndirect () ||
3035
+ errorSchema.shouldReturnTypedErrorIndirectly ()) {
3036
+ // Return the error indirectly.
3037
+ auto buf = IGF.getCalleeTypedErrorResultSlot (silErrorTy);
3038
+ Args[--LastArgWritten] = buf.getAddress ();
3039
+ }
2956
3040
}
2957
3041
}
2958
3042
@@ -3134,7 +3218,22 @@ class AsyncCallEmission final : public CallEmission {
3134
3218
errorType =
3135
3219
substConv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
3136
3220
3137
- if (resultTys.size () == 1 ) {
3221
+ SILFunctionConventions fnConv (getCallee ().getOrigFunctionType (),
3222
+ IGF.getSILModule ());
3223
+
3224
+ // Get the natural IR type in the body of the function that makes
3225
+ // the call. This may be different than the IR type returned by the
3226
+ // call itself due to ABI type coercion.
3227
+ auto resultType =
3228
+ fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
3229
+ auto &nativeSchema =
3230
+ IGF.IGM .getTypeInfo (resultType).nativeReturnValueSchema (IGF.IGM );
3231
+
3232
+ bool mayReturnErrorDirectly = mayReturnTypedErrorDirectly ();
3233
+ if (mayReturnErrorDirectly && !nativeSchema.requiresIndirect ()) {
3234
+ return emitToUnmappedExplosionWithDirectTypedError (resultType, result,
3235
+ out);
3236
+ } else if (resultTys.size () == 1 ) {
3138
3237
result = Builder.CreateExtractValue (result, numAsyncContextParams);
3139
3238
if (hasError) {
3140
3239
Address errorAddr = IGF.getCalleeErrorResultSlot (errorType,
@@ -3166,17 +3265,6 @@ class AsyncCallEmission final : public CallEmission {
3166
3265
result = resultAgg;
3167
3266
}
3168
3267
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
3268
// For ABI reasons the result type of the call might not actually match the
3181
3269
// expected result type.
3182
3270
//
@@ -3315,7 +3403,7 @@ void CallEmission::emitToUnmappedMemory(Address result) {
3315
3403
#ifndef NDEBUG
3316
3404
LastArgWritten = 0 ; // appease an assert
3317
3405
#endif
3318
-
3406
+
3319
3407
auto call = emitCallSite ();
3320
3408
3321
3409
// Async calls need to store the error result that is passed as a parameter.
@@ -4403,32 +4491,21 @@ void CallEmission::emitToUnmappedExplosionWithDirectTypedError(
4403
4491
extractScalarResults (IGF, result->getType (), result, nativeExplosion);
4404
4492
auto values = nativeExplosion.claimAll ();
4405
4493
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
4494
Explosion errorExplosion;
4420
4495
if (!errorSchema.empty ()) {
4421
4496
if (auto *structTy =
4422
4497
dyn_cast<llvm::StructType>(errorSchema.getExpandedType (IGF.IGM ))) {
4423
4498
for (unsigned i = 0 , e = structTy->getNumElements (); i < e; ++i) {
4424
4499
llvm::Value *elt = values[combined.errorValueMapping [i]];
4425
4500
auto *nativeTy = structTy->getElementType (i);
4426
- elt = convertIfNecessary (nativeTy , elt);
4501
+ elt = convertForAsyncDirect (IGF , elt, nativeTy, /* forExtraction */ true );
4427
4502
errorExplosion.add (elt);
4428
4503
}
4429
4504
} else {
4430
- errorExplosion.add (convertIfNecessary (
4431
- combined.combinedTy , values[combined.errorValueMapping [0 ]]));
4505
+ auto *converted =
4506
+ convertForAsyncDirect (IGF, values[combined.errorValueMapping [0 ]],
4507
+ combined.combinedTy , /* forExtraction*/ true );
4508
+ errorExplosion.add (converted);
4432
4509
}
4433
4510
4434
4511
typedErrorExplosion =
@@ -4444,10 +4521,14 @@ void CallEmission::emitToUnmappedExplosionWithDirectTypedError(
4444
4521
dyn_cast<llvm::StructType>(nativeSchema.getExpandedType (IGF.IGM ))) {
4445
4522
for (unsigned i = 0 , e = structTy->getNumElements (); i < e; ++i) {
4446
4523
auto *nativeTy = structTy->getElementType (i);
4447
- resultExplosion.add (convertIfNecessary (nativeTy, values[i]));
4524
+ auto *converted = convertForAsyncDirect (IGF, values[i], nativeTy,
4525
+ /* forExtraction*/ true );
4526
+ resultExplosion.add (converted);
4448
4527
}
4449
4528
} else {
4450
- resultExplosion.add (convertIfNecessary (combined.combinedTy , values[0 ]));
4529
+ auto *converted = convertForAsyncDirect (
4530
+ IGF, values[0 ], combined.combinedTy , /* forExtraction*/ true );
4531
+ resultExplosion.add (converted);
4451
4532
}
4452
4533
out = nativeSchema.mapFromNative (IGF.IGM , IGF, resultExplosion, resultType);
4453
4534
}
@@ -5313,6 +5394,33 @@ llvm::Value* IRGenFunction::coerceValue(llvm::Value *value, llvm::Type *toTy,
5313
5394
return loaded;
5314
5395
}
5315
5396
5397
+ llvm::Value *irgen::convertForAsyncDirect (IRGenFunction &IGF,
5398
+ llvm::Value *value, llvm::Type *toTy,
5399
+ bool forExtraction) {
5400
+ auto &Builder = IGF.Builder ;
5401
+ auto *fromTy = value->getType ();
5402
+ if (toTy->isIntOrPtrTy () && fromTy->isIntOrPtrTy () && toTy != fromTy) {
5403
+
5404
+ if (toTy->isPointerTy ()) {
5405
+ if (fromTy->isPointerTy ())
5406
+ return Builder.CreateBitCast (value, toTy);
5407
+ if (fromTy == IGF.IGM .IntPtrTy )
5408
+ return Builder.CreateIntToPtr (value, toTy);
5409
+ } else if (fromTy->isPointerTy ()) {
5410
+ if (toTy == IGF.IGM .IntPtrTy ) {
5411
+ return Builder.CreatePtrToInt (value, toTy);
5412
+ }
5413
+ }
5414
+
5415
+ if (forExtraction) {
5416
+ return Builder.CreateTruncOrBitCast (value, toTy);
5417
+ } else {
5418
+ return Builder.CreateZExtOrBitCast (value, toTy);
5419
+ }
5420
+ }
5421
+ return value;
5422
+ }
5423
+
5316
5424
void IRGenFunction::emitScalarReturn (llvm::Type *resultType,
5317
5425
Explosion &result) {
5318
5426
if (result.empty ()) {
@@ -5754,32 +5862,18 @@ void IRGenFunction::emitScalarReturn(SILType returnResultType,
5754
5862
return ;
5755
5863
}
5756
5864
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
5865
if (auto *structTy = dyn_cast<llvm::StructType>(combinedTy)) {
5774
5866
nativeAgg = llvm::UndefValue::get (combinedTy);
5775
5867
for (unsigned i = 0 , e = native.size (); i != e; ++i) {
5776
5868
llvm::Value *elt = native.claimNext ();
5777
5869
auto *nativeTy = structTy->getElementType (i);
5778
- elt = convertIfNecessary (nativeTy, elt);
5870
+ elt = convertForAsyncDirect (*this , elt, nativeTy,
5871
+ /* forExtraction*/ false );
5779
5872
nativeAgg = Builder.CreateInsertValue (nativeAgg, elt, i);
5780
5873
}
5781
5874
} else {
5782
- nativeAgg = convertIfNecessary (combinedTy, native.claimNext ());
5875
+ nativeAgg = convertForAsyncDirect (*this , native.claimNext (), combinedTy,
5876
+ /* forExtraction*/ false );
5783
5877
}
5784
5878
}
5785
5879
@@ -6089,6 +6183,51 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
6089
6183
SILFunctionConventions conv (fnType, IGF.getSILModule ());
6090
6184
auto &nativeSchema =
6091
6185
IGM.getTypeInfo (funcResultTypeInContext).nativeReturnValueSchema (IGM);
6186
+
6187
+ if (fnType->hasErrorResult () && !conv.hasIndirectSILResults () &&
6188
+ !conv.hasIndirectSILErrorResults () && !nativeSchema.requiresIndirect () &&
6189
+ conv.isTypedError ()) {
6190
+ auto errorType = conv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
6191
+ auto &errorTI = IGM.getTypeInfo (errorType);
6192
+ auto &nativeError = errorTI.nativeReturnValueSchema (IGM);
6193
+ if (!nativeError.shouldReturnTypedErrorIndirectly ()) {
6194
+ assert (!error.empty () && " Direct error return must have error value" );
6195
+ auto *combinedTy =
6196
+ combineResultAndTypedErrorType (IGM, nativeSchema, nativeError)
6197
+ .combinedTy ;
6198
+
6199
+ if (combinedTy->isVoidTy ()) {
6200
+ assert (result.empty () && " Unexpected result values" );
6201
+ } else {
6202
+ if (auto *structTy = dyn_cast<llvm::StructType>(combinedTy)) {
6203
+ llvm::Value *nativeAgg = llvm::UndefValue::get (structTy);
6204
+ for (unsigned i = 0 , e = result.size (); i != e; ++i) {
6205
+ llvm::Value *elt = result.claimNext ();
6206
+ auto *nativeTy = structTy->getElementType (i);
6207
+ elt = convertForAsyncDirect (IGF, elt, nativeTy,
6208
+ /* forExtraction*/ false );
6209
+ nativeAgg = IGF.Builder .CreateInsertValue (nativeAgg, elt, i);
6210
+ }
6211
+ Explosion out;
6212
+ IGF.emitAllExtractValues (nativeAgg, structTy, out);
6213
+ while (!out.empty ()) {
6214
+ nativeResultsStorage.push_back (out.claimNext ());
6215
+ }
6216
+ } else {
6217
+ auto *converted = convertForAsyncDirect (
6218
+ IGF, result.claimNext (), combinedTy, /* forExtraction*/ false );
6219
+ nativeResultsStorage.push_back (converted);
6220
+ }
6221
+ }
6222
+
6223
+ nativeResultsStorage.push_back (error.claimNext ());
6224
+ nativeResults = nativeResultsStorage;
6225
+
6226
+ emitAsyncReturn (IGF, asyncLayout, fnType, nativeResults);
6227
+ return ;
6228
+ }
6229
+ }
6230
+
6092
6231
if (result.empty () && !nativeSchema.empty ()) {
6093
6232
if (!nativeSchema.requiresIndirect ())
6094
6233
// When we throw, we set the return values to undef.
0 commit comments