[cfe-commits] r111752 - in /cfe/trunk/lib/CodeGen: CGCXX.cpp CGCXXABI.h CGExprCXX.cpp ItaniumCXXABI.cpp
John McCall
rjmccall at apple.com
Sat Aug 21 17:05:51 PDT 2010
Author: rjmccall
Date: Sat Aug 21 19:05:51 2010
New Revision: 111752
URL: http://llvm.org/viewvc/llvm-project?rev=111752&view=rev
Log:
Extract calls to method pointers out as an ABI routine.
No functionality change.
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGCXXABI.h
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sat Aug 21 19:05:51 2010
@@ -357,3 +357,25 @@
}
CGCXXABI::~CGCXXABI() {}
+
+llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ Diagnostic &Diags = CGF.CGM.getDiags();
+ unsigned DiagID =
+ Diags.getCustomDiagID(Diagnostic::Error,
+ "cannot yet compile member pointer calls in this ABI");
+ Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
+ DiagID);
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+ const llvm::FunctionType *FTy =
+ CGF.CGM.getTypes().GetFunctionType(
+ CGF.CGM.getTypes().getFunctionInfo(RD, FPT),
+ FPT->isVariadic());
+ return llvm::Constant::getNullValue(FTy->getPointerTo());
+}
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sat Aug 21 19:05:51 2010
@@ -15,8 +15,15 @@
#ifndef CLANG_CODEGEN_CXXABI_H
#define CLANG_CODEGEN_CXXABI_H
+namespace llvm {
+ class Value;
+}
+
namespace clang {
+ class MemberPointerType;
+
namespace CodeGen {
+ class CodeGenFunction;
class CodeGenModule;
class MangleContext;
@@ -27,12 +34,19 @@
/// Gets the mangle context.
virtual MangleContext &getMangleContext() = 0;
+
+ virtual llvm::Value *
+ EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
};
/// Creates an instance of a C++ ABI class.
CGCXXABI *CreateARMCXXABI(CodeGenModule &CGM);
CGCXXABI *CreateItaniumCXXABI(CodeGenModule &CGM);
CGCXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM);
+
}
}
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sat Aug 21 19:05:51 2010
@@ -153,17 +153,12 @@
const MemberPointerType *MPT =
MemFnExpr->getType()->getAs<MemberPointerType>();
+
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
- const llvm::FunctionType *FTy =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
- FPT->isVariadic());
-
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-
// Get the member function pointer.
llvm::Value *MemFnPtr = CreateMemTemp(MemFnExpr->getType(), "mem.fn");
EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false);
@@ -175,67 +170,11 @@
This = EmitScalarExpr(BaseExpr);
else
This = EmitLValue(BaseExpr).getAddress();
-
- // Adjust it.
- llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
- Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
-
- llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr");
- Ptr = Builder.CreateGEP(Ptr, Adj, "adj");
-
- This = Builder.CreateBitCast(Ptr, This->getType(), "this");
-
- llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
-
- const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
- llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
-
- // If the LSB in the function pointer is 1, the function pointer points to
- // a virtual function.
- llvm::Value *IsVirtual
- = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1),
- "and");
-
- IsVirtual = Builder.CreateTrunc(IsVirtual,
- llvm::Type::getInt1Ty(VMContext));
+ // Ask the ABI to load the callee. Note that This is modified.
+ llvm::Value *Callee =
+ CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(CGF, This, MemFnPtr, MPT);
- llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual");
- llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual");
- llvm::BasicBlock *FnEnd = createBasicBlock("fn.end");
-
- Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
- EmitBlock(FnVirtual);
-
- const llvm::Type *VTableTy =
- FTy->getPointerTo()->getPointerTo();
-
- llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
- VTable = Builder.CreateLoad(VTable);
-
- VTable = Builder.CreateBitCast(VTable, Int8PtrTy);
- llvm::Value *VTableOffset =
- Builder.CreateSub(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1));
-
- VTable = Builder.CreateGEP(VTable, VTableOffset, "fn");
- VTable = Builder.CreateBitCast(VTable, VTableTy);
-
- llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
-
- EmitBranch(FnEnd);
- EmitBlock(FnNonVirtual);
-
- // If the function is not virtual, just load the pointer.
- llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn");
- NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo());
-
- EmitBlock(FnEnd);
-
- llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
- Callee->reserveOperandSpace(2);
- Callee->addIncoming(VirtualFn, FnVirtual);
- Callee->addIncoming(NonVirtualFn, FnNonVirtual);
-
CallArgList Args;
QualType ThisType =
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=111752&r1=111751&r2=111752&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sat Aug 21 19:05:51 2010
@@ -19,21 +19,32 @@
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "Mangle.h"
+#include <clang/AST/Type.h>
+#include <llvm/Value.h>
using namespace clang;
+using namespace CodeGen;
namespace {
class ItaniumCXXABI : public CodeGen::CGCXXABI {
+protected:
+ CodeGenModule &CGM;
CodeGen::MangleContext MangleCtx;
public:
ItaniumCXXABI(CodeGen::CodeGenModule &CGM) :
- MangleCtx(CGM.getContext(), CGM.getDiags()) { }
+ CGM(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()) { }
CodeGen::MangleContext &getMangleContext() {
return MangleCtx;
}
+
+ llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT);
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -50,3 +61,77 @@
return new ARMCXXABI(CGM);
}
+llvm::Value *
+ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+
+ const llvm::FunctionType *FTy =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+ FPT->isVariadic());
+
+ llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("fn.virtual");
+ llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("fn.nonvirtual");
+ llvm::BasicBlock *FnEnd = CGF.createBasicBlock("fn.end");
+
+ // Load the adjustment, which is in the second field.
+ llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
+ Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
+
+ // Apply the adjustment and cast back to the original struct type
+ // for consistency.
+ llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy(), "ptr");
+ Ptr = Builder.CreateInBoundsGEP(Ptr, Adj, "adj");
+ This = Builder.CreateBitCast(Ptr, This->getType(), "this");
+
+ // Load the function pointer.
+ llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
+ llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
+
+ // If the LSB in the function pointer is 1, the function pointer points to
+ // a virtual function.
+ llvm::Constant *iptr_1 = llvm::ConstantInt::get(FnAsInt->getType(), 1);
+ llvm::Value *IsVirtual = Builder.CreateAnd(FnAsInt, iptr_1);
+ IsVirtual = Builder.CreateIsNotNull(IsVirtual);
+ Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
+
+ // In the virtual path, the adjustment left 'This' pointing to the
+ // vtable of the correct base subobject. The "function pointer" is an
+ // offset within the vtable (+1 for the virtual flag).
+ CGF.EmitBlock(FnVirtual);
+
+ // Cast the adjusted this to a pointer to vtable pointer and load.
+ const llvm::Type *VTableTy = Builder.getInt8PtrTy();
+ llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
+ VTable = Builder.CreateLoad(VTable);
+
+ // Apply the offset.
+ llvm::Value *VTableOffset = Builder.CreateSub(FnAsInt, iptr_1);
+ VTable = Builder.CreateGEP(VTable, VTableOffset, "fn");
+
+ // Load the virtual function to call.
+ VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
+ llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
+ CGF.EmitBranch(FnEnd);
+
+ // In the non-virtual path, the function pointer is actually a
+ // function pointer.
+ CGF.EmitBlock(FnNonVirtual);
+ llvm::Value *NonVirtualFn =
+ Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo());
+
+ // We're done.
+ CGF.EmitBlock(FnEnd);
+ llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
+ Callee->reserveOperandSpace(2);
+ Callee->addIncoming(VirtualFn, FnVirtual);
+ Callee->addIncoming(NonVirtualFn, FnNonVirtual);
+ return Callee;
+}
More information about the cfe-commits
mailing list