forked from OSchip/llvm-project
Move isNearlyEmpty out into the ASTContext so it can be called from CodeGen as well.
llvm-svn: 120137
This commit is contained in:
parent
640cdae167
commit
60a6263ee8
|
@ -1040,6 +1040,8 @@ public:
|
|||
/// of class definition.
|
||||
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
|
||||
|
||||
bool isNearlyEmpty(const CXXRecordDecl *RD);
|
||||
|
||||
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
|
||||
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
|
||||
|
||||
|
|
|
@ -5716,4 +5716,9 @@ CallingConv ASTContext::getDefaultMethodCallConv() {
|
|||
return ABI->getDefaultMethodCallConv();
|
||||
}
|
||||
|
||||
bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) {
|
||||
// Pass through to the C++ ABI object
|
||||
return ABI->isNearlyEmpty(RD);
|
||||
}
|
||||
|
||||
CXXABI::~CXXABI() {}
|
||||
|
|
|
@ -33,6 +33,10 @@ public:
|
|||
|
||||
/// Returns the default calling convention for C++ methods.
|
||||
virtual CallingConv getDefaultMethodCallConv() const = 0;
|
||||
|
||||
// Returns whether the given class is nearly empty, with just virtual pointers
|
||||
// and no data except possibly virtual bases.
|
||||
virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0;
|
||||
};
|
||||
|
||||
/// Creates an instance of a C++ ABI class.
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
|
||||
#include "CXXABI.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
|
@ -39,6 +42,18 @@ public:
|
|||
CallingConv getDefaultMethodCallConv() const {
|
||||
return CC_C;
|
||||
}
|
||||
|
||||
// We cheat and just check that the class has a vtable pointer, and that it's
|
||||
// only big enough to have a vtable pointer and nothing more (or less).
|
||||
bool isNearlyEmpty(const CXXRecordDecl *RD) const {
|
||||
|
||||
// Check that the class has a vtable pointer.
|
||||
if (!RD->isDynamicClass())
|
||||
return false;
|
||||
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
return Layout.getNonVirtualSize() == Context.Target.getPointerWidth(0);
|
||||
}
|
||||
};
|
||||
|
||||
class ARMCXXABI : public ItaniumCXXABI {
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CXXABI.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
|
@ -34,6 +35,18 @@ public:
|
|||
else
|
||||
return CC_C;
|
||||
}
|
||||
|
||||
bool isNearlyEmpty(const CXXRecordDecl *RD) const {
|
||||
// FIXME: Audit the corners
|
||||
if (!RD->isDynamicClass())
|
||||
return false;
|
||||
|
||||
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
|
||||
|
||||
// In the Microsoft ABI, classes can have one or two vtable pointers.
|
||||
return Layout.getNonVirtualSize() == Context.Target.getPointerWidth(0) ||
|
||||
Layout.getNonVirtualSize() == Context.Target.getPointerWidth(0) * 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -667,8 +667,6 @@ protected:
|
|||
|
||||
virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
|
||||
|
||||
virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
|
||||
|
||||
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
|
||||
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
|
||||
void LayoutNonVirtualBases(const CXXRecordDecl *RD);
|
||||
|
@ -717,18 +715,6 @@ public:
|
|||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
/// IsNearlyEmpty - Indicates when a class has a vtable pointer, but
|
||||
/// no other data.
|
||||
bool RecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
|
||||
// FIXME: Audit the corners
|
||||
if (!RD->isDynamicClass())
|
||||
return false;
|
||||
const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
|
||||
if (BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
|
||||
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
|
||||
|
@ -740,7 +726,7 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
|
|||
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
// Check if this is a nearly empty virtual base.
|
||||
if (I->isVirtual() && IsNearlyEmpty(Base)) {
|
||||
if (I->isVirtual() && Context.isNearlyEmpty(Base)) {
|
||||
// If it's not an indirect primary base, then we've found our primary
|
||||
// base.
|
||||
if (!IndirectPrimaryBases.count(Base)) {
|
||||
|
@ -1608,23 +1594,10 @@ namespace {
|
|||
MSRecordLayoutBuilder(ASTContext& Ctx, EmptySubobjectMap *EmptySubobjects) :
|
||||
RecordLayoutBuilder(Ctx, EmptySubobjects) {}
|
||||
|
||||
virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
|
||||
virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
|
||||
};
|
||||
}
|
||||
|
||||
bool MSRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
|
||||
// FIXME: Audit the corners
|
||||
if (!RD->isDynamicClass())
|
||||
return false;
|
||||
const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
|
||||
// In the Microsoft ABI, classes can have one or two vtable pointers.
|
||||
if (BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0) ||
|
||||
BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0) * 2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
|
||||
// We should reserve space for two pointers if the class has both
|
||||
|
|
Loading…
Reference in New Issue