diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 41 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 35 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 16 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 107 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 63 |
9 files changed, 116 insertions, 175 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index f64a633d25e..899e5e7b258 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -97,8 +97,12 @@ public: return *MangleCtx; } - /// Returns true if the given instance method is one of the - /// kinds that the ABI says returns 'this'. + /// Returns true if the given constructor or destructor is one of the + /// kinds that the ABI says returns 'this' (only applies when called + /// non-virtually for destructors). + /// + /// There currently is no way to indicate if a destructor returns 'this' + /// when called virtually, and code generation does not support the case. virtual bool HasThisReturn(GlobalDecl GD) const { return false; } /// Returns true if the given record type should be returned indirectly. @@ -214,10 +218,10 @@ public: const CXXRecordDecl *BaseClassDecl) = 0; /// Build the signature of the given constructor variant by adding - /// any required parameters. For convenience, ResTy has been - /// initialized to 'void', and ArgTys has been initialized with the - /// type of 'this' (although this may be changed by the ABI) and - /// will have the formal parameters added to it afterwards. + /// any required parameters. For convenience, ArgTys has been initialized + /// with the type of 'this' and ResTy has been initialized with the type of + /// 'this' if HasThisReturn(GlobalDecl(Ctor, T)) is true or 'void' otherwise + /// (although both may be changed by the ABI). /// /// If there are ever any ABIs where the implicit parameters are /// intermixed with the formal parameters, we can address those @@ -230,9 +234,10 @@ public: virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF); /// Build the signature of the given destructor variant by adding - /// any required parameters. For convenience, ResTy has been - /// initialized to 'void' and ArgTys has been initialized with the - /// type of 'this' (although this may be changed by the ABI). + /// any required parameters. For convenience, ArgTys has been initialized + /// with the type of 'this' and ResTy has been initialized with the type of + /// 'this' if HasThisReturn(GlobalDecl(Dtor, T)) is true or 'void' otherwise + /// (although both may be changed by the ABI). virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor, CXXDtorType T, CanQualType &ResTy, @@ -243,7 +248,8 @@ public: /// possibly some extra data for constructors and destructors. /// /// ABIs may also choose to override the return type, which has been - /// initialized with the formal return type of the function. + /// 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; @@ -252,13 +258,14 @@ public: virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0; /// Emit the constructor call. Return the function that is called. - virtual llvm::Value *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; + virtual RValue EmitConstructorCall(CodeGenFunction &CGF, + const CXXConstructorDecl *D, + CXXCtorType Type, + bool ForVirtualBase, bool Delegating, + ReturnValueSlot ReturnValue, + llvm::Value *This, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd) = 0; /// Emit the ABI-specific virtual destructor call. virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 80446393d5b..f74ae391205 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -200,7 +200,10 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D, CXXCtorType ctorKind) { SmallVector<CanQualType, 16> argTypes; argTypes.push_back(GetThisType(Context, D->getParent())); - CanQualType resultType = Context.VoidTy; + + GlobalDecl GD(D, ctorKind); + CanQualType resultType = + TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy; TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes); @@ -225,7 +228,10 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D, CXXDtorType dtorKind) { SmallVector<CanQualType, 2> argTypes; argTypes.push_back(GetThisType(Context, D->getParent())); - CanQualType resultType = Context.VoidTy; + + GlobalDecl GD(D, dtorKind); + CanQualType resultType = + TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy; TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes); @@ -1633,18 +1639,6 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { return store; } -/// Check whether 'this' argument of a callsite matches 'this' of the caller. -static bool checkThisPointer(llvm::Value *ThisArg, llvm::Value *This) { - if (ThisArg == This) - return true; - // Check whether ThisArg is a bitcast of This. - llvm::BitCastInst *Bitcast; - if ((Bitcast = dyn_cast<llvm::BitCastInst>(ThisArg)) && - Bitcast->getOperand(0) == This) - return true; - return false; -} - void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc) { // Functions with no result always return void. @@ -1741,19 +1735,6 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, llvm_unreachable("Invalid ABI kind for return argument"); } - // If this function returns 'this', the last instruction is a CallInst - // that returns 'this', and 'this' argument of the CallInst points to - // the same object as CXXThisValue, use the return value from the CallInst. - // We will not need to keep 'this' alive through the callsite. It also enables - // optimizations in the backend, such as tail call optimization. - if (CalleeWithThisReturn && CGM.getCXXABI().HasThisReturn(CurGD)) { - llvm::BasicBlock *IP = Builder.GetInsertBlock(); - llvm::CallInst *Callsite; - if (!IP->empty() && (Callsite = dyn_cast<llvm::CallInst>(&IP->back())) && - Callsite->getCalledFunction() == CalleeWithThisReturn && - checkThisPointer(Callsite->getOperand(0), CXXThisValue)) - RV = Builder.CreateBitCast(Callsite, RetAI.getCoerceToType()); - } llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid(); if (!RetDbgLoc.isUnknown()) Ret->setDebugLoc(RetDbgLoc); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 9d08d1c7f7a..88f5cf9e6b5 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1661,11 +1661,9 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, } // Non-trivial constructors are handled in an ABI-specific manner. - llvm::Value *Callee = CGM.getCXXABI().EmitConstructorCall(*this, D, Type, - ForVirtualBase, Delegating, This, ArgBeg, ArgEnd); - if (CGM.getCXXABI().HasThisReturn(CurGD) && - CGM.getCXXABI().HasThisReturn(GlobalDecl(D, Type))) - CalleeWithThisReturn = Callee; + CGM.getCXXABI().EmitConstructorCall(*this, D, Type, + ForVirtualBase, Delegating, + ReturnValueSlot(), This, ArgBeg, ArgEnd); } void @@ -1757,9 +1755,6 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(Ctor, CtorType); EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor, CtorType), Callee, ReturnValueSlot(), DelegateArgs, Ctor); - if (CGM.getCXXABI().HasThisReturn(CurGD) && - CGM.getCXXABI().HasThisReturn(GlobalDecl(Ctor, CtorType))) - CalleeWithThisReturn = Callee; } namespace { @@ -1826,9 +1821,6 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This, VTT, getContext().getPointerType(getContext().VoidPtrTy), 0, 0); - if (CGM.getCXXABI().HasThisReturn(CurGD) && - CGM.getCXXABI().HasThisReturn(GlobalDecl(DD, Type))) - CalleeWithThisReturn = Callee; } namespace { diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index b1072b47213..d1168770ddb 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -287,8 +287,9 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, const ThunkInfo &Thunk) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); - QualType ResultType = FPT->getResultType(); QualType ThisType = MD->getThisType(getContext()); + QualType ResultType = + CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType(); FunctionArgList FunctionArgs; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 297fc655e44..e8469e64802 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -42,8 +42,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) AutoreleaseResult(false), BlockInfo(0), BlockPointer(0), LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1), FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), - DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0), - DidCallStackSave(false), + DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), NumReturnExprs(0), NumSimpleReturnExprs(0), CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), @@ -662,8 +661,12 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, QualType ResTy = FD->getResultType(); CurGD = GD; - if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance()) + const CXXMethodDecl *MD; + if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) { + if (CGM.getCXXABI().HasThisReturn(GD)) + ResTy = MD->getThisType(getContext()); CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args); + } for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) Args.push_back(FD->getParamDecl(i)); @@ -672,10 +675,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); CurEHLocation = BodyRange.getEnd(); - // CalleeWithThisReturn keeps track of the last callee inside this function - // that returns 'this'. Before starting the function, we set it to null. - CalleeWithThisReturn = 0; - // Emit the standard function prologue. StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin()); @@ -727,9 +726,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // Emit the standard function epilogue. FinishFunction(BodyRange.getEnd()); - // CalleeWithThisReturn keeps track of the last callee inside this function - // that returns 'this'. After finishing the function, we set it to null. - CalleeWithThisReturn = 0; // If we haven't marked the function nothrow through other means, do // a quick pass now to see if we can. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 508e6a4ec34..9071e07ac90 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -798,10 +798,6 @@ private: CGDebugInfo *DebugInfo; bool DisableDebugInfo; - /// If the current function returns 'this', use the field to keep track of - /// the callee that returns 'this'. - llvm::Value *CalleeWithThisReturn; - /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid /// calling llvm.stacksave for multiple VLAs in the same scope. bool DidCallStackSave; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 824d2a04662..d76fee5c844 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -717,6 +717,14 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, if (!IsIncompleteFunction) SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); + if (getCXXABI().HasThisReturn(GD)) { + llvm::Type *RetTy = F->getReturnType(); + assert(!F->arg_empty() && + F->arg_begin()->getType()->canLosslesslyBitCastTo(RetTy) && + "unexpected this return"); + F->addAttribute(1, llvm::Attribute::Returned); + } + // Only a few attributes are set on declarations; these may later be // overridden by a definition. diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 6cf95b5ce99..72284007381 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -119,13 +119,14 @@ public: void EmitInstanceFunctionProlog(CodeGenFunction &CGF); - llvm::Value *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); + RValue EmitConstructorCall(CodeGenFunction &CGF, + const CXXConstructorDecl *D, + CXXCtorType Type, + bool ForVirtualBase, bool Delegating, + ReturnValueSlot ReturnValue, + llvm::Value *This, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd); RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, @@ -165,21 +166,11 @@ class ARMCXXABI : public ItaniumCXXABI { public: ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} - void BuildConstructorSignature(const CXXConstructorDecl *Ctor, - CXXCtorType T, - CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys); - - void BuildDestructorSignature(const CXXDestructorDecl *Dtor, - CXXDtorType T, - CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys); - - void BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params); - - void EmitInstanceFunctionProlog(CodeGenFunction &CGF); + bool HasThisReturn(GlobalDecl GD) const { + return (isa<CXXConstructorDecl>(GD.getDecl()) || ( + isa<CXXDestructorDecl>(GD.getDecl()) && + GD.getDtorType() != Dtor_Deleting)); + } void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); @@ -191,15 +182,6 @@ public: QualType ElementType); llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr, CharUnits cookieSize); - - /// \brief Returns true if the given instance method is one of the - /// kinds that the ARM ABI says returns 'this'. - bool HasThisReturn(GlobalDecl GD) const { - const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(GD.getDecl()); - if (!MD) return false; - return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) || - (isa<CXXConstructorDecl>(MD))); - } }; } @@ -754,22 +736,14 @@ void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, SmallVectorImpl<CanQualType> &ArgTys) { ASTContext &Context = getContext(); - // 'this' is already there. + // 'this' parameter is already there, as well as 'this' return if + // HasThisReturn(GlobalDecl(Ctor, Type)) is true // 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)); } -/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. -void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, - CXXCtorType Type, - CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys) { - ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); - ResTy = ArgTys[0]; -} - /// The generic ABI passes 'this', plus a VTT if it's destroying a /// base subobject. void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, @@ -778,25 +752,14 @@ void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, SmallVectorImpl<CanQualType> &ArgTys) { ASTContext &Context = getContext(); - // 'this' is already there. + // 'this' parameter is already there, as well as 'this' return if + // HasThisReturn(GlobalDecl(Dtor, Type)) is true // Check if we need to add a VTT parameter (which has type void **). if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); } -/// The ARM ABI does the same as the Itanium ABI, but returns 'this' -/// for non-deleting destructors. -void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, - CXXDtorType Type, - CanQualType &ResTy, - SmallVectorImpl<CanQualType> &ArgTys) { - ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); - - if (Type != Dtor_Deleting) - ResTy = ArgTys[0]; -} - void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { @@ -820,16 +783,6 @@ void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, } } -void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, - QualType &ResTy, - FunctionArgList &Params) { - ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); - - // Return 'this' from certain constructors and destructors. - if (HasThisReturn(CGF.CurGD)) - ResTy = Params[0]->getType(); -} - void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { /// Initialize the 'this' slot. EmitThisParam(CGF); @@ -840,21 +793,24 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), "vtt"); } -} -void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { - ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); - - /// Initialize the return slot to 'this' at the start of the - /// function. + /// If this is a function that the ABI specifies returns 'this', initialize + /// the return slot to 'this' at the start of the function. + /// + /// Unlike the setting of return types, this is done within the ABI + /// implementation instead of by clients of CGCXXABI because: + /// 1) getThisValue is currently protected + /// 2) in theory, an ABI could implement 'this' returns some other way; + /// HasThisReturn only specifies a contract, not the implementation if (HasThisReturn(CGF.CurGD)) CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); } -llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, +RValue ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, const CXXConstructorDecl *D, - CXXCtorType Type, bool ForVirtualBase, - bool Delegating, + CXXCtorType Type, + bool ForVirtualBase, bool Delegating, + ReturnValueSlot ReturnValue, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { @@ -864,9 +820,8 @@ llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); // FIXME: Provide a source location here. - CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, - VTT, VTTTy, ArgBeg, ArgEnd); - return Callee; + return CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValue, + This, VTT, VTTTy, ArgBeg, ArgEnd); } RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 1bb2c55f559..e6eca28b29f 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -28,6 +28,8 @@ class MicrosoftCXXABI : public CGCXXABI { public: MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {} + bool HasThisReturn(GlobalDecl GD) const; + bool isReturnTypeIndirect(const CXXRecordDecl *RD) const { // Structures that are not C++03 PODs are always indirect. return !RD->isPOD(); @@ -71,13 +73,14 @@ public: void EmitInstanceFunctionProlog(CodeGenFunction &CGF); - llvm::Value *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); + RValue EmitConstructorCall(CodeGenFunction &CGF, + const CXXConstructorDecl *D, + CXXCtorType Type, + bool ForVirtualBase, bool Delegating, + ReturnValueSlot ReturnValue, + llvm::Value *This, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd); RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, @@ -124,7 +127,6 @@ public: llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr, CharUnits cookieSize); - static bool needThisReturn(GlobalDecl GD); private: llvm::Constant *getZeroInt() { @@ -299,19 +301,15 @@ MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase); } -bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) { - const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl()); - return isa<CXXConstructorDecl>(MD); +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' is already in place - - // Ctor returns this ptr - ResTy = ArgTys[0]; + // 'this' parameter and 'this' return are already in place const CXXRecordDecl *Class = Ctor->getParent(); if (Class->getNumVBases()) { @@ -346,6 +344,7 @@ void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, CanQualType &ResTy, SmallVectorImpl<CanQualType> &ArgTys) { // 'this' is already in place + // TODO: 'for base' flag if (Type == Dtor_Deleting) { @@ -366,9 +365,6 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { BuildThisParam(CGF, Params); - if (needThisReturn(CGF.CurGD)) { - ResTy = Params[0]->getType(); - } ASTContext &Context = getContext(); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); @@ -393,9 +389,17 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { EmitThisParam(CGF); - if (needThisReturn(CGF.CurGD)) { + + /// If this is a function that the ABI specifies returns 'this', initialize + /// the return slot to 'this' at the start of the function. + /// + /// Unlike the setting of return types, this is done within the ABI + /// implementation instead of by clients of CGCXXABI because: + /// 1) getThisValue is currently protected + /// 2) in theory, an ABI could implement 'this' returns some other way; + /// HasThisReturn only specifies a contract, not the implementation + if (HasThisReturn(CGF.CurGD)) CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); - } const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { @@ -417,11 +421,13 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { } } -llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF, - const CXXConstructorDecl *D, - CXXCtorType Type, bool ForVirtualBase, - bool Delegating, - llvm::Value *This, +RValue MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF, + const CXXConstructorDecl *D, + CXXCtorType Type, + bool ForVirtualBase, + bool Delegating, + ReturnValueSlot ReturnValue, + llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { assert(Type == Ctor_Complete || Type == Ctor_Base); @@ -435,10 +441,9 @@ llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF, } // FIXME: Provide a source location here. - CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, - ImplicitParam, ImplicitParamTy, - ArgBeg, ArgEnd); - return Callee; + return CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValue, + This, ImplicitParam, ImplicitParamTy, + ArgBeg, ArgEnd); } RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, |