Move isNearlyEmpty out into the ASTContext so it can be called from CodeGen as well.

llvm-svn: 120137
This commit is contained in:
Anders Carlsson 2010-11-25 01:51:53 +00:00
parent 640cdae167
commit 60a6263ee8
6 changed files with 42 additions and 30 deletions

View File

@ -1040,6 +1040,8 @@ public:
/// of class definition. /// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
bool isNearlyEmpty(const CXXRecordDecl *RD);
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);

View File

@ -5716,4 +5716,9 @@ CallingConv ASTContext::getDefaultMethodCallConv() {
return ABI->getDefaultMethodCallConv(); return ABI->getDefaultMethodCallConv();
} }
bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) {
// Pass through to the C++ ABI object
return ABI->isNearlyEmpty(RD);
}
CXXABI::~CXXABI() {} CXXABI::~CXXABI() {}

View File

@ -33,6 +33,10 @@ public:
/// Returns the default calling convention for C++ methods. /// Returns the default calling convention for C++ methods.
virtual CallingConv getDefaultMethodCallConv() const = 0; 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. /// Creates an instance of a C++ ABI class.

View File

@ -19,7 +19,10 @@
#include "CXXABI.h" #include "CXXABI.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang; using namespace clang;
@ -39,6 +42,18 @@ public:
CallingConv getDefaultMethodCallConv() const { CallingConv getDefaultMethodCallConv() const {
return CC_C; 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 { class ARMCXXABI : public ItaniumCXXABI {

View File

@ -13,10 +13,11 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "CXXABI.h" #include "CXXABI.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang; using namespace clang;
@ -34,6 +35,18 @@ public:
else else
return CC_C; 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;
}
}; };
} }

View File

@ -667,8 +667,6 @@ protected:
virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const; virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
/// LayoutNonVirtualBases - Determines the primary base class (if any) and /// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess. /// lays it out. Will then proceed to lay out all non-virtual base clasess.
void LayoutNonVirtualBases(const CXXRecordDecl *RD); void LayoutNonVirtualBases(const CXXRecordDecl *RD);
@ -717,18 +715,6 @@ public:
}; };
} // end anonymous namespace } // 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 void
RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), 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()); cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
// Check if this is a nearly empty virtual base. // 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 // If it's not an indirect primary base, then we've found our primary
// base. // base.
if (!IndirectPrimaryBases.count(Base)) { if (!IndirectPrimaryBases.count(Base)) {
@ -1608,23 +1594,10 @@ namespace {
MSRecordLayoutBuilder(ASTContext& Ctx, EmptySubobjectMap *EmptySubobjects) : MSRecordLayoutBuilder(ASTContext& Ctx, EmptySubobjectMap *EmptySubobjects) :
RecordLayoutBuilder(Ctx, EmptySubobjects) {} RecordLayoutBuilder(Ctx, EmptySubobjects) {}
virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
virtual uint64_t GetVirtualPointersSize(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 uint64_t
MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const { MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
// We should reserve space for two pointers if the class has both // We should reserve space for two pointers if the class has both