From 60a6263ee8cb7e35d2a6481f7abc239371204aff Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Thu, 25 Nov 2010 01:51:53 +0000 Subject: [PATCH] Move isNearlyEmpty out into the ASTContext so it can be called from CodeGen as well. llvm-svn: 120137 --- clang/include/clang/AST/ASTContext.h | 2 ++ clang/lib/AST/ASTContext.cpp | 5 +++++ clang/lib/AST/CXXABI.h | 4 ++++ clang/lib/AST/ItaniumCXXABI.cpp | 15 ++++++++++++++ clang/lib/AST/MicrosoftCXXABI.cpp | 17 ++++++++++++++-- clang/lib/AST/RecordLayoutBuilder.cpp | 29 +-------------------------- 6 files changed, 42 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 11f4e81f605d..848f76bfa794 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -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 &Ivars); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 7b247701021f..e5081e384f7b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -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() {} diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index 5326cd4826c2..943c43e79198 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -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. diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index f5f5f438e76c..ca1fffa06215 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -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 { diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index b1f032b897ae..c4259f43a71e 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -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; + } }; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 0e94ac7e1c57..ba7be0ac692d 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -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(I->getType()->getAs()->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