From c1f3bf0e3fb80e6820c8e9bad0b58eb79869f0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20B=C3=B6hme?= Date: Tue, 19 May 2020 08:43:46 +0200 Subject: [PATCH] [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: https://github.com/apple/swift/pull/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 --- clang/include/clang/CodeGen/CodeGenABITypes.h | 16 +++++++ clang/lib/CodeGen/CGCXXABI.cpp | 17 +++++++ clang/lib/CodeGen/CGCXXABI.h | 48 ++++++++++++++----- clang/lib/CodeGen/CGCall.cpp | 2 +- clang/lib/CodeGen/CGClass.cpp | 2 +- clang/lib/CodeGen/CodeGenABITypes.cpp | 26 ++++++++++ clang/lib/CodeGen/ItaniumCXXABI.cpp | 24 +++++----- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 28 +++++------ 8 files changed, 123 insertions(+), 40 deletions(-) diff --git a/clang/include/clang/CodeGen/CodeGenABITypes.h b/clang/include/clang/CodeGen/CodeGenABITypes.h index a8457ac349cd66..09833c06031a62 100644 --- a/clang/include/clang/CodeGen/CodeGenABITypes.h +++ b/clang/include/clang/CodeGen/CodeGenABITypes.h @@ -38,6 +38,7 @@ namespace llvm { namespace clang { class ASTContext; +class CXXConstructorDecl; class CXXRecordDecl; class CXXMethodDecl; class CodeGenOptions; @@ -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 Prefix; + + /// Implicit arguments to add after the explicit arguments. + SmallVector Suffix; +}; + const CGFunctionInfo &arrangeObjCMessageSendSignature(CodeGenModule &CGM, const ObjCMethodDecl *MD, QualType receiverType); @@ -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); diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 7ada4032b3eefd..928fbaea82787d 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -313,3 +313,20 @@ CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { 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/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index bff49be7a3c455..f5f378510950be 100644 --- 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 @@ 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 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 @@ 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, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index bfb7977e35162d..db3e81085bb34f 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -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. diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 4dedfc02f551b4..911b0fe457c16e 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -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); diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp index 6b6a116cf259b6..36bb5155dc69df 100644 --- 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" @@ -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!"); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 4742639b7dff37..e31285e6eaddcf 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -204,7 +204,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { void EmitCXXConstructors(const CXXConstructorDecl *D) override; - AddedStructorArgs + AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl &ArgTys) override; @@ -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, @@ -1621,7 +1622,7 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { } } -CGCXXABI::AddedStructorArgs +CGCXXABI::AddedStructorArgCounts ItaniumCXXABI::buildStructorSignature(GlobalDecl GD, SmallVectorImpl &ArgTys) { ASTContext &Context = getContext(); @@ -1635,9 +1636,9 @@ ItaniumCXXABI::buildStructorSignature(GlobalDecl GD, 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) { @@ -1703,9 +1704,9 @@ 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{}; @@ -1713,8 +1714,7 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( 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 index ba7f61e705fdcf..f4281959a22cf1 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -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 &ArgTys) override; @@ -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, @@ -1261,10 +1262,10 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF, } } -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 @@ 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. @@ -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, @@ -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);