@@ -358,7 +358,8 @@ static void addIndirectResultAttributes(IRGenModule &IGM,
358358 llvm::AttributeList &attrs,
359359 unsigned paramIndex, bool allowSRet,
360360 llvm::Type *storageType,
361- const TypeInfo &typeInfo) {
361+ const TypeInfo &typeInfo,
362+ bool useInReg = false ) {
362363 llvm::AttrBuilder b (IGM.getLLVMContext ());
363364 b.addAttribute (llvm::Attribute::NoAlias);
364365 // Bitwise takable value types are guaranteed not to capture
@@ -368,6 +369,8 @@ static void addIndirectResultAttributes(IRGenModule &IGM,
368369 if (allowSRet) {
369370 assert (storageType);
370371 b.addStructRetAttr (storageType);
372+ if (useInReg)
373+ b.addAttribute (llvm::Attribute::InReg);
371374 }
372375 attrs = attrs.addParamAttributes (IGM.getLLVMContext (), paramIndex, b);
373376}
@@ -475,7 +478,7 @@ namespace {
475478
476479 private:
477480 const TypeInfo &expand (SILParameterInfo param);
478- llvm::Type *addIndirectResult (SILType resultType);
481+ llvm::Type *addIndirectResult (SILType resultType, bool useInReg = false );
479482
480483 SILFunctionConventions getSILFuncConventions () const {
481484 return SILFunctionConventions (FnType, IGM.getSILModule ());
@@ -533,11 +536,12 @@ namespace {
533536} // end namespace irgen
534537} // end namespace swift
535538
536- llvm::Type *SignatureExpansion::addIndirectResult (SILType resultType) {
539+ llvm::Type *SignatureExpansion::addIndirectResult (SILType resultType,
540+ bool useInReg) {
537541 const TypeInfo &resultTI = IGM.getTypeInfo (resultType);
538542 auto storageTy = resultTI.getStorageType ();
539543 addIndirectResultAttributes (IGM, Attrs, ParamIRTypes.size (), claimSRet (),
540- storageTy, resultTI);
544+ storageTy, resultTI, useInReg );
541545 addPointerParameter (storageTy);
542546 return IGM.VoidTy ;
543547}
@@ -1449,9 +1453,15 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14491453 // Generate function info for this signature.
14501454 auto extInfo = clang::FunctionType::ExtInfo ();
14511455
1452- auto &FI = clang::CodeGen::arrangeFreeFunctionCall (IGM.ClangCodeGen ->CGM (),
1453- clangResultTy, paramTys, extInfo,
1454- clang::CodeGen::RequiredArgs::All);
1456+ bool isCXXMethod =
1457+ FnType->getRepresentation () == SILFunctionTypeRepresentation::CXXMethod;
1458+ auto &FI = isCXXMethod ?
1459+ clang::CodeGen::arrangeCXXMethodCall (IGM.ClangCodeGen ->CGM (),
1460+ clangResultTy, paramTys, extInfo, {},
1461+ clang::CodeGen::RequiredArgs::All) :
1462+ clang::CodeGen::arrangeFreeFunctionCall (IGM.ClangCodeGen ->CGM (),
1463+ clangResultTy, paramTys, extInfo, {},
1464+ clang::CodeGen::RequiredArgs::All);
14551465 ForeignInfo.ClangInfo = &FI;
14561466
14571467 assert (FI.arg_size () == paramTys.size () &&
@@ -1573,16 +1583,14 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15731583 if (returnInfo.isIndirect ()) {
15741584 auto resultType = getSILFuncConventions ().getSingleSILResultType (
15751585 IGM.getMaximalTypeExpansionContext ());
1576- if (IGM.Triple .isWindowsMSVCEnvironment () &&
1577- FnType->getRepresentation () ==
1578- SILFunctionTypeRepresentation::CXXMethod) {
1586+ if (returnInfo.isSRetAfterThis ()) {
15791587 // Windows ABI places `this` before the
15801588 // returned indirect values.
15811589 emitArg (0 );
15821590 firstParamToLowerNormally = 1 ;
1583- addIndirectResult (resultType);
1591+ addIndirectResult (resultType, returnInfo. getInReg () );
15841592 } else
1585- addIndirectResult (resultType);
1593+ addIndirectResult (resultType, returnInfo. getInReg () );
15861594 }
15871595
15881596 // Use a special IR type for passing block pointers.
@@ -2534,11 +2542,12 @@ class SyncCallEmission final : public CallEmission {
25342542
25352543 // Windows ABI places `this` before the
25362544 // returned indirect values.
2537- bool isThisFirst = IGF.IGM .Triple .isWindowsMSVCEnvironment ();
2538- if (!isThisFirst)
2545+ auto &returnInfo =
2546+ getCallee ().getForeignInfo ().ClangInfo ->getReturnInfo ();
2547+ if (returnInfo.isIndirect () && !returnInfo.isSRetAfterThis ())
25392548 passIndirectResults ();
25402549 adjusted.add (arg);
2541- if (isThisFirst )
2550+ if (returnInfo. isIndirect () && returnInfo. isSRetAfterThis () )
25422551 passIndirectResults ();
25432552 }
25442553
@@ -3115,9 +3124,10 @@ void CallEmission::emitToUnmappedMemory(Address result) {
31153124 assert (LastArgWritten == 1 && " emitting unnaturally to indirect result" );
31163125
31173126 Args[0 ] = result.getAddress ();
3118- if (IGF.IGM .Triple .isWindowsMSVCEnvironment () &&
3119- getCallee ().getRepresentation () ==
3120- SILFunctionTypeRepresentation::CXXMethod &&
3127+
3128+ auto *FI = getCallee ().getForeignInfo ().ClangInfo ;
3129+ if (FI && FI->getReturnInfo ().isIndirect () &&
3130+ FI->getReturnInfo ().isSRetAfterThis () &&
31213131 Args[1 ] == getCallee ().getCXXMethodSelf ()) {
31223132 // C++ methods in MSVC ABI pass `this` before the
31233133 // indirectly returned value.
@@ -3482,10 +3492,10 @@ void CallEmission::emitToExplosion(Explosion &out, bool isOutlined) {
34823492 emitToMemory (temp, substResultTI, isOutlined);
34833493 return ;
34843494 }
3485- if (IGF. IGM . Triple . isWindowsMSVCEnvironment () &&
3486- getCallee ().getRepresentation () ==
3487- SILFunctionTypeRepresentation::CXXMethod &&
3488- substResultType.isVoid ()) {
3495+
3496+ auto *FI = getCallee ().getForeignInfo (). ClangInfo ;
3497+ if (FI && FI-> getReturnInfo (). isIndirect () &&
3498+ FI-> getReturnInfo (). isSRetAfterThis () && substResultType.isVoid ()) {
34893499 // Some C++ methods return a value but are imported as
34903500 // returning `Void` (e.g. `operator +=`). In this case
34913501 // we should allocate the correct temp indirect return
0 commit comments