Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-pick from upstream: [clang] Add an API to retrieve implicit constructor arguments. #1240

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions clang/include/clang/CodeGen/CodeGenABITypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace llvm {

namespace clang {
class ASTContext;
class CXXConstructorDecl;
class CXXRecordDecl;
class CXXMethodDecl;
class CodeGenOptions;
Expand All @@ -52,6 +53,16 @@ namespace CodeGen {
class CGFunctionInfo;
class CodeGenModule;

/// Additional implicit arguments to add to a constructor argument list.
struct ImplicitCXXConstructorArgs {
/// Implicit arguments to add before the explicit arguments, but after the
/// `*this` argument (which always comes first).
SmallVector<llvm::Value *, 1> Prefix;

/// Implicit arguments to add after the explicit arguments.
SmallVector<llvm::Value *, 1> Suffix;
};

const CGFunctionInfo &arrangeObjCMessageSendSignature(CodeGenModule &CGM,
const ObjCMethodDecl *MD,
QualType receiverType);
Expand All @@ -73,6 +84,11 @@ const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM,
FunctionType::ExtInfo info,
RequiredArgs args);

/// Returns the implicit arguments to add to a complete, non-delegating C++
/// constructor call.
ImplicitCXXConstructorArgs
getImplicitCXXConstructorArgs(CodeGenModule &CGM, const CXXConstructorDecl *D);

/// Returns null if the function type is incomplete and can't be lowered.
llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM,
const FunctionDecl *FD);
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/CodeGen/CGCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,20 @@ CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
return std::vector<CharUnits>();
}

CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs(
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
AddedStructorArgs AddedArgs =
getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating);
for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) {
Args.insert(Args.begin() + 1 + i,
CallArg(RValue::get(AddedArgs.Prefix[i].Value),
AddedArgs.Prefix[i].Type));
}
for (const auto &arg : AddedArgs.Suffix) {
Args.add(RValue::get(arg.Value), arg.Type);
}
return AddedStructorArgCounts(AddedArgs.Prefix.size(),
AddedArgs.Suffix.size());
}
48 changes: 37 additions & 11 deletions clang/lib/CodeGen/CGCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "CodeGenFunction.h"
#include "clang/Basic/LLVM.h"
#include "clang/CodeGen/CodeGenABITypes.h"

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

/// Notes how many arguments were added to the beginning (Prefix) and ending
/// (Suffix) of an arg list.
/// Additional implicit arguments to add to the beginning (Prefix) and end
/// (Suffix) of a constructor / destructor arg list.
///
/// Note that Prefix actually refers to the number of args *after* the first
/// one: `this` arguments always come first.
/// Note that Prefix should actually be inserted *after* the first existing
/// arg; `this` arguments always come first.
struct AddedStructorArgs {
struct Arg {
llvm::Value *Value;
QualType Type;
};
SmallVector<Arg, 1> Prefix;
SmallVector<Arg, 1> Suffix;
AddedStructorArgs() = default;
AddedStructorArgs(SmallVector<Arg, 1> P, SmallVector<Arg, 1> S)
: Prefix(std::move(P)), Suffix(std::move(S)) {}
static AddedStructorArgs prefix(SmallVector<Arg, 1> Args) {
return {std::move(Args), {}};
}
static AddedStructorArgs suffix(SmallVector<Arg, 1> Args) {
return {{}, std::move(Args)};
}
};

/// Similar to AddedStructorArgs, but only notes the number of additional
/// arguments.
struct AddedStructorArgCounts {
unsigned Prefix = 0;
unsigned Suffix = 0;
AddedStructorArgs() = default;
AddedStructorArgs(unsigned P, unsigned S) : Prefix(P), Suffix(S) {}
static AddedStructorArgs prefix(unsigned N) { return {N, 0}; }
static AddedStructorArgs suffix(unsigned N) { return {0, N}; }
AddedStructorArgCounts() = default;
AddedStructorArgCounts(unsigned P, unsigned S) : Prefix(P), Suffix(S) {}
static AddedStructorArgCounts prefix(unsigned N) { return {N, 0}; }
static AddedStructorArgCounts suffix(unsigned N) { return {0, N}; }
};

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

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

virtual AddedStructorArgs
getImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
CXXCtorType Type, bool ForVirtualBase,
bool Delegating) = 0;

/// Add any ABI-specific implicit arguments needed to call a constructor.
///
/// \return The number of arguments added at the beginning and end of the
/// call, which is typically zero or one.
virtual AddedStructorArgs
AddedStructorArgCounts
addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
CXXCtorType Type, bool ForVirtualBase,
bool Delegating, CallArgList &Args) = 0;
bool Delegating, CallArgList &Args);

/// Emit the destructor call.
virtual void EmitDestructorCall(CodeGenFunction &CGF,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) {
if (PassParams)
appendParameterTypes(*this, argTypes, paramInfos, FTP);

CGCXXABI::AddedStructorArgs AddedArgs =
CGCXXABI::AddedStructorArgCounts AddedArgs =
TheCXXABI.buildStructorSignature(GD, argTypes);
if (!paramInfos.empty()) {
// Note: prefix implies after the first param.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2168,7 +2168,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
}

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

Expand Down
26 changes: 26 additions & 0 deletions clang/lib/CodeGen/CodeGenABITypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
//===----------------------------------------------------------------------===//

#include "clang/CodeGen/CodeGenABITypes.h"
#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Lex/HeaderSearchOptions.h"
Expand Down Expand Up @@ -63,6 +65,30 @@ CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM,
info, {}, args);
}

ImplicitCXXConstructorArgs
CodeGen::getImplicitCXXConstructorArgs(CodeGenModule &CGM,
const CXXConstructorDecl *D) {
// We have to create a dummy CodeGenFunction here to pass to
// getImplicitConstructorArgs(). In some cases (base and delegating
// constructor calls), getImplicitConstructorArgs() can reach into the
// CodeGenFunction to find parameters of the calling constructor to pass on to
// the called constructor, but that can't happen here because we're asking for
// the args for a complete, non-delegating constructor call.
CodeGenFunction CGF(CGM, /* suppressNewContext= */ true);
CGCXXABI::AddedStructorArgs addedArgs =
CGM.getCXXABI().getImplicitConstructorArgs(CGF, D, Ctor_Complete,
/* ForVirtualBase= */ false,
/* Delegating= */ false);
ImplicitCXXConstructorArgs implicitArgs;
for (const auto &arg : addedArgs.Prefix) {
implicitArgs.Prefix.push_back(arg.Value);
}
for (const auto &arg : addedArgs.Suffix) {
implicitArgs.Suffix.push_back(arg.Value);
}
return implicitArgs;
}

llvm::FunctionType *
CodeGen::convertFreeFunctionType(CodeGenModule &CGM, const FunctionDecl *FD) {
assert(FD != nullptr && "Expected a non-null function declaration!");
Expand Down
24 changes: 12 additions & 12 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {

void EmitCXXConstructors(const CXXConstructorDecl *D) override;

AddedStructorArgs
AddedStructorArgCounts
buildStructorSignature(GlobalDecl GD,
SmallVectorImpl<CanQualType> &ArgTys) override;

Expand All @@ -223,10 +223,11 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {

void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;

AddedStructorArgs
addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
CXXCtorType Type, bool ForVirtualBase,
bool Delegating, CallArgList &Args) override;
AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
CXXCtorType Type,
bool ForVirtualBase,
bool Delegating) override;

void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
Expand Down Expand Up @@ -1621,7 +1622,7 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
}
}

CGCXXABI::AddedStructorArgs
CGCXXABI::AddedStructorArgCounts
ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
Expand All @@ -1635,9 +1636,9 @@ ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) {
ArgTys.insert(ArgTys.begin() + 1,
Context.getPointerType(Context.VoidPtrTy));
return AddedStructorArgs::prefix(1);
return AddedStructorArgCounts::prefix(1);
}
return AddedStructorArgs{};
return AddedStructorArgCounts{};
}

void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
Expand Down Expand Up @@ -1703,18 +1704,17 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
}

CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(
CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
bool ForVirtualBase, bool Delegating) {
if (!NeedsVTTParameter(GlobalDecl(D, Type)))
return AddedStructorArgs{};

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

void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
Expand Down
28 changes: 13 additions & 15 deletions clang/lib/CodeGen/MicrosoftCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class MicrosoftCXXABI : public CGCXXABI {
// lacks a definition for the destructor, non-base destructors must always
// delegate to or alias the base destructor.

AddedStructorArgs
AddedStructorArgCounts
buildStructorSignature(GlobalDecl GD,
SmallVectorImpl<CanQualType> &ArgTys) override;

Expand Down Expand Up @@ -253,10 +253,11 @@ class MicrosoftCXXABI : public CGCXXABI {

void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;

AddedStructorArgs
addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
CXXCtorType Type, bool ForVirtualBase,
bool Delegating, CallArgList &Args) override;
AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
CXXCtorType Type,
bool ForVirtualBase,
bool Delegating) override;

void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
Expand Down Expand Up @@ -1261,10 +1262,10 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
}
}

CGCXXABI::AddedStructorArgs
CGCXXABI::AddedStructorArgCounts
MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
SmallVectorImpl<CanQualType> &ArgTys) {
AddedStructorArgs Added;
AddedStructorArgCounts Added;
// TODO: 'for base' flag
if (isa<CXXDestructorDecl>(GD.getDecl()) &&
GD.getDtorType() == Dtor_Deleting) {
Expand Down Expand Up @@ -1553,9 +1554,9 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
}
}

CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs(
CGCXXABI::AddedStructorArgs MicrosoftCXXABI::getImplicitConstructorArgs(
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
bool ForVirtualBase, bool Delegating) {
assert(Type == Ctor_Complete || Type == Ctor_Base);

// Check if we need a 'most_derived' parameter.
Expand All @@ -1570,13 +1571,10 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs(
} else {
MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
}
RValue RV = RValue::get(MostDerivedArg);
if (FPT->isVariadic()) {
Args.insert(Args.begin() + 1, CallArg(RV, getContext().IntTy));
return AddedStructorArgs::prefix(1);
return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});
}
Args.add(RV, getContext().IntTy);
return AddedStructorArgs::suffix(1);
return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});
}

void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
Expand Down Expand Up @@ -4000,7 +3998,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
CGF.EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0);

// Insert any ABI-specific implicit constructor arguments.
AddedStructorArgs ExtraArgs =
AddedStructorArgCounts ExtraArgs =
addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
/*ForVirtualBase=*/false,
/*Delegating=*/false, Args);
Expand Down