2525#include " swift/SIL/SILModule.h"
2626#include " swift/SIL/SILType.h"
2727#include " clang/AST/ASTContext.h"
28+ #include " clang/AST/GlobalDecl.h"
2829#include " clang/AST/RecordLayout.h"
2930#include " clang/Basic/TargetInfo.h"
3031#include " clang/CodeGen/CodeGenABITypes.h"
@@ -428,6 +429,10 @@ namespace {
428429 IRGenModule &IGM;
429430 CanSILFunctionType FnType;
430431 bool forStaticCall = false ; // Used for objc_method (direct call or not).
432+
433+ // Indicates this is a c++ constructor call.
434+ const clang::CXXConstructorDecl *cxxCtorDecl = nullptr ;
435+
431436 public:
432437 SmallVector<llvm::Type*, 8 > ParamIRTypes;
433438 llvm::Type *ResultIRType = nullptr ;
@@ -442,8 +447,10 @@ namespace {
442447 FunctionPointerKind FnKind;
443448
444449 SignatureExpansion (IRGenModule &IGM, CanSILFunctionType fnType,
445- FunctionPointerKind fnKind, bool forStaticCall = false )
446- : IGM(IGM), FnType(fnType), forStaticCall(forStaticCall), FnKind(fnKind) {}
450+ FunctionPointerKind fnKind, bool forStaticCall = false ,
451+ const clang::CXXConstructorDecl *cxxCtorDecl = nullptr )
452+ : IGM(IGM), FnType(fnType), forStaticCall(forStaticCall),
453+ cxxCtorDecl (cxxCtorDecl), FnKind(fnKind) {}
447454
448455 // / Expand the components of the primary entrypoint of the function type.
449456 void expandFunctionType (
@@ -468,7 +475,7 @@ namespace {
468475
469476 private:
470477 const TypeInfo &expand (SILParameterInfo param);
471- llvm::Type *addIndirectResult ();
478+ llvm::Type *addIndirectResult (SILType resultType );
472479
473480 SILFunctionConventions getSILFuncConventions () const {
474481 return SILFunctionConventions (FnType, IGM.getSILModule ());
@@ -526,9 +533,7 @@ namespace {
526533} // end namespace irgen
527534} // end namespace swift
528535
529- llvm::Type *SignatureExpansion::addIndirectResult () {
530- auto resultType = getSILFuncConventions ().getSILResultType (
531- IGM.getMaximalTypeExpansionContext ());
536+ llvm::Type *SignatureExpansion::addIndirectResult (SILType resultType) {
532537 const TypeInfo &resultTI = IGM.getTypeInfo (resultType);
533538 auto storageTy = resultTI.getStorageType ();
534539 addIndirectResultAttributes (IGM, Attrs, ParamIRTypes.size (), claimSRet (),
@@ -925,7 +930,7 @@ SignatureExpansion::expandDirectResult() {
925930 auto &ti = IGM.getTypeInfo (resultType);
926931 auto &native = ti.nativeReturnValueSchema (IGM);
927932 if (native.requiresIndirect ())
928- return std::make_pair (addIndirectResult (), nullptr );
933+ return std::make_pair (addIndirectResult (resultType ), nullptr );
929934
930935 // Disable the use of sret if we have a non-trivial direct result.
931936 if (!native.empty ()) CanUseSRet = false ;
@@ -1361,26 +1366,28 @@ static bool doesClangExpansionMatchSchema(IRGenModule &IGM,
13611366void SignatureExpansion::expandExternalSignatureTypes () {
13621367 assert (FnType->getLanguage () == SILFunctionLanguage::C);
13631368
1364- // Convert the SIL result type to a Clang type.
1365- auto clangResultTy =
1366- IGM.getClangType (FnType->getFormalCSemanticResult (IGM.getSILModule ()));
1369+ auto SILResultTy = [&]() {
1370+ if (FnType->getNumResults () == 0 )
1371+ return SILType::getPrimitiveObjectType (IGM.Context .TheEmptyTupleType );
1372+
1373+ return SILType::getPrimitiveObjectType (
1374+ FnType->getSingleResult ().getReturnValueType (
1375+ IGM.getSILModule (), FnType, TypeExpansionContext::minimal ()));
1376+ }();
1377+
1378+ // Convert the SIL result type to a Clang type. If this is for a c++
1379+ // constructor, use 'void' as the return type to arrange the function type.
1380+ auto clangResultTy = IGM.getClangType (
1381+ cxxCtorDecl
1382+ ? SILType::getPrimitiveObjectType (IGM.Context .TheEmptyTupleType )
1383+ : SILResultTy);
13671384
13681385 // Now convert the parameters to Clang types.
13691386 auto params = FnType->getParameters ();
13701387
13711388 SmallVector<clang::CanQualType,4 > paramTys;
13721389 auto const &clangCtx = IGM.getClangASTContext ();
13731390
1374- bool formalIndirectResult = FnType->getNumResults () > 0 &&
1375- FnType->getSingleResult ().isFormalIndirect ();
1376- if (formalIndirectResult) {
1377- auto resultType = getSILFuncConventions ().getSingleSILResultType (
1378- IGM.getMaximalTypeExpansionContext ());
1379- auto clangTy =
1380- IGM.getClangASTContext ().getPointerType (IGM.getClangType (resultType));
1381- paramTys.push_back (clangTy);
1382- }
1383-
13841391 switch (FnType->getRepresentation ()) {
13851392 case SILFunctionTypeRepresentation::ObjCMethod: {
13861393 // ObjC methods take their 'self' argument first, followed by an
@@ -1409,7 +1416,11 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14091416 }
14101417
14111418 case SILFunctionTypeRepresentation::CFunctionPointer:
1412- // No implicit arguments.
1419+ if (cxxCtorDecl) {
1420+ auto clangTy = IGM.getClangASTContext ().getPointerType (
1421+ IGM.getClangType (SILResultTy));
1422+ paramTys.push_back (clangTy);
1423+ }
14131424 break ;
14141425
14151426 case SILFunctionTypeRepresentation::Thin:
@@ -1437,6 +1448,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14371448
14381449 // Generate function info for this signature.
14391450 auto extInfo = clang::FunctionType::ExtInfo ();
1451+
14401452 auto &FI = clang::CodeGen::arrangeFreeFunctionCall (IGM.ClangCodeGen ->CGM (),
14411453 clangResultTy, paramTys, extInfo,
14421454 clang::CodeGen::RequiredArgs::All);
@@ -1447,6 +1459,14 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14471459
14481460 auto &returnInfo = FI.getReturnInfo ();
14491461
1462+ #ifndef NDEBUG
1463+ bool formalIndirectResult = FnType->getNumResults () > 0 &&
1464+ FnType->getSingleResult ().isFormalIndirect ();
1465+ assert (
1466+ (cxxCtorDecl || !formalIndirectResult || returnInfo.isIndirect ()) &&
1467+ " swift and clang disagree on whether the result is returned indirectly" );
1468+ #endif
1469+
14501470 // Does the result need an extension attribute?
14511471 if (returnInfo.isExtend ()) {
14521472 bool signExt = clangResultTy->hasSignedIntegerRepresentation ();
@@ -1551,16 +1571,18 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15511571
15521572 // If we return indirectly, that is the first parameter type.
15531573 if (returnInfo.isIndirect ()) {
1574+ auto resultType = getSILFuncConventions ().getSingleSILResultType (
1575+ IGM.getMaximalTypeExpansionContext ());
15541576 if (IGM.Triple .isWindowsMSVCEnvironment () &&
15551577 FnType->getRepresentation () ==
15561578 SILFunctionTypeRepresentation::CXXMethod) {
15571579 // Windows ABI places `this` before the
15581580 // returned indirect values.
15591581 emitArg (0 );
15601582 firstParamToLowerNormally = 1 ;
1561- addIndirectResult ();
1583+ addIndirectResult (resultType );
15621584 } else
1563- addIndirectResult ();
1585+ addIndirectResult (resultType );
15641586 }
15651587
15661588 // Use a special IR type for passing block pointers.
@@ -1574,7 +1596,12 @@ void SignatureExpansion::expandExternalSignatureTypes() {
15741596 for (auto i : indices (paramTys).slice (firstParamToLowerNormally))
15751597 emitArg (i);
15761598
1577- if (returnInfo.isIndirect () || returnInfo.isIgnore ()) {
1599+ if (cxxCtorDecl) {
1600+ ResultIRType = cast<llvm::Function>(IGM.getAddrOfClangGlobalDecl (
1601+ {cxxCtorDecl, clang::Ctor_Complete},
1602+ (ForDefinition_t) false ))
1603+ ->getReturnType ();
1604+ } else if (returnInfo.isIndirect () || returnInfo.isIgnore ()) {
15781605 ResultIRType = IGM.VoidTy ;
15791606 } else {
15801607 ResultIRType = returnInfo.getCoerceToType ();
@@ -1986,7 +2013,7 @@ void SignatureExpansion::expandAsyncEntryType() {
19862013 auto &ti = IGM.getTypeInfo (resultType);
19872014 auto &native = ti.nativeReturnValueSchema (IGM);
19882015 if (native.requiresIndirect ())
1989- addIndirectResult ();
2016+ addIndirectResult (resultType );
19902017
19912018 // Add the indirect result types.
19922019 expandIndirectResults ();
@@ -2153,10 +2180,11 @@ Signature SignatureExpansion::getSignature() {
21532180
21542181Signature Signature::getUncached (IRGenModule &IGM,
21552182 CanSILFunctionType formalType,
2156- FunctionPointerKind fpKind,
2157- bool forStaticCall ) {
2183+ FunctionPointerKind fpKind, bool forStaticCall,
2184+ const clang::CXXConstructorDecl *cxxCtorDecl ) {
21582185 GenericContextScope scope (IGM, formalType->getInvocationGenericSignature ());
2159- SignatureExpansion expansion (IGM, formalType, fpKind, forStaticCall);
2186+ SignatureExpansion expansion (IGM, formalType, fpKind, forStaticCall,
2187+ cxxCtorDecl);
21602188 expansion.expandFunctionType ();
21612189 return expansion.getSignature ();
21622190}
@@ -3235,7 +3263,13 @@ llvm::CallBase *IRBuilder::CreateCallOrInvoke(
32353263 for (unsigned argIndex = 0 ; argIndex < func->arg_size (); ++argIndex) {
32363264 if (func->hasParamAttribute (argIndex, llvm::Attribute::StructRet)) {
32373265 llvm::AttrBuilder builder (func->getContext ());
3238- builder.addStructRetAttr (func->getParamStructRetType (argIndex));
3266+ // See if there is a sret parameter in the signature. There are cases
3267+ // where the called function has a sret parameter, but the signature
3268+ // doesn't (e.g., noreturn functions).
3269+ llvm::Type *ty = attrs.getParamStructRetType (argIndex);
3270+ if (!ty)
3271+ ty = func->getParamStructRetType (argIndex);
3272+ builder.addStructRetAttr (ty);
32393273 attrs = attrs.addParamAttributes (func->getContext (), argIndex, builder);
32403274 }
32413275 if (func->hasParamAttribute (argIndex, llvm::Attribute::ByVal)) {
@@ -3950,11 +3984,13 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
39503984 params = params.drop_back ();
39513985 }
39523986
3953- if (fnType->getNumResults () > 0 &&
3954- fnType->getSingleResult ().isFormalIndirect ()) {
3955- // Ignore the indirect result parameter.
3987+ bool formalIndirectResult = fnType->getNumResults () > 0 &&
3988+ fnType->getSingleResult ().isFormalIndirect ();
3989+
3990+ // If clang returns directly and swift returns indirectly, this must be a c++
3991+ // constructor call. In that case, skip the "self" param.
3992+ if (!FI.getReturnInfo ().isIndirect () && formalIndirectResult)
39563993 firstParam += 1 ;
3957- }
39583994
39593995 for (unsigned i = firstParam; i != paramEnd; ++i) {
39603996 auto clangParamTy = FI.arg_begin ()[i].type ;
0 commit comments