24
24
#include " swift/SIL/SILModule.h"
25
25
#include " swift/SIL/SILType.h"
26
26
#include " clang/AST/ASTContext.h"
27
+ #include " clang/AST/GlobalDecl.h"
27
28
#include " clang/AST/RecordLayout.h"
28
29
#include " clang/Basic/TargetInfo.h"
29
30
#include " clang/CodeGen/CodeGenABITypes.h"
@@ -420,6 +421,10 @@ namespace {
420
421
IRGenModule &IGM;
421
422
CanSILFunctionType FnType;
422
423
bool forStaticCall = false ; // Used for objc_method (direct call or not).
424
+
425
+ // Indicates this is a c++ constructor call.
426
+ const clang::CXXConstructorDecl *cxxCtorDecl = nullptr ;
427
+
423
428
public:
424
429
SmallVector<llvm::Type*, 8 > ParamIRTypes;
425
430
llvm::Type *ResultIRType = nullptr ;
@@ -434,8 +439,10 @@ namespace {
434
439
FunctionPointerKind FnKind;
435
440
436
441
SignatureExpansion (IRGenModule &IGM, CanSILFunctionType fnType,
437
- FunctionPointerKind fnKind, bool forStaticCall = false )
438
- : IGM(IGM), FnType(fnType), forStaticCall(forStaticCall), FnKind(fnKind) {}
442
+ FunctionPointerKind fnKind, bool forStaticCall = false ,
443
+ const clang::CXXConstructorDecl *cxxCtorDecl = nullptr )
444
+ : IGM(IGM), FnType(fnType), forStaticCall(forStaticCall),
445
+ cxxCtorDecl (cxxCtorDecl), FnKind(fnKind) {}
439
446
440
447
// / Expand the components of the primary entrypoint of the function type.
441
448
void expandFunctionType (
@@ -460,7 +467,7 @@ namespace {
460
467
461
468
private:
462
469
const TypeInfo &expand (SILParameterInfo param);
463
- llvm::Type *addIndirectResult ();
470
+ llvm::Type *addIndirectResult (SILType resultType );
464
471
465
472
SILFunctionConventions getSILFuncConventions () const {
466
473
return SILFunctionConventions (FnType, IGM.getSILModule ());
@@ -514,9 +521,7 @@ namespace {
514
521
} // end namespace irgen
515
522
} // end namespace swift
516
523
517
- llvm::Type *SignatureExpansion::addIndirectResult () {
518
- auto resultType = getSILFuncConventions ().getSILResultType (
519
- IGM.getMaximalTypeExpansionContext ());
524
+ llvm::Type *SignatureExpansion::addIndirectResult (SILType resultType) {
520
525
const TypeInfo &resultTI = IGM.getTypeInfo (resultType);
521
526
auto storageTy = resultTI.getStorageType ();
522
527
addIndirectResultAttributes (IGM, Attrs, ParamIRTypes.size (), claimSRet (),
@@ -913,7 +918,7 @@ SignatureExpansion::expandDirectResult() {
913
918
auto &ti = IGM.getTypeInfo (resultType);
914
919
auto &native = ti.nativeReturnValueSchema (IGM);
915
920
if (native.requiresIndirect ())
916
- return std::make_pair (addIndirectResult (), nullptr );
921
+ return std::make_pair (addIndirectResult (resultType ), nullptr );
917
922
918
923
// Disable the use of sret if we have a non-trivial direct result.
919
924
if (!native.empty ()) CanUseSRet = false ;
@@ -1345,26 +1350,28 @@ static bool doesClangExpansionMatchSchema(IRGenModule &IGM,
1345
1350
void SignatureExpansion::expandExternalSignatureTypes () {
1346
1351
assert (FnType->getLanguage () == SILFunctionLanguage::C);
1347
1352
1348
- // Convert the SIL result type to a Clang type.
1349
- auto clangResultTy =
1350
- IGM.getClangType (FnType->getFormalCSemanticResult (IGM.getSILModule ()));
1353
+ auto SILResultTy = [&]() {
1354
+ if (FnType->getNumResults () == 0 )
1355
+ return SILType::getPrimitiveObjectType (IGM.Context .TheEmptyTupleType );
1356
+
1357
+ return SILType::getPrimitiveObjectType (
1358
+ FnType->getSingleResult ().getReturnValueType (
1359
+ IGM.getSILModule (), FnType, TypeExpansionContext::minimal ()));
1360
+ }();
1361
+
1362
+ // Convert the SIL result type to a Clang type. If this is for a c++
1363
+ // constructor, use 'void' as the return type to arrange the function type.
1364
+ auto clangResultTy = IGM.getClangType (
1365
+ cxxCtorDecl
1366
+ ? SILType::getPrimitiveObjectType (IGM.Context .TheEmptyTupleType )
1367
+ : SILResultTy);
1351
1368
1352
1369
// Now convert the parameters to Clang types.
1353
1370
auto params = FnType->getParameters ();
1354
1371
1355
1372
SmallVector<clang::CanQualType,4 > paramTys;
1356
1373
auto const &clangCtx = IGM.getClangASTContext ();
1357
1374
1358
- bool formalIndirectResult = FnType->getNumResults () > 0 &&
1359
- FnType->getSingleResult ().isFormalIndirect ();
1360
- if (formalIndirectResult) {
1361
- auto resultType = getSILFuncConventions ().getSingleSILResultType (
1362
- IGM.getMaximalTypeExpansionContext ());
1363
- auto clangTy =
1364
- IGM.getClangASTContext ().getPointerType (IGM.getClangType (resultType));
1365
- paramTys.push_back (clangTy);
1366
- }
1367
-
1368
1375
switch (FnType->getRepresentation ()) {
1369
1376
case SILFunctionTypeRepresentation::ObjCMethod: {
1370
1377
// ObjC methods take their 'self' argument first, followed by an
@@ -1393,7 +1400,11 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1393
1400
}
1394
1401
1395
1402
case SILFunctionTypeRepresentation::CFunctionPointer:
1396
- // No implicit arguments.
1403
+ if (cxxCtorDecl) {
1404
+ auto clangTy = IGM.getClangASTContext ().getPointerType (
1405
+ IGM.getClangType (SILResultTy));
1406
+ paramTys.push_back (clangTy);
1407
+ }
1397
1408
break ;
1398
1409
1399
1410
case SILFunctionTypeRepresentation::Thin:
@@ -1417,6 +1428,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1417
1428
1418
1429
// Generate function info for this signature.
1419
1430
auto extInfo = clang::FunctionType::ExtInfo ();
1431
+
1420
1432
auto &FI = clang::CodeGen::arrangeFreeFunctionCall (IGM.ClangCodeGen ->CGM (),
1421
1433
clangResultTy, paramTys, extInfo,
1422
1434
clang::CodeGen::RequiredArgs::All);
@@ -1427,6 +1439,14 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1427
1439
1428
1440
auto &returnInfo = FI.getReturnInfo ();
1429
1441
1442
+ #ifndef NDEBUG
1443
+ bool formalIndirectResult = FnType->getNumResults () > 0 &&
1444
+ FnType->getSingleResult ().isFormalIndirect ();
1445
+ assert (
1446
+ (cxxCtorDecl || !formalIndirectResult || returnInfo.isIndirect ()) &&
1447
+ " swift and clang disagree on whether the result is returned indirectly" );
1448
+ #endif
1449
+
1430
1450
// Does the result need an extension attribute?
1431
1451
if (returnInfo.isExtend ()) {
1432
1452
bool signExt = clangResultTy->hasSignedIntegerRepresentation ();
@@ -1531,16 +1551,18 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1531
1551
1532
1552
// If we return indirectly, that is the first parameter type.
1533
1553
if (returnInfo.isIndirect ()) {
1554
+ auto resultType = getSILFuncConventions ().getSingleSILResultType (
1555
+ IGM.getMaximalTypeExpansionContext ());
1534
1556
if (IGM.Triple .isWindowsMSVCEnvironment () &&
1535
1557
FnType->getRepresentation () ==
1536
1558
SILFunctionTypeRepresentation::CXXMethod) {
1537
1559
// Windows ABI places `this` before the
1538
1560
// returned indirect values.
1539
1561
emitArg (0 );
1540
1562
firstParamToLowerNormally = 1 ;
1541
- addIndirectResult ();
1563
+ addIndirectResult (resultType );
1542
1564
} else
1543
- addIndirectResult ();
1565
+ addIndirectResult (resultType );
1544
1566
}
1545
1567
1546
1568
// Use a special IR type for passing block pointers.
@@ -1554,7 +1576,12 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1554
1576
for (auto i : indices (paramTys).slice (firstParamToLowerNormally))
1555
1577
emitArg (i);
1556
1578
1557
- if (returnInfo.isIndirect () || returnInfo.isIgnore ()) {
1579
+ if (cxxCtorDecl) {
1580
+ ResultIRType = cast<llvm::Function>(IGM.getAddrOfClangGlobalDecl (
1581
+ {cxxCtorDecl, clang::Ctor_Complete},
1582
+ (ForDefinition_t) false ))
1583
+ ->getReturnType ();
1584
+ } else if (returnInfo.isIndirect () || returnInfo.isIgnore ()) {
1558
1585
ResultIRType = IGM.VoidTy ;
1559
1586
} else {
1560
1587
ResultIRType = returnInfo.getCoerceToType ();
@@ -1874,7 +1901,7 @@ void SignatureExpansion::expandAsyncEntryType() {
1874
1901
auto &ti = IGM.getTypeInfo (resultType);
1875
1902
auto &native = ti.nativeReturnValueSchema (IGM);
1876
1903
if (native.requiresIndirect ())
1877
- addIndirectResult ();
1904
+ addIndirectResult (resultType );
1878
1905
1879
1906
// Add the indirect result types.
1880
1907
expandIndirectResults ();
@@ -2035,10 +2062,11 @@ Signature SignatureExpansion::getSignature() {
2035
2062
2036
2063
Signature Signature::getUncached (IRGenModule &IGM,
2037
2064
CanSILFunctionType formalType,
2038
- FunctionPointerKind fpKind,
2039
- bool forStaticCall ) {
2065
+ FunctionPointerKind fpKind, bool forStaticCall,
2066
+ const clang::CXXConstructorDecl *cxxCtorDecl ) {
2040
2067
GenericContextScope scope (IGM, formalType->getInvocationGenericSignature ());
2041
- SignatureExpansion expansion (IGM, formalType, fpKind, forStaticCall);
2068
+ SignatureExpansion expansion (IGM, formalType, fpKind, forStaticCall,
2069
+ cxxCtorDecl);
2042
2070
expansion.expandFunctionType ();
2043
2071
return expansion.getSignature ();
2044
2072
}
@@ -3083,7 +3111,13 @@ llvm::CallBase *IRBuilder::CreateCallOrInvoke(
3083
3111
for (unsigned argIndex = 0 ; argIndex < func->arg_size (); ++argIndex) {
3084
3112
if (func->hasParamAttribute (argIndex, llvm::Attribute::StructRet)) {
3085
3113
llvm::AttrBuilder builder (func->getContext ());
3086
- builder.addStructRetAttr (func->getParamStructRetType (argIndex));
3114
+ // See if there is a sret parameter in the signature. There are cases
3115
+ // where the called function has a sret parameter, but the signature
3116
+ // doesn't (e.g., noreturn functions).
3117
+ llvm::Type *ty = attrs.getParamStructRetType (argIndex);
3118
+ if (!ty)
3119
+ ty = func->getParamStructRetType (argIndex);
3120
+ builder.addStructRetAttr (ty);
3087
3121
attrs = attrs.addParamAttributes (func->getContext (), argIndex, builder);
3088
3122
}
3089
3123
if (func->hasParamAttribute (argIndex, llvm::Attribute::ByVal)) {
@@ -3797,11 +3831,13 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
3797
3831
params = params.drop_back ();
3798
3832
}
3799
3833
3800
- if (fnType->getNumResults () > 0 &&
3801
- fnType->getSingleResult ().isFormalIndirect ()) {
3802
- // Ignore the indirect result parameter.
3834
+ bool formalIndirectResult = fnType->getNumResults () > 0 &&
3835
+ fnType->getSingleResult ().isFormalIndirect ();
3836
+
3837
+ // If clang returns directly and swift returns indirectly, this must be a c++
3838
+ // constructor call. In that case, skip the "self" param.
3839
+ if (!FI.getReturnInfo ().isIndirect () && formalIndirectResult)
3803
3840
firstParam += 1 ;
3804
- }
3805
3841
3806
3842
for (unsigned i = firstParam; i != paramEnd; ++i) {
3807
3843
auto clangParamTy = FI.arg_begin ()[i].type ;
0 commit comments