[MS ABI] Reuse getVFPtrOffsets instead of using getClassAtVTableLocation

getClassAtVTableLocation hunts through virtual bases without using the
MDC layout which is indicative of a bug.

Instead, reuse the getVFPtrOffsets machinery to calculate which
subobject within the MDC is responsible for the vfptr.

Differential Revision: https://reviews.llvm.org/D25895

llvm-svn: 285315
This commit is contained in:
David Majnemer 2016-10-27 17:11:51 +00:00
parent 28c4f18bfe
commit 07c915e1d5
1 changed files with 16 additions and 40 deletions

View File

@ -1762,42 +1762,6 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
return VTable;
}
// Compute the identity of the most derived class whose virtual table is located
// at the given offset into RD.
static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx,
const CXXRecordDecl *RD,
CharUnits Offset) {
if (Offset.isZero())
return RD;
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
const CXXRecordDecl *MaxBase = nullptr;
CharUnits MaxBaseOffset;
for (auto &&B : RD->bases()) {
const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
CharUnits BaseOffset = B.isVirtual() ? Layout.getVBaseClassOffset(Base)
: Layout.getBaseClassOffset(Base);
if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
MaxBase = Base;
MaxBaseOffset = BaseOffset;
}
}
assert(MaxBase);
return getClassAtVTableLocation(Ctx, MaxBase, Offset - MaxBaseOffset);
}
// Compute the identity of the most derived class whose virtual table is located
// at the MethodVFTableLocation ML.
static const CXXRecordDecl *
getClassAtVTableLocation(ASTContext &Ctx, GlobalDecl GD,
MicrosoftVTableContext::MethodVFTableLocation &ML) {
const CXXRecordDecl *RD = ML.VBase;
if (!RD)
RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
return getClassAtVTableLocation(Ctx, RD, ML.VFPtrOffset);
}
CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
Address This,
@ -1813,18 +1777,30 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent());
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
VFTContext.getMethodVFTableLocation(GD);
// Compute the identity of the most derived class whose virtual table is
// located at the MethodVFTableLocation ML.
auto getObjectWithVPtr = [&] {
return llvm::find_if(VFTContext.getVFPtrOffsets(
ML.VBase ? ML.VBase : MethodDecl->getParent()),
[&](const std::unique_ptr<VPtrInfo> &Info) {
return Info->FullOffsetInMDC == ML.VFPtrOffset;
})
->get()
->ObjectWithVPtr;
};
llvm::Value *VFunc;
if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
VFunc = CGF.EmitVTableTypeCheckedLoad(
getClassAtVTableLocation(getContext(), GD, ML), VTable,
getObjectWithVPtr(), VTable,
ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
} else {
if (CGM.getCodeGenOpts().PrepareForLTO)
CGF.EmitTypeMetadataCodeForVCall(
getClassAtVTableLocation(getContext(), GD, ML), VTable, Loc);
CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc);
llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");