summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h43
-rw-r--r--clang/lib/CodeGen/CGCall.cpp35
-rw-r--r--clang/lib/CodeGen/CGClass.cpp13
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp26
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp16
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h4
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp123
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp72
10 files changed, 208 insertions, 135 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index cfcba090cc3..04bc54b6bfc 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -97,12 +97,8 @@ public:
return *MangleCtx;
}
- /// 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.
+ /// Returns true if the given instance method is one of the
+ /// kinds that the ABI says returns 'this'.
virtual bool HasThisReturn(GlobalDecl GD) const { return false; }
/// Returns true if the given record type should be returned indirectly.
@@ -218,10 +214,10 @@ public:
const CXXRecordDecl *BaseClassDecl) = 0;
/// Build the signature of the given constructor variant by adding
- /// 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).
+ /// 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.
///
/// If there are ever any ABIs where the implicit parameters are
/// intermixed with the formal parameters, we can address those
@@ -235,10 +231,9 @@ public:
const CXXRecordDecl *RD);
/// Build the signature of the given destructor variant by adding
- /// 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).
+ /// 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).
virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
@@ -249,8 +244,7 @@ public:
/// possibly some 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.
+ /// initialized with the formal return type of the function.
virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) = 0;
@@ -259,20 +253,21 @@ public:
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
/// Emit the constructor call. Return the function that is called.
- virtual void EmitConstructorCall(CodeGenFunction &CGF,
+ virtual llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type,
- bool ForVirtualBase, bool Delegating,
+ CXXCtorType Type, bool ForVirtualBase,
+ bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) = 0;
/// Emit the ABI-specific virtual destructor call.
- virtual void EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- llvm::Value *This) = 0;
+ virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This) = 0;
/// Emit any tables needed to implement virtual inheritance. For Itanium,
/// this emits virtual table tables. For the MSVC++ ABI, this emits virtual
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index f74ae391205..80446393d5b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -200,10 +200,7 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
CXXCtorType ctorKind) {
SmallVector<CanQualType, 16> argTypes;
argTypes.push_back(GetThisType(Context, D->getParent()));
-
- GlobalDecl GD(D, ctorKind);
- CanQualType resultType =
- TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
+ CanQualType resultType = Context.VoidTy;
TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
@@ -228,10 +225,7 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType dtorKind) {
SmallVector<CanQualType, 2> argTypes;
argTypes.push_back(GetThisType(Context, D->getParent()));
-
- GlobalDecl GD(D, dtorKind);
- CanQualType resultType =
- TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
+ CanQualType resultType = Context.VoidTy;
TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);
@@ -1639,6 +1633,18 @@ 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.
@@ -1735,6 +1741,19 @@ 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 cceae6873a6..a32c152fee2 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1662,8 +1662,11 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
}
// Non-trivial constructors are handled in an ABI-specific manner.
- CGM.getCXXABI().EmitConstructorCall(*this, D, Type, ForVirtualBase,
- Delegating, This, ArgBeg, ArgEnd);
+ 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;
}
void
@@ -1755,6 +1758,9 @@ 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 {
@@ -1821,6 +1827,9 @@ 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/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 438657ae223..60a70f8e07f 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -280,15 +280,16 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;
- llvm::Value *Callee;
+ llvm::Value *Callee;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
- assert(CE->arg_begin() == CE->arg_end() &&
- "Destructor shouldn't have explicit parameters");
- assert(ReturnValue.isNull() && "Destructor shouldn't have return value");
if (UseVirtualCall) {
- CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor, Dtor_Complete,
- CE->getExprLoc(), This);
+ assert(CE->arg_begin() == CE->arg_end() &&
+ "Virtual destructor shouldn't have explicit parameters");
+ return CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor,
+ Dtor_Complete,
+ CE->getExprLoc(),
+ ReturnValue, This);
} else {
if (getLangOpts().AppleKext &&
MD->isVirtual() &&
@@ -301,16 +302,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);
}
- EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/0, QualType(), 0, 0);
}
- return RValue::get(0);
- }
-
- if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
+ } else if (const CXXConstructorDecl *Ctor =
+ dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
} else if (UseVirtualCall) {
- Callee = BuildVirtualCall(MD, This, Ty);
+ Callee = BuildVirtualCall(MD, This, Ty);
} else {
if (getLangOpts().AppleKext &&
MD->isVirtual() &&
@@ -1416,7 +1413,8 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
// FIXME: Provide a source location here.
CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
CGF.CGM.getCXXABI().EmitVirtualDestructorCall(CGF, Dtor, DtorType,
- SourceLocation(), Ptr);
+ SourceLocation(),
+ ReturnValueSlot(), Ptr);
if (UseGlobalDelete) {
CGF.PopCleanupBlock();
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 9c4a5e0cdad..e15639d31dd 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -287,9 +287,8 @@ 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 e8469e64802..297fc655e44 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -42,7 +42,8 @@ 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), DidCallStackSave(false),
+ DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0),
+ DidCallStackSave(false),
IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),
NumReturnExprs(0), NumSimpleReturnExprs(0),
CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
@@ -661,12 +662,8 @@ 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()) {
- if (CGM.getCXXABI().HasThisReturn(GD))
- ResTy = MD->getThisType(getContext());
+ if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
- }
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
Args.push_back(FD->getParamDecl(i));
@@ -675,6 +672,10 @@ 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());
@@ -726,6 +727,9 @@ 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 b7e2086c75a..7b18edf3215 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -798,6 +798,10 @@ 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 3298d5a0899..efff4b118d5 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -722,14 +722,6 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD,
if (!IsIncompleteFunction)
SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
- if (getCXXABI().HasThisReturn(GD)) {
- assert(!F->arg_empty() &&
- F->arg_begin()->getType()
- ->canLosslesslyBitCastTo(F->getReturnType()) &&
- "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 51c1dc5e590..36b3da58b99 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -119,17 +119,20 @@ public:
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
- void EmitConstructorCall(CodeGenFunction &CGF,
- const CXXConstructorDecl *D, CXXCtorType Type,
- bool ForVirtualBase, bool Delegating,
+ 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);
- void EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, SourceLocation CallLoc,
- llvm::Value *This);
+ RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This);
void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes Linkage,
const CXXRecordDecl *RD);
@@ -165,11 +168,21 @@ class ARMCXXABI : public ItaniumCXXABI {
public:
ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
- bool HasThisReturn(GlobalDecl GD) const {
- return (isa<CXXConstructorDecl>(GD.getDecl()) || (
- isa<CXXDestructorDecl>(GD.getDecl()) &&
- GD.getDtorType() != Dtor_Deleting));
- }
+ 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);
void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
@@ -181,6 +194,15 @@ 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)));
+ }
};
}
@@ -735,14 +757,22 @@ void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
- // 'this' parameter is already there, as well as 'this' return if
- // HasThisReturn(GlobalDecl(Ctor, Type)) is true
+ // 'this' is already there.
// 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,
@@ -751,14 +781,25 @@ void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
- // 'this' parameter is already there, as well as 'this' return if
- // HasThisReturn(GlobalDecl(Dtor, Type)) is true
+ // 'this' is already there.
// 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) {
@@ -782,6 +823,16 @@ 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);
@@ -792,23 +843,21 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
"vtt");
}
+}
- /// 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
+void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
+
+ /// Initialize the return slot to 'this' at the start of the
+ /// function.
if (HasThisReturn(CGF.CurGD))
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
}
-void ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
+llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type,
- bool ForVirtualBase, bool Delegating,
+ CXXCtorType Type, bool ForVirtualBase,
+ bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
@@ -818,15 +867,17 @@ void 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);
+ CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
+ VTT, VTTTy, ArgBeg, ArgEnd);
+ return Callee;
}
-void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- llvm::Value *This) {
+RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This) {
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
const CGFunctionInfo *FInfo
@@ -834,8 +885,8 @@ void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, DtorType, This, Ty);
- CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/0, QualType(), 0, 0);
+ return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
+ /*ImplicitParam=*/0, QualType(), 0, 0);
}
void ItaniumCXXABI::EmitVirtualInheritanceTables(
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 1dca209ed4f..1ff794695cb 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -30,8 +30,6 @@ 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();
@@ -76,17 +74,20 @@ public:
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
- void EmitConstructorCall(CodeGenFunction &CGF,
- const CXXConstructorDecl *D, CXXCtorType Type,
- bool ForVirtualBase, bool Delegating,
+ 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);
-
- void EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, SourceLocation CallLoc,
- llvm::Value *This);
+
+ RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This);
void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes Linkage,
const CXXRecordDecl *RD);
@@ -129,6 +130,7 @@ public:
llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
llvm::Value *allocPtr,
CharUnits cookieSize);
+ static bool needThisReturn(GlobalDecl GD);
private:
llvm::Constant *getZeroInt() {
@@ -312,15 +314,19 @@ MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
}
-bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
- return isa<CXXConstructorDecl>(GD.getDecl());
+bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
+ const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
+ return isa<CXXConstructorDecl>(MD);
}
void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
- // 'this' parameter and 'this' return are already in place
+ // 'this' is already in place
+
+ // Ctor returns this ptr
+ ResTy = ArgTys[0];
const CXXRecordDecl *Class = Ctor->getParent();
if (Class->getNumVBases()) {
@@ -378,7 +384,6 @@ void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CanQualType &ResTy,
SmallVectorImpl<CanQualType> &ArgTys) {
// 'this' is already in place
-
// TODO: 'for base' flag
if (Type == Dtor_Deleting) {
@@ -399,6 +404,9 @@ 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());
@@ -423,17 +431,9 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
EmitThisParam(CGF);
-
- /// 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))
+ if (needThisReturn(CGF.CurGD)) {
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
+ }
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
@@ -455,10 +455,9 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
}
}
-void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
+llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
const CXXConstructorDecl *D,
- CXXCtorType Type,
- bool ForVirtualBase,
+ CXXCtorType Type, bool ForVirtualBase,
bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
@@ -475,14 +474,17 @@ void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
// FIXME: Provide a source location here.
CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,
- ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd);
+ ImplicitParam, ImplicitParamTy,
+ ArgBeg, ArgEnd);
+ return Callee;
}
-void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- SourceLocation CallLoc,
- llvm::Value *This) {
+RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ SourceLocation CallLoc,
+ ReturnValueSlot ReturnValue,
+ llvm::Value *This) {
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
// We have only one destructor in the vftable but can get both behaviors
@@ -497,8 +499,8 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
= llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()),
DtorType == Dtor_Deleting);
- CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
- ImplicitParam, Context.BoolTy, 0, 0);
+ return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This,
+ ImplicitParam, Context.BoolTy, 0, 0);
}
const VBTableVector &
OpenPOWER on IntegriCloud