@@ -2906,6 +2906,15 @@ void CallEmission::emitToUnmappedMemory(Address result) {
2906
2906
assert (LastArgWritten == 1 && " emitting unnaturally to indirect result" );
2907
2907
2908
2908
Args[0 ] = result.getAddress ();
2909
+ if (IGF.IGM .Triple .isWindowsMSVCEnvironment () &&
2910
+ getCallee ().getRepresentation () ==
2911
+ SILFunctionTypeRepresentation::CXXMethod &&
2912
+ Args[1 ] == getCallee ().getCXXMethodSelf ()) {
2913
+ // C++ methods in MSVC ABI pass `this` before the
2914
+ // indirectly returned value.
2915
+ std::swap (Args[0 ], Args[1 ]);
2916
+ assert (!isa<llvm::UndefValue>(Args[1 ]));
2917
+ }
2909
2918
SILFunctionConventions FnConv (CurCallee.getSubstFunctionType (),
2910
2919
IGF.getSILModule ());
2911
2920
@@ -3276,6 +3285,37 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
3276
3285
emitToMemory (temp, substResultTI, isOutlined);
3277
3286
return ;
3278
3287
}
3288
+ if (IGF.IGM .Triple .isWindowsMSVCEnvironment () &&
3289
+ getCallee ().getRepresentation () ==
3290
+ SILFunctionTypeRepresentation::CXXMethod &&
3291
+ substResultType.isVoid ()) {
3292
+ // Some C++ methods return a value but are imported as
3293
+ // returning `Void` (e.g. `operator +=`). In this case
3294
+ // we should allocate the correct temp indirect return
3295
+ // value for it.
3296
+ // FIXME: MSVC ABI hits this as it makes some SIL direct
3297
+ // returns as indirect at IR layer, so fix this for MSVC
3298
+ // first to get this into Swfit 5.9. However, then investigate
3299
+ // if this could also apply to Itanium ABI too.
3300
+ auto fnType = getCallee ().getFunctionPointer ().getFunctionType ();
3301
+ assert (fnType->getNumParams () > 1 );
3302
+ auto func = dyn_cast<llvm::Function>(
3303
+ getCallee ().getFunctionPointer ().getRawPointer ());
3304
+ if (func) {
3305
+ // `this` comes before the returned value under the MSVC ABI
3306
+ // so return value is parameter #1.
3307
+ assert (func->hasParamAttribute (1 , llvm::Attribute::StructRet));
3308
+ auto resultTy = func->getParamStructRetType (1 );
3309
+ auto temp = IGF.createAlloca (resultTy, Alignment (/* safe alignment*/ 16 ),
3310
+ " indirect.result" );
3311
+ if (IGF.IGM .getLLVMContext ().supportsTypedPointers ()) {
3312
+ temp = IGF.Builder .CreateElementBitCast (
3313
+ temp, fnType->getParamType (1 )->getNonOpaquePointerElementType ());
3314
+ }
3315
+ emitToMemory (temp, substResultTI, isOutlined);
3316
+ return ;
3317
+ }
3318
+ }
3279
3319
3280
3320
StackAddress ctemp = substResultTI.allocateStack (IGF, substResultType,
3281
3321
" call.aggresult" );
0 commit comments