Skip to content

Commit 591cd54

Browse files
martinboehmememfrob
authored andcommitted
[clang] Add an API to retrieve implicit constructor arguments.
Summary: This is needed in Swift for C++ interop -- see here for the corresponding Swift change: swiftlang/swift#30630 As part of this change, I've had to make some changes to the interface of CGCXXABI to return the additional parameters separately rather than adding them directly to a `CallArgList`. Reviewers: rjmccall Reviewed By: rjmccall Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D79942
1 parent 048bb97 commit 591cd54

File tree

8 files changed

+123
-40
lines changed

8 files changed

+123
-40
lines changed

clang/include/clang/CodeGen/CodeGenABITypes.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Type;
3939

4040
namespace clang {
4141
class ASTContext;
42+
class CXXConstructorDecl;
4243
class CXXRecordDecl;
4344
class CXXMethodDecl;
4445
class CodeGenOptions;
@@ -53,6 +54,16 @@ namespace CodeGen {
5354
class CGFunctionInfo;
5455
class CodeGenModule;
5556

57+
/// Additional implicit arguments to add to a constructor argument list.
58+
struct ImplicitCXXConstructorArgs {
59+
/// Implicit arguments to add before the explicit arguments, but after the
60+
/// `*this` argument (which always comes first).
61+
SmallVector<llvm::Value *, 1> Prefix;
62+
63+
/// Implicit arguments to add after the explicit arguments.
64+
SmallVector<llvm::Value *, 1> Suffix;
65+
};
66+
5667
const CGFunctionInfo &arrangeObjCMessageSendSignature(CodeGenModule &CGM,
5768
const ObjCMethodDecl *MD,
5869
QualType receiverType);
@@ -74,6 +85,11 @@ const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM,
7485
FunctionType::ExtInfo info,
7586
RequiredArgs args);
7687

88+
/// Returns the implicit arguments to add to a complete, non-delegating C++
89+
/// constructor call.
90+
ImplicitCXXConstructorArgs
91+
getImplicitCXXConstructorArgs(CodeGenModule &CGM, const CXXConstructorDecl *D);
92+
7793
/// Returns null if the function type is incomplete and can't be lowered.
7894
llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM,
7995
const FunctionDecl *FD);

clang/lib/CodeGen/CGCXXABI.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,20 @@ CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
313313
std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
314314
return std::vector<CharUnits>();
315315
}
316+
317+
CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs(
318+
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
319+
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
320+
AddedStructorArgs AddedArgs =
321+
getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating);
322+
for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) {
323+
Args.insert(Args.begin() + 1 + i,
324+
CallArg(RValue::get(AddedArgs.Prefix[i].Value),
325+
AddedArgs.Prefix[i].Type));
326+
}
327+
for (const auto &arg : AddedArgs.Suffix) {
328+
Args.add(RValue::get(arg.Value), arg.Type);
329+
}
330+
return AddedStructorArgCounts(AddedArgs.Prefix.size(),
331+
AddedArgs.Suffix.size());
332+
}

clang/lib/CodeGen/CGCXXABI.h

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "CodeGenFunction.h"
1818
#include "clang/Basic/LLVM.h"
19+
#include "clang/CodeGen/CodeGenABITypes.h"
1920

2021
namespace llvm {
2122
class Constant;
@@ -287,24 +288,44 @@ class CGCXXABI {
287288
/// Emit constructor variants required by this ABI.
288289
virtual void EmitCXXConstructors(const CXXConstructorDecl *D) = 0;
289290

290-
/// Notes how many arguments were added to the beginning (Prefix) and ending
291-
/// (Suffix) of an arg list.
291+
/// Additional implicit arguments to add to the beginning (Prefix) and end
292+
/// (Suffix) of a constructor / destructor arg list.
292293
///
293-
/// Note that Prefix actually refers to the number of args *after* the first
294-
/// one: `this` arguments always come first.
294+
/// Note that Prefix should actually be inserted *after* the first existing
295+
/// arg; `this` arguments always come first.
295296
struct AddedStructorArgs {
297+
struct Arg {
298+
llvm::Value *Value;
299+
QualType Type;
300+
};
301+
SmallVector<Arg, 1> Prefix;
302+
SmallVector<Arg, 1> Suffix;
303+
AddedStructorArgs() = default;
304+
AddedStructorArgs(SmallVector<Arg, 1> P, SmallVector<Arg, 1> S)
305+
: Prefix(std::move(P)), Suffix(std::move(S)) {}
306+
static AddedStructorArgs prefix(SmallVector<Arg, 1> Args) {
307+
return {std::move(Args), {}};
308+
}
309+
static AddedStructorArgs suffix(SmallVector<Arg, 1> Args) {
310+
return {{}, std::move(Args)};
311+
}
312+
};
313+
314+
/// Similar to AddedStructorArgs, but only notes the number of additional
315+
/// arguments.
316+
struct AddedStructorArgCounts {
296317
unsigned Prefix = 0;
297318
unsigned Suffix = 0;
298-
AddedStructorArgs() = default;
299-
AddedStructorArgs(unsigned P, unsigned S) : Prefix(P), Suffix(S) {}
300-
static AddedStructorArgs prefix(unsigned N) { return {N, 0}; }
301-
static AddedStructorArgs suffix(unsigned N) { return {0, N}; }
319+
AddedStructorArgCounts() = default;
320+
AddedStructorArgCounts(unsigned P, unsigned S) : Prefix(P), Suffix(S) {}
321+
static AddedStructorArgCounts prefix(unsigned N) { return {N, 0}; }
322+
static AddedStructorArgCounts suffix(unsigned N) { return {0, N}; }
302323
};
303324

304325
/// Build the signature of the given constructor or destructor variant by
305326
/// adding any required parameters. For convenience, ArgTys has been
306327
/// initialized with the type of 'this'.
307-
virtual AddedStructorArgs
328+
virtual AddedStructorArgCounts
308329
buildStructorSignature(GlobalDecl GD,
309330
SmallVectorImpl<CanQualType> &ArgTys) = 0;
310331

@@ -365,14 +386,19 @@ class CGCXXABI {
365386
/// Emit the ABI-specific prolog for the function.
366387
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
367388

389+
virtual AddedStructorArgs
390+
getImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
391+
CXXCtorType Type, bool ForVirtualBase,
392+
bool Delegating) = 0;
393+
368394
/// Add any ABI-specific implicit arguments needed to call a constructor.
369395
///
370396
/// \return The number of arguments added at the beginning and end of the
371397
/// call, which is typically zero or one.
372-
virtual AddedStructorArgs
398+
AddedStructorArgCounts
373399
addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
374400
CXXCtorType Type, bool ForVirtualBase,
375-
bool Delegating, CallArgList &Args) = 0;
401+
bool Delegating, CallArgList &Args);
376402

377403
/// Emit the destructor call.
378404
virtual void EmitDestructorCall(CodeGenFunction &CGF,

clang/lib/CodeGen/CGCall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) {
326326
if (PassParams)
327327
appendParameterTypes(*this, argTypes, paramInfos, FTP);
328328

329-
CGCXXABI::AddedStructorArgs AddedArgs =
329+
CGCXXABI::AddedStructorArgCounts AddedArgs =
330330
TheCXXABI.buildStructorSignature(GD, argTypes);
331331
if (!paramInfos.empty()) {
332332
// Note: prefix implies after the first param.

clang/lib/CodeGen/CGClass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2165,7 +2165,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
21652165
}
21662166

21672167
// Insert any ABI-specific implicit constructor arguments.
2168-
CGCXXABI::AddedStructorArgs ExtraArgs =
2168+
CGCXXABI::AddedStructorArgCounts ExtraArgs =
21692169
CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase,
21702170
Delegating, Args);
21712171

clang/lib/CodeGen/CodeGenABITypes.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "clang/CodeGen/CodeGenABITypes.h"
19+
#include "CGCXXABI.h"
1920
#include "CGRecordLayout.h"
21+
#include "CodeGenFunction.h"
2022
#include "CodeGenModule.h"
2123
#include "clang/CodeGen/CGFunctionInfo.h"
2224
#include "clang/Lex/HeaderSearchOptions.h"
@@ -68,6 +70,30 @@ CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM,
6870
info, {}, args);
6971
}
7072

73+
ImplicitCXXConstructorArgs
74+
CodeGen::getImplicitCXXConstructorArgs(CodeGenModule &CGM,
75+
const CXXConstructorDecl *D) {
76+
// We have to create a dummy CodeGenFunction here to pass to
77+
// getImplicitConstructorArgs(). In some cases (base and delegating
78+
// constructor calls), getImplicitConstructorArgs() can reach into the
79+
// CodeGenFunction to find parameters of the calling constructor to pass on to
80+
// the called constructor, but that can't happen here because we're asking for
81+
// the args for a complete, non-delegating constructor call.
82+
CodeGenFunction CGF(CGM, /* suppressNewContext= */ true);
83+
CGCXXABI::AddedStructorArgs addedArgs =
84+
CGM.getCXXABI().getImplicitConstructorArgs(CGF, D, Ctor_Complete,
85+
/* ForVirtualBase= */ false,
86+
/* Delegating= */ false);
87+
ImplicitCXXConstructorArgs implicitArgs;
88+
for (const auto &arg : addedArgs.Prefix) {
89+
implicitArgs.Prefix.push_back(arg.Value);
90+
}
91+
for (const auto &arg : addedArgs.Suffix) {
92+
implicitArgs.Suffix.push_back(arg.Value);
93+
}
94+
return implicitArgs;
95+
}
96+
7197
llvm::FunctionType *
7298
CodeGen::convertFreeFunctionType(CodeGenModule &CGM, const FunctionDecl *FD) {
7399
assert(FD != nullptr && "Expected a non-null function declaration!");

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
203203

204204
void EmitCXXConstructors(const CXXConstructorDecl *D) override;
205205

206-
AddedStructorArgs
206+
AddedStructorArgCounts
207207
buildStructorSignature(GlobalDecl GD,
208208
SmallVectorImpl<CanQualType> &ArgTys) override;
209209

@@ -222,10 +222,11 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
222222

223223
void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
224224

225-
AddedStructorArgs
226-
addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
227-
CXXCtorType Type, bool ForVirtualBase,
228-
bool Delegating, CallArgList &Args) override;
225+
AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
226+
const CXXConstructorDecl *D,
227+
CXXCtorType Type,
228+
bool ForVirtualBase,
229+
bool Delegating) override;
229230

230231
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
231232
CXXDtorType Type, bool ForVirtualBase,
@@ -1550,7 +1551,7 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
15501551
}
15511552
}
15521553

1553-
CGCXXABI::AddedStructorArgs
1554+
CGCXXABI::AddedStructorArgCounts
15541555
ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
15551556
SmallVectorImpl<CanQualType> &ArgTys) {
15561557
ASTContext &Context = getContext();
@@ -1564,9 +1565,9 @@ ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
15641565
cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) {
15651566
ArgTys.insert(ArgTys.begin() + 1,
15661567
Context.getPointerType(Context.VoidPtrTy));
1567-
return AddedStructorArgs::prefix(1);
1568+
return AddedStructorArgCounts::prefix(1);
15681569
}
1569-
return AddedStructorArgs{};
1570+
return AddedStructorArgCounts{};
15701571
}
15711572

15721573
void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
@@ -1632,18 +1633,17 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
16321633
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
16331634
}
16341635

1635-
CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(
1636+
CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
16361637
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
1637-
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
1638+
bool ForVirtualBase, bool Delegating) {
16381639
if (!NeedsVTTParameter(GlobalDecl(D, Type)))
16391640
return AddedStructorArgs{};
16401641

16411642
// Insert the implicit 'vtt' argument as the second argument.
16421643
llvm::Value *VTT =
16431644
CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);
16441645
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1645-
Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy));
1646-
return AddedStructorArgs::prefix(1); // Added one arg.
1646+
return AddedStructorArgs::prefix({{VTT, VTTTy}});
16471647
}
16481648

16491649
void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,

clang/lib/CodeGen/MicrosoftCXXABI.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ class MicrosoftCXXABI : public CGCXXABI {
206206
// lacks a definition for the destructor, non-base destructors must always
207207
// delegate to or alias the base destructor.
208208

209-
AddedStructorArgs
209+
AddedStructorArgCounts
210210
buildStructorSignature(GlobalDecl GD,
211211
SmallVectorImpl<CanQualType> &ArgTys) override;
212212

@@ -253,10 +253,11 @@ class MicrosoftCXXABI : public CGCXXABI {
253253

254254
void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
255255

256-
AddedStructorArgs
257-
addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
258-
CXXCtorType Type, bool ForVirtualBase,
259-
bool Delegating, CallArgList &Args) override;
256+
AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
257+
const CXXConstructorDecl *D,
258+
CXXCtorType Type,
259+
bool ForVirtualBase,
260+
bool Delegating) override;
260261

261262
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
262263
CXXDtorType Type, bool ForVirtualBase,
@@ -1261,10 +1262,10 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
12611262
}
12621263
}
12631264

1264-
CGCXXABI::AddedStructorArgs
1265+
CGCXXABI::AddedStructorArgCounts
12651266
MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
12661267
SmallVectorImpl<CanQualType> &ArgTys) {
1267-
AddedStructorArgs Added;
1268+
AddedStructorArgCounts Added;
12681269
// TODO: 'for base' flag
12691270
if (isa<CXXDestructorDecl>(GD.getDecl()) &&
12701271
GD.getDtorType() == Dtor_Deleting) {
@@ -1553,9 +1554,9 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
15531554
}
15541555
}
15551556

1556-
CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs(
1557+
CGCXXABI::AddedStructorArgs MicrosoftCXXABI::getImplicitConstructorArgs(
15571558
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
1558-
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
1559+
bool ForVirtualBase, bool Delegating) {
15591560
assert(Type == Ctor_Complete || Type == Ctor_Base);
15601561

15611562
// Check if we need a 'most_derived' parameter.
@@ -1570,13 +1571,10 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs(
15701571
} else {
15711572
MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
15721573
}
1573-
RValue RV = RValue::get(MostDerivedArg);
15741574
if (FPT->isVariadic()) {
1575-
Args.insert(Args.begin() + 1, CallArg(RV, getContext().IntTy));
1576-
return AddedStructorArgs::prefix(1);
1575+
return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});
15771576
}
1578-
Args.add(RV, getContext().IntTy);
1579-
return AddedStructorArgs::suffix(1);
1577+
return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});
15801578
}
15811579

15821580
void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
@@ -4009,7 +4007,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
40094007
CGF.EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0);
40104008

40114009
// Insert any ABI-specific implicit constructor arguments.
4012-
AddedStructorArgs ExtraArgs =
4010+
AddedStructorArgCounts ExtraArgs =
40134011
addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
40144012
/*ForVirtualBase=*/false,
40154013
/*Delegating=*/false, Args);

0 commit comments

Comments
 (0)