зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
14cc9451de
Коммит
2726267f09
|
@ -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,7 +190,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
|
|||
dyn_cast<CXXConstructorDecl>(MD)) {
|
||||
Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
|
||||
} else if (UseVirtualCall) {
|
||||
Callee = BuildVirtualCall(MD, This, Ty);
|
||||
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
|
Загрузка…
Ссылка в новой задаче