diff --git a/clang/include/clang/CodeGen/CodeGenABITypes.h b/clang/include/clang/CodeGen/CodeGenABITypes.h --- a/clang/include/clang/CodeGen/CodeGenABITypes.h +++ b/clang/include/clang/CodeGen/CodeGenABITypes.h @@ -39,6 +39,7 @@ namespace clang { class ASTContext; +class CXXConstructorDecl; class CXXRecordDecl; class CXXMethodDecl; class CodeGenOptions; @@ -53,6 +54,16 @@ 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 Prefix; + + /// Implicit arguments to add after the explicit arguments. + SmallVector Suffix; +}; + const CGFunctionInfo &arrangeObjCMessageSendSignature(CodeGenModule &CGM, const ObjCMethodDecl *MD, QualType receiverType); @@ -74,6 +85,11 @@ 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); diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -16,6 +16,7 @@ #include "CodeGenFunction.h" #include "clang/Basic/LLVM.h" +#include "clang/CodeGen/CodeGenABITypes.h" namespace llvm { class Constant; @@ -287,24 +288,44 @@ /// 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 Prefix; + SmallVector Suffix; + AddedStructorArgs() = default; + AddedStructorArgs(SmallVector P, SmallVector S) + : Prefix(std::move(P)), Suffix(std::move(S)) {} + static AddedStructorArgs prefix(SmallVector Args) { + return {std::move(Args), {}}; + } + static AddedStructorArgs suffix(SmallVector 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 &ArgTys) = 0; @@ -365,14 +386,19 @@ /// 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, diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -313,3 +313,20 @@ std::vector CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { return std::vector(); } + +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()); +} diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -326,7 +326,7 @@ 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. diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2165,7 +2165,7 @@ } // Insert any ABI-specific implicit constructor arguments. - CGCXXABI::AddedStructorArgs ExtraArgs = + CGCXXABI::AddedStructorArgCounts ExtraArgs = CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase, Delegating, Args); diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp --- a/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -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" @@ -68,6 +70,30 @@ 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!"); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -203,7 +203,7 @@ void EmitCXXConstructors(const CXXConstructorDecl *D) override; - AddedStructorArgs + AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl &ArgTys) override; @@ -222,10 +222,11 @@ 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, @@ -1550,7 +1551,7 @@ } } -CGCXXABI::AddedStructorArgs +CGCXXABI::AddedStructorArgCounts ItaniumCXXABI::buildStructorSignature(GlobalDecl GD, SmallVectorImpl &ArgTys) { ASTContext &Context = getContext(); @@ -1564,9 +1565,9 @@ cast(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) { @@ -1632,9 +1633,9 @@ 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{}; @@ -1642,8 +1643,7 @@ 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, diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -206,7 +206,7 @@ // lacks a definition for the destructor, non-base destructors must always // delegate to or alias the base destructor. - AddedStructorArgs + AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl &ArgTys) override; @@ -253,10 +253,11 @@ 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, @@ -1261,10 +1262,10 @@ } } -CGCXXABI::AddedStructorArgs +CGCXXABI::AddedStructorArgCounts MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD, SmallVectorImpl &ArgTys) { - AddedStructorArgs Added; + AddedStructorArgCounts Added; // TODO: 'for base' flag if (isa(GD.getDecl()) && GD.getDtorType() == Dtor_Deleting) { @@ -1553,9 +1554,9 @@ } } -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. @@ -1570,13 +1571,10 @@ } 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, @@ -4009,7 +4007,7 @@ 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);