@@ -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