summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-08-29 21:43:29 +0000
committerReid Kleckner <reid@kleckner.net>2014-08-29 21:43:29 +0000
commitc34735148f00ca26ebf29eb5a3ec8a42075509e0 (patch)
tree085400f10364f0ed1839fc4894c8cf25b169e414 /clang/lib
parentdccd0cbec3d6eb835362d921c6bd33a5cc0a920f (diff)
downloadbcm5719-llvm-c34735148f00ca26ebf29eb5a3ec8a42075509e0.tar.gz
bcm5719-llvm-c34735148f00ca26ebf29eb5a3ec8a42075509e0.zip
Make all virtual member pointers use variadic musttail calls
This avoids encoding information about the function prototype into the thunk at the cost of some function prototype bitcast gymnastics. Fixes PR20653. llvm-svn: 216782
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp14
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.h1
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp37
3 files changed, 40 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index aa7de709cb5..ce16d3bd64c 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -332,6 +332,20 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
return arrangeFunctionDeclaration(FD);
}
+/// Arrange a thunk that takes 'this' as the first parameter followed by
+/// varargs. Return a void pointer, regardless of the actual return type.
+/// The body of the thunk will end in a musttail call to a function of the
+/// correct type, and the caller will bitcast the function to the correct
+/// prototype.
+const CGFunctionInfo &
+CodeGenTypes::arrangeMSMemberPointerThunk(const CXXMethodDecl *MD) {
+ assert(MD->isVirtual() && "only virtual memptrs have thunks");
+ CanQual<FunctionProtoType> FTP = GetFormalType(MD);
+ CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
+ return arrangeLLVMFunctionInfo(Context.VoidTy, false, ArgTys,
+ FTP->getExtInfo(), RequiredArgs(1));
+}
+
/// Arrange a call as unto a free function, except possibly with an
/// additional number of formal parameters considered required.
static const CGFunctionInfo &
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 51466c6e2c7..91727e3d5e2 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -207,6 +207,7 @@ public:
const CGFunctionInfo &arrangeCXXMethodCall(const CallArgList &args,
const FunctionProtoType *type,
RequiredArgs required);
+ const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index ca1196dbbf7..9fa7f339ad3 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1434,6 +1434,9 @@ MicrosoftCXXABI::enumerateVBTables(const CXXRecordDecl *RD) {
llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
const MicrosoftVTableContext::MethodVFTableLocation &ML) {
+ assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) &&
+ "can't form pointers to ctors or virtual dtors");
+
// Calculate the mangled name.
SmallString<256> ThunkName;
llvm::raw_svector_ostream Out(ThunkName);
@@ -1445,7 +1448,7 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
return cast<llvm::Function>(GV);
// Create the llvm::Function.
- const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(MD);
+ const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSMemberPointerThunk(MD);
llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
llvm::Function *ThunkFn =
llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
@@ -1464,18 +1467,28 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
// Start codegen.
CodeGenFunction CGF(CGM);
- CGF.StartThunk(ThunkFn, MD, FnInfo);
+ CGF.CurGD = GlobalDecl(MD);
+ CGF.CurFuncIsThunk = true;
+
+ // Build FunctionArgs, but only include the implicit 'this' parameter
+ // declaration.
+ FunctionArgList FunctionArgs;
+ buildThisParam(CGF, FunctionArgs);
+
+ // Start defining the function.
+ CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
+ FunctionArgs, MD->getLocation(), SourceLocation());
+ EmitThisParam(CGF);
// Load the vfptr and then callee from the vftable. The callee should have
// adjusted 'this' so that the vfptr is at offset zero.
- llvm::Value *This = CGF.LoadCXXThis();
- llvm::Value *VTable =
- CGF.GetVTablePtr(This, ThunkTy->getPointerTo()->getPointerTo());
+ llvm::Value *VTable = CGF.GetVTablePtr(
+ getThisValue(CGF), ThunkTy->getPointerTo()->getPointerTo());
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
llvm::Value *Callee = CGF.Builder.CreateLoad(VFuncPtr);
- CGF.EmitCallAndReturnForThunk(Callee, 0);
+ CGF.EmitMustTailThunk(MD, getThisValue(CGF), Callee);
return ThunkFn;
}
@@ -1935,8 +1948,8 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
CodeGenTypes &Types = CGM.getTypes();
llvm::Constant *FirstField;
+ const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
if (!MD->isVirtual()) {
- const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
llvm::Type *Ty;
// Check whether the function has a computable LLVM signature.
if (Types.isFuncTypeConvertible(FPT)) {
@@ -1952,14 +1965,14 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
} else {
MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
- if (MD->isVariadic()) {
- CGM.ErrorUnsupported(MD, "pointer to variadic virtual member function");
- FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
- } else if (!CGM.getTypes().isFuncTypeConvertible(
- MD->getType()->castAs<FunctionType>())) {
+ if (!CGM.getTypes().isFuncTypeConvertible(
+ MD->getType()->castAs<FunctionType>())) {
CGM.ErrorUnsupported(MD, "pointer to virtual member function with "
"incomplete return or parameter type");
FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+ } else if (FPT->getCallConv() == CC_X86FastCall) {
+ CGM.ErrorUnsupported(MD, "pointer to fastcall virtual member function");
+ FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
} else if (ML.VBase) {
CGM.ErrorUnsupported(MD, "pointer to virtual member function overriding "
"member function in virtual base class");
OpenPOWER on IntegriCloud