Stash Decl's TopLevelDeclInObjCContainer and ModulePrivate bits

into the two unused lower bits of the NextDeclInContext link, dropping
the number of bits in Decl down to 32, and saving 8 bytes per
declaration on x86-64.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147660 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2012-01-06 16:59:53 +00:00
Родитель b4e85ed519
Коммит 46cd2186bd
5 изменённых файлов: 73 добавлений и 50 удалений

Просмотреть файл

@ -185,16 +185,9 @@ public:
/// \brief Determine whether this declaration has linkage. /// \brief Determine whether this declaration has linkage.
bool hasLinkage() const; bool hasLinkage() const;
/// \brief Whether this declaration was marked as being private to the using Decl::isModulePrivate;
/// module in which it was defined. using Decl::setModulePrivate;
bool isModulePrivate() const { return ModulePrivate; }
/// \brief Specify whether this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
ModulePrivate = MP;
}
/// \brief Determine whether this declaration is hidden from name lookup. /// \brief Determine whether this declaration is hidden from name lookup.
bool isHidden() const { return Hidden; } bool isHidden() const { return Hidden; }

Просмотреть файл

@ -180,12 +180,28 @@ public:
OBJC_TQ_Oneway = 0x20 OBJC_TQ_Oneway = 0x20
}; };
private: protected:
/// NextDeclInContext - The next declaration within the same lexical // Enumeration values used in the bits stored in NextInContextAndBits.
enum {
/// \brief Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
TopLevelDeclInObjCContainerFlag = 0x01,
/// \brief Whether this declaration is private to the module in which it was
/// defined.
ModulePrivateFlag = 0x02
};
/// \brief The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is /// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end(). /// traversed via DeclContext's decls_begin()/decls_end().
Decl *NextDeclInContext; ///
/// The extra two bits are used for the TopLevelDeclInObjCContainer and
/// ModulePrivate bits.
llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits;
private:
friend class DeclContext; friend class DeclContext;
struct MultipleDC { struct MultipleDC {
@ -244,12 +260,6 @@ private:
/// are regarded as "referenced" but not "used". /// are regarded as "referenced" but not "used".
unsigned Referenced : 1; unsigned Referenced : 1;
/// \brief Whether this declaration is a top-level declaration (function,
/// global variable, etc.) that is lexically inside an objc container
/// definition.
/// FIXME: Consider setting the lexical context to the objc container.
unsigned TopLevelDeclInObjCContainer : 1;
protected: protected:
/// Access - Used by C++ decls for the access specifier. /// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
@ -259,10 +269,6 @@ protected:
/// \brief Whether this declaration was loaded from an AST file. /// \brief Whether this declaration was loaded from an AST file.
unsigned FromASTFile : 1; unsigned FromASTFile : 1;
/// \brief Whether this declaration is private to the module in which it was
/// defined.
unsigned ModulePrivate : 1;
/// \brief Whether this declaration is hidden from normal name lookup, e.g., /// \brief Whether this declaration is hidden from normal name lookup, e.g.,
/// because it is was loaded from an AST file is either module-private or /// because it is was loaded from an AST file is either module-private or
/// because its submodule has not been made visible. /// because its submodule has not been made visible.
@ -291,11 +297,10 @@ private:
protected: protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L) Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextDeclInContext(0), DeclCtx(DC), : NextInContextAndBits(), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0), Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false), HasAttrs(false), Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), Access(AS_none), FromASTFile(0), Hidden(0),
ModulePrivate(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0) HasCachedLinkage(0)
{ {
@ -303,10 +308,9 @@ protected:
} }
Decl(Kind DK, EmptyShell Empty) Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), Referenced(false), HasAttrs(false), Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), Access(AS_none), FromASTFile(0), Hidden(0),
ModulePrivate(0), Hidden(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
HasCachedLinkage(0) HasCachedLinkage(0)
{ {
@ -342,8 +346,8 @@ public:
Kind getKind() const { return static_cast<Kind>(DeclKind); } Kind getKind() const { return static_cast<Kind>(DeclKind); }
const char *getDeclKindName() const; const char *getDeclKindName() const;
Decl *getNextDeclInContext() { return NextDeclInContext; } Decl *getNextDeclInContext() { return NextInContextAndBits.getPointer(); }
const Decl *getNextDeclInContext() const { return NextDeclInContext; } const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();}
DeclContext *getDeclContext() { DeclContext *getDeclContext() {
if (isInSemaDC()) if (isInSemaDC())
@ -480,13 +484,38 @@ public:
/// global variable, etc.) that is lexically inside an objc container /// global variable, etc.) that is lexically inside an objc container
/// definition. /// definition.
bool isTopLevelDeclInObjCContainer() const { bool isTopLevelDeclInObjCContainer() const {
return TopLevelDeclInObjCContainer; return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag;
} }
void setTopLevelDeclInObjCContainer(bool V = true) { void setTopLevelDeclInObjCContainer(bool V = true) {
TopLevelDeclInObjCContainer = V; unsigned Bits = NextInContextAndBits.getInt();
if (V)
Bits |= TopLevelDeclInObjCContainerFlag;
else
Bits &= ~TopLevelDeclInObjCContainerFlag;
NextInContextAndBits.setInt(Bits);
} }
protected:
/// \brief Whether this declaration was marked as being private to the
/// module in which it was defined.
bool isModulePrivate() const {
return NextInContextAndBits.getInt() & ModulePrivateFlag;
}
/// \brief Specify whether this declaration was marked as being private
/// to the module in which it was defined.
void setModulePrivate(bool MP = true) {
unsigned Bits = NextInContextAndBits.getInt();
if (MP)
Bits |= ModulePrivateFlag;
else
Bits &= ~ModulePrivateFlag;
NextInContextAndBits.setInt(Bits);
}
public:
/// \brief Determine the availability of the given declaration. /// \brief Determine the availability of the given declaration.
/// ///
/// This routine will determine the most restrictive availability of /// This routine will determine the most restrictive availability of
@ -1396,7 +1425,8 @@ public:
/// \brief Determine whether the given declaration is stored in the list of /// \brief Determine whether the given declaration is stored in the list of
/// declarations lexically within this context. /// declarations lexically within this context.
bool isDeclInLexicalTraversal(const Decl *D) const { bool isDeclInLexicalTraversal(const Decl *D) const {
return D && (D->NextDeclInContext || D == FirstDecl || D == LastDecl); return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl ||
D == LastDecl);
} }
static bool classof(const Decl *D); static bool classof(const Decl *D);

Просмотреть файл

@ -853,7 +853,7 @@ DeclContext *DeclContext::getNextContext() {
std::pair<Decl *, Decl *> std::pair<Decl *, Decl *>
DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls,
bool FieldsAlreadyLoaded) { bool FieldsAlreadyLoaded) {
// Build up a chain of declarations via the Decl::NextDeclInContext field. // Build up a chain of declarations via the Decl::NextInContextAndBits field.
Decl *FirstNewDecl = 0; Decl *FirstNewDecl = 0;
Decl *PrevDecl = 0; Decl *PrevDecl = 0;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) { for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
@ -862,7 +862,7 @@ DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls,
Decl *D = Decls[I]; Decl *D = Decls[I];
if (PrevDecl) if (PrevDecl)
PrevDecl->NextDeclInContext = D; PrevDecl->NextInContextAndBits.setPointer(D);
else else
FirstNewDecl = D; FirstNewDecl = D;
@ -908,7 +908,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
Decl *ExternalFirst, *ExternalLast; Decl *ExternalFirst, *ExternalLast;
llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls, llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls,
FieldsAlreadyLoaded); FieldsAlreadyLoaded);
ExternalLast->NextDeclInContext = FirstDecl; ExternalLast->NextInContextAndBits.setPointer(FirstDecl);
FirstDecl = ExternalFirst; FirstDecl = ExternalFirst;
if (!LastDecl) if (!LastDecl)
LastDecl = ExternalLast; LastDecl = ExternalLast;
@ -983,7 +983,7 @@ bool DeclContext::decls_empty() const {
void DeclContext::removeDecl(Decl *D) { void DeclContext::removeDecl(Decl *D) {
assert(D->getLexicalDeclContext() == this && assert(D->getLexicalDeclContext() == this &&
"decl being removed from non-lexical context"); "decl being removed from non-lexical context");
assert((D->NextDeclInContext || D == LastDecl) && assert((D->NextInContextAndBits.getPointer() || D == LastDecl) &&
"decl is not in decls list"); "decl is not in decls list");
// Remove D from the decl chain. This is O(n) but hopefully rare. // Remove D from the decl chain. This is O(n) but hopefully rare.
@ -991,12 +991,12 @@ void DeclContext::removeDecl(Decl *D) {
if (D == LastDecl) if (D == LastDecl)
FirstDecl = LastDecl = 0; FirstDecl = LastDecl = 0;
else else
FirstDecl = D->NextDeclInContext; FirstDecl = D->NextInContextAndBits.getPointer();
} else { } else {
for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) { for (Decl *I = FirstDecl; true; I = I->NextInContextAndBits.getPointer()) {
assert(I && "decl not found in linked list"); assert(I && "decl not found in linked list");
if (I->NextDeclInContext == D) { if (I->NextInContextAndBits.getPointer() == D) {
I->NextDeclInContext = D->NextDeclInContext; I->NextInContextAndBits.setPointer(D->NextInContextAndBits.getPointer());
if (D == LastDecl) LastDecl = I; if (D == LastDecl) LastDecl = I;
break; break;
} }
@ -1004,7 +1004,7 @@ void DeclContext::removeDecl(Decl *D) {
} }
// Mark that D is no longer in the decl chain. // Mark that D is no longer in the decl chain.
D->NextDeclInContext = 0; D->NextInContextAndBits.setPointer(0);
// Remove D from the lookup table if necessary. // Remove D from the lookup table if necessary.
if (isa<NamedDecl>(D)) { if (isa<NamedDecl>(D)) {
@ -1030,7 +1030,7 @@ void DeclContext::addHiddenDecl(Decl *D) {
"Decl already inserted into a DeclContext"); "Decl already inserted into a DeclContext");
if (FirstDecl) { if (FirstDecl) {
LastDecl->NextDeclInContext = D; LastDecl->NextInContextAndBits.setPointer(D);
LastDecl = D; LastDecl = D;
} else { } else {
FirstDecl = LastDecl = D; FirstDecl = LastDecl = D;

Просмотреть файл

@ -360,17 +360,17 @@ void ASTDeclReader::VisitDecl(Decl *D) {
D->setImplicit(Record[Idx++]); D->setImplicit(Record[Idx++]);
D->setUsed(Record[Idx++]); D->setUsed(Record[Idx++]);
D->setReferenced(Record[Idx++]); D->setReferenced(Record[Idx++]);
D->TopLevelDeclInObjCContainer = Record[Idx++]; D->setTopLevelDeclInObjCContainer(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]);
D->FromASTFile = true; D->FromASTFile = true;
D->ModulePrivate = Record[Idx++]; D->setModulePrivate(Record[Idx++]);
D->Hidden = D->ModulePrivate; D->Hidden = D->isModulePrivate();
// Determine whether this declaration is part of a (sub)module. If so, it // Determine whether this declaration is part of a (sub)module. If so, it
// may not yet be visible. // may not yet be visible.
if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) { if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
// Module-private declarations are never visible, so there is no work to do. // Module-private declarations are never visible, so there is no work to do.
if (!D->ModulePrivate) { if (!D->isModulePrivate()) {
if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
if (Owner->NameVisibility != Module::AllVisible) { if (Owner->NameVisibility != Module::AllVisible) {
// The owning module is not visible. Mark this declaration as hidden. // The owning module is not visible. Mark this declaration as hidden.

Просмотреть файл

@ -154,9 +154,9 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->isImplicit()); Record.push_back(D->isImplicit());
Record.push_back(D->isUsed(false)); Record.push_back(D->isUsed(false));
Record.push_back(D->isReferenced()); Record.push_back(D->isReferenced());
Record.push_back(D->TopLevelDeclInObjCContainer); Record.push_back(D->isTopLevelDeclInObjCContainer());
Record.push_back(D->getAccess()); Record.push_back(D->getAccess());
Record.push_back(D->ModulePrivate); Record.push_back(D->isModulePrivate());
Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation())); Record.push_back(Writer.inferSubmoduleIDFromLocation(D->getLocation()));
} }