apple kext abi requires all vf calls, including qualified

vf calls, be made indirect. This patch is towards that goal.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123922 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2011-01-20 17:19:02 +00:00
Родитель 14cc9451de
Коммит 2726267f09
4 изменённых файлов: 62 добавлений и 3 удалений

Просмотреть файл

@ -306,6 +306,35 @@ CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
}
/// BuildVirtualCall - This routine is to support gcc's kext ABI making
/// indirect call to virtual functions. It makes the call through indexing
/// into the vtable.
llvm::Value *
CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Value *This,
const llvm::Type *Ty) {
llvm::Value *VTable = 0;
assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
"BuildAppleKextVirtualCall - bad Qual kind");
const Type *QTy = Qual->getAsType();
QualType T = QualType(QTy, 0);
const RecordType *RT = T->getAs<RecordType>();
assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
VTable = CGM.getVTables().GetAddrOfVTable(RD);
Ty = Ty->getPointerTo()->getPointerTo();
VTable = Builder.CreateBitCast(VTable, Ty);
assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
MD = MD->getCanonicalDecl();
uint64_t VTableIndex = CGM.getVTables().getMethodVTableIndex(MD);
VTableIndex += 2;
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
return CGF.Builder.CreateLoad(VFuncPtr);
}
llvm::Value *
CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
llvm::Value *This, const llvm::Type *Ty) {

Просмотреть файл

@ -172,8 +172,12 @@ 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 = MD->isVirtual() && !ME->hasQualifier()
bool UseVirtualCall;
if (!getContext().getLangOptions().AppleKext)
UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
&& !canDevirtualizeMemberFunctionCalls(ME->getBase(), MD);
else
UseVirtualCall = MD->isVirtual();
llvm::Value *Callee;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
@ -186,6 +190,11 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
} else if (UseVirtualCall) {
if (getContext().getLangOptions().AppleKext &&
ME->hasQualifier()) {
Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), This, Ty);
}
else
Callee = BuildVirtualCall(MD, This, Ty);
} else {
Callee = CGM.GetAddrOfFunction(MD, Ty);
@ -267,7 +276,9 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
FPT->isVariadic());
llvm::Value *Callee;
if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0), MD))
if (MD->isVirtual() &&
(getContext().getLangOptions().AppleKext ||
!canDevirtualizeMemberFunctionCalls(E->getArg(0), MD)))
Callee = BuildVirtualCall(MD, This, Ty);
else
Callee = CGM.GetAddrOfFunction(MD, Ty);

Просмотреть файл

@ -1500,6 +1500,10 @@ public:
const llvm::Type *Ty);
llvm::Value *BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
llvm::Value *This, const llvm::Type *Ty);
llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
NestedNameSpecifier *Qual,
llvm::Value *This,
const llvm::Type *Ty);
RValue EmitCXXMemberCall(const CXXMethodDecl *MD,
llvm::Value *Callee,

Просмотреть файл

@ -0,0 +1,15 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -emit-llvm -o - %s | FileCheck %s
struct Base {
virtual void abc1(void) const;
virtual void abc2(void) const;
virtual void abc(void) const;
};
void Base::abc(void) const {}
void FUNC(Base* p) {
p->Base::abc();
}
// CHECK-NOT: call void @_ZNK4Base3abcEv