diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 35 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 29 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 69 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 86 |
9 files changed, 139 insertions, 107 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 412b27814ac..e9e34b0a1a4 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -116,7 +116,7 @@ bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { return true; } -void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { +void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); // FIXME: I'm not entirely sure I like using a fake decl just for code diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index cbb120f576f..6c89143c5fb 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -67,11 +67,8 @@ protected: return CGF.CXXStructorImplicitParamValue; } - /// Build a parameter variable suitable for 'this'. - void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params); - /// Perform prolog initialization of the parameter variable suitable - /// for 'this' emitted by BuildThisParam. + /// for 'this' emitted by buildThisParam. void EmitThisParam(CodeGenFunction &CGF); ASTContext &getContext() const { return CGM.getContext(); } @@ -270,16 +267,18 @@ public: return This; } - /// Build the ABI-specific portion of the parameter list for a - /// function. This generally involves a 'this' parameter and - /// possibly some extra data for constructors and destructors. + /// Build a parameter variable suitable for 'this'. + void buildThisParam(CodeGenFunction &CGF, FunctionArgList &Params); + + /// Insert any ABI-specific implicit parameters into the parameter list for a + /// function. This generally involves extra data for constructors and + /// destructors. /// /// ABIs may also choose to override the return type, which has been /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or /// the formal return type of the function otherwise. - virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params) = 0; + virtual void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, + FunctionArgList &Params) = 0; /// Perform ABI-specific "this" parameter adjustment in a virtual function /// prologue. @@ -291,14 +290,14 @@ public: /// Emit the ABI-specific prolog for the function. virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0; - /// Emit the constructor call. - virtual void EmitConstructorCall(CodeGenFunction &CGF, - const CXXConstructorDecl *D, - CXXCtorType Type, - bool ForVirtualBase, bool Delegating, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) = 0; + /// Add any ABI-specific implicit arguments needed to call a constructor. + /// + /// \return The number of args added to the call, which is typically zero or + /// one. + virtual unsigned + addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, + CXXCtorType Type, bool ForVirtualBase, + bool Delegating, CallArgList &Args) = 0; /// Emit the destructor call. virtual void EmitDestructorCall(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 726e808ed08..50cbdb1b071 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -202,16 +202,17 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D, CanQualType resultType = TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy; - TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes); - CanQual<FunctionProtoType> FTP = GetFormalType(D); - RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, argTypes.size()); - // Add the formal parameters. for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) argTypes.push_back(FTP->getArgType(i)); + TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes); + + RequiredArgs required = + (D->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All); + FunctionType::ExtInfo extInfo = FTP->getExtInfo(); return arrangeLLVMFunctionInfo(resultType, argTypes, extInfo, required); } diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 7a0391b9b9c..20ff2a46def 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1682,9 +1682,32 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, return; } - // Non-trivial constructors are handled in an ABI-specific manner. - CGM.getCXXABI().EmitConstructorCall(*this, D, Type, ForVirtualBase, - Delegating, This, ArgBeg, ArgEnd); + // C++11 [class.mfct.non-static]p2: + // If a non-static member function of a class X is called for an object that + // is not of type X, or of a type derived from X, the behavior is undefined. + // FIXME: Provide a source location here. + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), This, + getContext().getRecordType(D->getParent())); + + CallArgList Args; + + // Push the this ptr. + Args.add(RValue::get(This), D->getThisType(getContext())); + + // Add the rest of the user-supplied arguments. + const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); + EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); + + // Insert any ABI-specific implicit constructor arguments. + unsigned ExtraArgs = CGM.getCXXABI().addImplicitConstructorArgs( + *this, D, Type, ForVirtualBase, Delegating, Args); + + // Emit the call. + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); + RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs); + const CGFunctionInfo &Info = + CGM.getTypes().arrangeCXXMethodCall(Args, FPT, Required); + EmitCall(Info, Callee, ReturnValueSlot(), Args, D); } void diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 894e81ca297..a5967fddf24 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -253,7 +253,7 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, FunctionArgList FunctionArgs; // Create the implicit 'this' parameter declaration. - CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs); + CGM.getCXXABI().buildThisParam(*this, FunctionArgs); // Add the rest of the parameters. for (FunctionDecl::param_const_iterator I = MD->param_begin(), @@ -261,6 +261,9 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, I != E; ++I) FunctionArgs.push_back(*I); + if (isa<CXXDestructorDecl>(MD)) + CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs); + // Start defining the function. StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, SourceLocation()); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index ce2c9b05c47..46e2edd9169 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -694,16 +694,19 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, QualType ResTy = FD->getResultType(); CurGD = GD; - const CXXMethodDecl *MD; - if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) { + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD && MD->isInstance()) { if (CGM.getCXXABI().HasThisReturn(GD)) ResTy = MD->getThisType(getContext()); - CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args); + CGM.getCXXABI().buildThisParam(*this, Args); } for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) Args.push_back(FD->getParamDecl(i)); + if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))) + CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args); + SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); CurEHLocation = BodyRange.getEnd(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2ddb1b9460d..6c00b2a6b4c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2492,6 +2492,7 @@ private: std::string &ConstraintStr, SourceLocation Loc); +public: /// EmitCallArgs - Emit call arguments for a function. template <typename T> void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, @@ -2565,6 +2566,7 @@ private: CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, bool ForceColumnInfo); +private: const TargetCodeGenInfo &getTargetHooks() const { return CGM.getTargetCodeGenInfo(); } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index bb8b5362025..b5dc8195117 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -136,18 +136,15 @@ public: void EmitCXXDestructors(const CXXDestructorDecl *D); - void BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params); + void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, + FunctionArgList &Params); void EmitInstanceFunctionProlog(CodeGenFunction &CGF); - void EmitConstructorCall(CodeGenFunction &CGF, - const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, bool Delegating, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); + unsigned addImplicitConstructorArgs(CodeGenFunction &CGF, + const CXXConstructorDecl *D, + CXXCtorType Type, bool ForVirtualBase, + bool Delegating, CallArgList &Args); void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, @@ -801,18 +798,19 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, /// The generic ABI passes 'this', plus a VTT if it's initializing a /// base subobject. -void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys) { +void +ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, + CXXCtorType Type, CanQualType &ResTy, + SmallVectorImpl<CanQualType> &ArgTys) { ASTContext &Context = getContext(); - // 'this' parameter is already there, as well as 'this' return if - // HasThisReturn(GlobalDecl(Ctor, Type)) is true + // All parameters are already in place except VTT, which goes after 'this'. + // These are Clang types, so we don't need to worry about sret yet. // Check if we need to add a VTT parameter (which has type void **). if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) - ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); + ArgTys.insert(ArgTys.begin() + 1, + Context.getPointerType(Context.VoidPtrTy)); } void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) { @@ -863,14 +861,11 @@ void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting)); } -void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params) { - /// Create the 'this' variable. - BuildThisParam(CGF, Params); - +void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, + QualType &ResTy, + FunctionArgList &Params) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); - assert(MD->isInstance()); + assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); // Check if we need a VTT parameter as well. if (NeedsVTTParameter(CGF.CurGD)) { @@ -881,7 +876,7 @@ void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, ImplicitParamDecl *VTTDecl = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), &Context.Idents.get("vtt"), T); - Params.push_back(VTTDecl); + Params.insert(Params.begin() + 1, VTTDecl); getStructorImplicitParamDecl(CGF) = VTTDecl; } } @@ -908,21 +903,19 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); } -void ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, - const CXXConstructorDecl *D, - CXXCtorType Type, - bool ForVirtualBase, bool Delegating, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) { - llvm::Value *VTT = CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, - Delegating); - QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); - llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); +unsigned ItaniumCXXABI::addImplicitConstructorArgs( + CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, + bool ForVirtualBase, bool Delegating, CallArgList &Args) { + if (!NeedsVTTParameter(GlobalDecl(D, Type))) + return 0; - // FIXME: Provide a source location here. - CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, - VTT, VTTTy, ArgBeg, ArgEnd); + // 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, /*needscopy=*/false)); + return 1; // Added one arg. } void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 46a9256a32e..62b7f430221 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -140,21 +140,18 @@ public: GlobalDecl GD, llvm::Value *This); - void BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params); + void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, + FunctionArgList &Params); llvm::Value *adjustThisParameterInVirtualFunctionPrologue( CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This); void EmitInstanceFunctionProlog(CodeGenFunction &CGF); - void EmitConstructorCall(CodeGenFunction &CGF, - const CXXConstructorDecl *D, CXXCtorType Type, - bool ForVirtualBase, bool Delegating, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); + unsigned addImplicitConstructorArgs(CodeGenFunction &CGF, + const CXXConstructorDecl *D, + CXXCtorType Type, bool ForVirtualBase, + bool Delegating, CallArgList &Args); void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, @@ -450,16 +447,20 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { return isa<CXXConstructorDecl>(GD.getDecl()); } -void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys) { - // 'this' parameter and 'this' return are already in place +void MicrosoftCXXABI::BuildConstructorSignature( + const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy, + SmallVectorImpl<CanQualType> &ArgTys) { + + // All parameters are already in place except is_most_derived, which goes + // after 'this' if it's variadic and last if it's not. const CXXRecordDecl *Class = Ctor->getParent(); + const FunctionProtoType *FPT = Ctor->getType()->castAs<FunctionProtoType>(); if (Class->getNumVBases()) { - // Constructors of classes with virtual bases take an implicit parameter. - ArgTys.push_back(CGM.getContext().IntTy); + if (FPT->isVariadic()) + ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy); + else + ArgTys.push_back(CGM.getContext().IntTy); } } @@ -682,20 +683,25 @@ static bool IsDeletingDtor(GlobalDecl GD) { return false; } -void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params) { - BuildThisParam(CGF, Params); - +void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF, + QualType &ResTy, + FunctionArgList &Params) { ASTContext &Context = getContext(); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); + assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)); if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { ImplicitParamDecl *IsMostDerived = ImplicitParamDecl::Create(Context, 0, CGF.CurGD.getDecl()->getLocation(), &Context.Idents.get("is_most_derived"), Context.IntTy); - Params.push_back(IsMostDerived); + // The 'most_derived' parameter goes second if the ctor is variadic and last + // if it's not. Dtors can't be variadic. + const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); + if (FPT->isVariadic()) + Params.insert(Params.begin() + 1, IsMostDerived); + else + Params.push_back(IsMostDerived); getStructorImplicitParamDecl(CGF) = IsMostDerived; } else if (IsDeletingDtor(CGF.CurGD)) { ImplicitParamDecl *ShouldDelete @@ -788,27 +794,29 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { } } -void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF, - const CXXConstructorDecl *D, - CXXCtorType Type, - bool ForVirtualBase, - bool Delegating, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) { +unsigned MicrosoftCXXABI::addImplicitConstructorArgs( + CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, + bool ForVirtualBase, bool Delegating, CallArgList &Args) { assert(Type == Ctor_Complete || Type == Ctor_Base); - llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Ctor_Complete); - llvm::Value *ImplicitParam = 0; - QualType ImplicitParamTy; - if (D->getParent()->getNumVBases()) { - ImplicitParam = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete); - ImplicitParamTy = getContext().IntTy; + // Check if we need a 'most_derived' parameter. + if (!D->getParent()->getNumVBases()) + return 0; + + // Add the 'most_derived' argument second if we are variadic or last if not. + const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); + llvm::Value *MostDerivedArg = + llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete); + RValue RV = RValue::get(MostDerivedArg); + if (MostDerivedArg) { + if (FPT->isVariadic()) + Args.insert(Args.begin() + 1, + CallArg(RV, getContext().IntTy, /*needscopy=*/false)); + else + Args.add(RV, getContext().IntTy); } - // FIXME: Provide a source location here. - CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, - ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd); + return 1; // Added one arg. } void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, |