@@ -1424,22 +1424,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14241424 attrKindForExtending (signExt));
14251425 }
14261426
1427- // If we return indirectly, that is the first parameter type.
1428- if (returnInfo.isIndirect ()) {
1429- addIndirectResult ();
1430- }
1431-
1432- size_t firstParamToLowerNormally = 0 ;
1433-
1434- // Use a special IR type for passing block pointers.
1435- if (FnType->getRepresentation () == SILFunctionTypeRepresentation::Block) {
1436- assert (FI.arg_begin ()[0 ].info .isDirect () &&
1437- " block pointer not passed directly?" );
1438- ParamIRTypes.push_back (IGM.ObjCBlockPtrTy );
1439- firstParamToLowerNormally = 1 ;
1440- }
1441-
1442- for (auto i : indices (paramTys).slice (firstParamToLowerNormally)) {
1427+ auto emitArg = [&](size_t i) {
14431428 auto &AI = FI.arg_begin ()[i].info ;
14441429
14451430 // Add a padding argument if required.
@@ -1528,8 +1513,35 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15281513 case clang::CodeGen::ABIArgInfo::InAlloca:
15291514 llvm_unreachable (" Need to handle InAlloca during signature expansion" );
15301515 }
1516+ };
1517+
1518+ size_t firstParamToLowerNormally = 0 ;
1519+
1520+ // If we return indirectly, that is the first parameter type.
1521+ if (returnInfo.isIndirect ()) {
1522+ if (IGM.Triple .isWindowsMSVCEnvironment () &&
1523+ FnType->getRepresentation () ==
1524+ SILFunctionTypeRepresentation::CXXMethod) {
1525+ // Windows ABI places `this` before the
1526+ // returned indirect values.
1527+ emitArg (0 );
1528+ firstParamToLowerNormally = 1 ;
1529+ addIndirectResult ();
1530+ } else
1531+ addIndirectResult ();
1532+ }
1533+
1534+ // Use a special IR type for passing block pointers.
1535+ if (FnType->getRepresentation () == SILFunctionTypeRepresentation::Block) {
1536+ assert (FI.arg_begin ()[0 ].info .isDirect () &&
1537+ " block pointer not passed directly?" );
1538+ ParamIRTypes.push_back (IGM.ObjCBlockPtrTy );
1539+ firstParamToLowerNormally = 1 ;
15311540 }
15321541
1542+ for (auto i : indices (paramTys).slice (firstParamToLowerNormally))
1543+ emitArg (i);
1544+
15331545 if (returnInfo.isIndirect () || returnInfo.isIgnore ()) {
15341546 ResultIRType = IGM.VoidTy ;
15351547 } else {
@@ -2894,6 +2906,15 @@ void CallEmission::emitToUnmappedMemory(Address result) {
28942906 assert (LastArgWritten == 1 && " emitting unnaturally to indirect result" );
28952907
28962908 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+ }
28972918 SILFunctionConventions FnConv (CurCallee.getSubstFunctionType (),
28982919 IGF.getSILModule ());
28992920
@@ -3264,6 +3285,37 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
32643285 emitToMemory (temp, substResultTI, isOutlined);
32653286 return ;
32663287 }
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+ }
32673319
32683320 StackAddress ctemp = substResultTI.allocateStack (IGF, substResultType,
32693321 " call.aggresult" );
0 commit comments