@@ -1424,22 +1424,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1424
1424
attrKindForExtending (signExt));
1425
1425
}
1426
1426
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) {
1443
1428
auto &AI = FI.arg_begin ()[i].info ;
1444
1429
1445
1430
// Add a padding argument if required.
@@ -1528,8 +1513,35 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1528
1513
case clang::CodeGen::ABIArgInfo::InAlloca:
1529
1514
llvm_unreachable (" Need to handle InAlloca during signature expansion" );
1530
1515
}
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 ;
1531
1540
}
1532
1541
1542
+ for (auto i : indices (paramTys).slice (firstParamToLowerNormally))
1543
+ emitArg (i);
1544
+
1533
1545
if (returnInfo.isIndirect () || returnInfo.isIgnore ()) {
1534
1546
ResultIRType = IGM.VoidTy ;
1535
1547
} else {
@@ -2894,6 +2906,15 @@ void CallEmission::emitToUnmappedMemory(Address result) {
2894
2906
assert (LastArgWritten == 1 && " emitting unnaturally to indirect result" );
2895
2907
2896
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
+ }
2897
2918
SILFunctionConventions FnConv (CurCallee.getSubstFunctionType (),
2898
2919
IGF.getSILModule ());
2899
2920
@@ -3264,6 +3285,37 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
3264
3285
emitToMemory (temp, substResultTI, isOutlined);
3265
3286
return ;
3266
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
+ }
3267
3319
3268
3320
StackAddress ctemp = substResultTI.allocateStack (IGF, substResultType,
3269
3321
" call.aggresult" );
0 commit comments