25
25
#include " swift/SIL/SILModule.h"
26
26
#include " swift/SIL/SILType.h"
27
27
#include " clang/AST/ASTContext.h"
28
+ #include " clang/AST/GlobalDecl.h"
28
29
#include " clang/AST/RecordLayout.h"
29
30
#include " clang/Basic/TargetInfo.h"
30
31
#include " clang/CodeGen/CodeGenABITypes.h"
@@ -428,6 +429,10 @@ namespace {
428
429
IRGenModule &IGM;
429
430
CanSILFunctionType FnType;
430
431
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
+
431
436
public:
432
437
SmallVector<llvm::Type*, 8 > ParamIRTypes;
433
438
llvm::Type *ResultIRType = nullptr ;
@@ -442,8 +447,10 @@ namespace {
442
447
FunctionPointerKind FnKind;
443
448
444
449
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) {}
447
454
448
455
// / Expand the components of the primary entrypoint of the function type.
449
456
void expandFunctionType (
@@ -468,7 +475,7 @@ namespace {
468
475
469
476
private:
470
477
const TypeInfo &expand (SILParameterInfo param);
471
- llvm::Type *addIndirectResult ();
478
+ llvm::Type *addIndirectResult (SILType resultType );
472
479
473
480
SILFunctionConventions getSILFuncConventions () const {
474
481
return SILFunctionConventions (FnType, IGM.getSILModule ());
@@ -526,9 +533,7 @@ namespace {
526
533
} // end namespace irgen
527
534
} // end namespace swift
528
535
529
- llvm::Type *SignatureExpansion::addIndirectResult () {
530
- auto resultType = getSILFuncConventions ().getSILResultType (
531
- IGM.getMaximalTypeExpansionContext ());
536
+ llvm::Type *SignatureExpansion::addIndirectResult (SILType resultType) {
532
537
const TypeInfo &resultTI = IGM.getTypeInfo (resultType);
533
538
auto storageTy = resultTI.getStorageType ();
534
539
addIndirectResultAttributes (IGM, Attrs, ParamIRTypes.size (), claimSRet (),
@@ -925,7 +930,7 @@ SignatureExpansion::expandDirectResult() {
925
930
auto &ti = IGM.getTypeInfo (resultType);
926
931
auto &native = ti.nativeReturnValueSchema (IGM);
927
932
if (native.requiresIndirect ())
928
- return std::make_pair (addIndirectResult (), nullptr );
933
+ return std::make_pair (addIndirectResult (resultType ), nullptr );
929
934
930
935
// Disable the use of sret if we have a non-trivial direct result.
931
936
if (!native.empty ()) CanUseSRet = false ;
@@ -1361,26 +1366,28 @@ static bool doesClangExpansionMatchSchema(IRGenModule &IGM,
1361
1366
void SignatureExpansion::expandExternalSignatureTypes () {
1362
1367
assert (FnType->getLanguage () == SILFunctionLanguage::C);
1363
1368
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);
1367
1384
1368
1385
// Now convert the parameters to Clang types.
1369
1386
auto params = FnType->getParameters ();
1370
1387
1371
1388
SmallVector<clang::CanQualType,4 > paramTys;
1372
1389
auto const &clangCtx = IGM.getClangASTContext ();
1373
1390
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
-
1384
1391
switch (FnType->getRepresentation ()) {
1385
1392
case SILFunctionTypeRepresentation::ObjCMethod: {
1386
1393
// ObjC methods take their 'self' argument first, followed by an
@@ -1409,7 +1416,11 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1409
1416
}
1410
1417
1411
1418
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
+ }
1413
1424
break ;
1414
1425
1415
1426
case SILFunctionTypeRepresentation::Thin:
@@ -1437,6 +1448,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1437
1448
1438
1449
// Generate function info for this signature.
1439
1450
auto extInfo = clang::FunctionType::ExtInfo ();
1451
+
1440
1452
auto &FI = clang::CodeGen::arrangeFreeFunctionCall (IGM.ClangCodeGen ->CGM (),
1441
1453
clangResultTy, paramTys, extInfo,
1442
1454
clang::CodeGen::RequiredArgs::All);
@@ -1447,6 +1459,14 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1447
1459
1448
1460
auto &returnInfo = FI.getReturnInfo ();
1449
1461
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
+
1450
1470
// Does the result need an extension attribute?
1451
1471
if (returnInfo.isExtend ()) {
1452
1472
bool signExt = clangResultTy->hasSignedIntegerRepresentation ();
@@ -1551,16 +1571,18 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1551
1571
1552
1572
// If we return indirectly, that is the first parameter type.
1553
1573
if (returnInfo.isIndirect ()) {
1574
+ auto resultType = getSILFuncConventions ().getSingleSILResultType (
1575
+ IGM.getMaximalTypeExpansionContext ());
1554
1576
if (IGM.Triple .isWindowsMSVCEnvironment () &&
1555
1577
FnType->getRepresentation () ==
1556
1578
SILFunctionTypeRepresentation::CXXMethod) {
1557
1579
// Windows ABI places `this` before the
1558
1580
// returned indirect values.
1559
1581
emitArg (0 );
1560
1582
firstParamToLowerNormally = 1 ;
1561
- addIndirectResult ();
1583
+ addIndirectResult (resultType );
1562
1584
} else
1563
- addIndirectResult ();
1585
+ addIndirectResult (resultType );
1564
1586
}
1565
1587
1566
1588
// Use a special IR type for passing block pointers.
@@ -1574,7 +1596,12 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1574
1596
for (auto i : indices (paramTys).slice (firstParamToLowerNormally))
1575
1597
emitArg (i);
1576
1598
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 ()) {
1578
1605
ResultIRType = IGM.VoidTy ;
1579
1606
} else {
1580
1607
ResultIRType = returnInfo.getCoerceToType ();
@@ -1986,7 +2013,7 @@ void SignatureExpansion::expandAsyncEntryType() {
1986
2013
auto &ti = IGM.getTypeInfo (resultType);
1987
2014
auto &native = ti.nativeReturnValueSchema (IGM);
1988
2015
if (native.requiresIndirect ())
1989
- addIndirectResult ();
2016
+ addIndirectResult (resultType );
1990
2017
1991
2018
// Add the indirect result types.
1992
2019
expandIndirectResults ();
@@ -2153,10 +2180,11 @@ Signature SignatureExpansion::getSignature() {
2153
2180
2154
2181
Signature Signature::getUncached (IRGenModule &IGM,
2155
2182
CanSILFunctionType formalType,
2156
- FunctionPointerKind fpKind,
2157
- bool forStaticCall ) {
2183
+ FunctionPointerKind fpKind, bool forStaticCall,
2184
+ const clang::CXXConstructorDecl *cxxCtorDecl ) {
2158
2185
GenericContextScope scope (IGM, formalType->getInvocationGenericSignature ());
2159
- SignatureExpansion expansion (IGM, formalType, fpKind, forStaticCall);
2186
+ SignatureExpansion expansion (IGM, formalType, fpKind, forStaticCall,
2187
+ cxxCtorDecl);
2160
2188
expansion.expandFunctionType ();
2161
2189
return expansion.getSignature ();
2162
2190
}
@@ -3235,7 +3263,13 @@ llvm::CallBase *IRBuilder::CreateCallOrInvoke(
3235
3263
for (unsigned argIndex = 0 ; argIndex < func->arg_size (); ++argIndex) {
3236
3264
if (func->hasParamAttribute (argIndex, llvm::Attribute::StructRet)) {
3237
3265
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);
3239
3273
attrs = attrs.addParamAttributes (func->getContext (), argIndex, builder);
3240
3274
}
3241
3275
if (func->hasParamAttribute (argIndex, llvm::Attribute::ByVal)) {
@@ -3950,11 +3984,13 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
3950
3984
params = params.drop_back ();
3951
3985
}
3952
3986
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)
3956
3993
firstParam += 1 ;
3957
- }
3958
3994
3959
3995
for (unsigned i = firstParam; i != paramEnd; ++i) {
3960
3996
auto clangParamTy = FI.arg_begin ()[i].type ;
0 commit comments