@@ -2906,6 +2906,15 @@ void CallEmission::emitToUnmappedMemory(Address result) {
29062906 assert (LastArgWritten == 1 && " emitting unnaturally to indirect result" );
29072907
29082908 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+ }
29092918 SILFunctionConventions FnConv (CurCallee.getSubstFunctionType (),
29102919 IGF.getSILModule ());
29112920
@@ -3276,6 +3285,37 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
32763285 emitToMemory (temp, substResultTI, isOutlined);
32773286 return ;
32783287 }
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+ }
32793319
32803320 StackAddress ctemp = substResultTI.allocateStack (IGF, substResultType,
32813321 " call.aggresult" );
0 commit comments