diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-12-17 23:38:30 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-12-17 23:38:30 +0000 |
commit | a1be278c4f3a234ff61f04018d26c6beecde1654 (patch) | |
tree | 417374c22b99d713e9c7dbe093ec987d65cb7374 /lib/Serialization/ASTWriterDecl.cpp | |
parent | 79cbbdc8affe52591f7ee487a789639aa38331ec (diff) |
Completely re-implement (de-)serialization of declaration
chains. The previous implementation relied heavily on the declaration
chain being stored as a (circular) linked list on disk, as it is in
memory. However, when deserializing from multiple modules, the
different chains could get mixed up, leading to broken declaration chains.
The new solution keeps track of the first and last declarations in the
chain for each module file. When we load a declaration, we search all
of the module files for redeclarations of that declaration, then
splice together all of the lists into a coherent whole (along with any
redeclarations that were actually parsed).
As a drive-by fix, (de-)serialize the redeclaration chains of
TypedefNameDecls, which had somehow gotten missed previously. Add a
test of this serialization.
This new scheme creates a redeclaration table that is fairly large in
the PCH file (on the order of 400k for Cocoa.h's 12MB PCH file). The
table is mmap'd in and searched via a binary search, but it's still
quite large. A future tweak will eliminate entries for declarations
that have no redeclarations anywhere, and should
drastically reduce the size of this table.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146841 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization/ASTWriterDecl.cpp')
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 89 |
1 files changed, 58 insertions, 31 deletions
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 9b74aaeae4..6c6428d55a 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -125,6 +125,30 @@ namespace clang { }; } +static bool isFirstDeclInFile(Decl *D) { + // FIXME: There must be a better way to abstract Redeclarable<T> into a + // more-general "redeclarable type". + if (TagDecl *Tag = dyn_cast<TagDecl>(D)) + return !Tag->getPreviousDeclaration() || + Tag->getPreviousDeclaration()->isFromASTFile(); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return !FD->getPreviousDeclaration() || + FD->getPreviousDeclaration()->isFromASTFile(); + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + return !VD->getPreviousDeclaration() || + VD->getPreviousDeclaration()->isFromASTFile(); + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) + return !TD->getPreviousDeclaration() || + TD->getPreviousDeclaration()->isFromASTFile(); + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) + return !ID->getPreviousDeclaration() || + ID->getPreviousDeclaration()->isFromASTFile(); + + RedeclarableTemplateDecl *RTD = cast<RedeclarableTemplateDecl>(D); + return !RTD->getPreviousDeclaration() || + RTD->getPreviousDeclaration()->isFromASTFile(); +} + void ASTDeclWriter::Visit(Decl *D) { DeclVisitor<ASTDeclWriter>::Visit(D); @@ -177,13 +201,14 @@ void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { } void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { + VisitRedeclarable(D); VisitTypeDecl(D); Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - D->RedeclLink.getNext() == D && + isFirstDeclInFile(D) && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -196,6 +221,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { } void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { + VisitRedeclarable(D); VisitTypeDecl(D); Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); Code = serialization::DECL_TYPEALIAS; @@ -234,7 +260,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - D->RedeclLink.getNext() == D && + isFirstDeclInFile(D) && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -258,7 +284,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - D->RedeclLink.getNext() == D && + isFirstDeclInFile(D) && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -701,7 +727,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier && !D->hasExtInfo() && - D->RedeclLink.getNext() == D && + isFirstDeclInFile(D) && !D->hasCXXDirectInitializer() && D->getInit() == 0 && !isa<ParmVarDecl>(D) && @@ -1267,30 +1293,24 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, template <typename T> void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { - enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; - if (D->RedeclLink.getNext() == D) { - Record.push_back(NoRedeclaration); - } else { - if (D->RedeclLink.NextIsPrevious()) { - Record.push_back(PointsToPrevious); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Writer.AddDeclRef(D->getFirstDeclaration(), Record); - } else { - Record.push_back(PointsToLatest); - Writer.AddDeclRef(D->RedeclLink.getPointer(), Record); - } - } - + enum { FirstInFile, PointsToPrevious }; T *First = D->getFirstDeclaration(); - T *ThisDecl = static_cast<T*>(D); - // If this is a most recent redeclaration that is pointed to by a first decl - // in a chained PCH, keep track of the association with the map so we can - // update the first decl during AST reading. - if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl && - First->isFromASTFile() && !ThisDecl->isFromASTFile()) { - assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end() - && "The latest is already set"); - Writer.FirstLatestDecls[First] = ThisDecl; + if (!D->getPreviousDeclaration() || + D->getPreviousDeclaration()->isFromASTFile()) { + Record.push_back(FirstInFile); + Writer.AddDeclRef(First, Record); + + // Capture the set of redeclarations in this file. + LocalRedeclarationsInfo LocalInfo = { + Writer.GetDeclRef(First), + Writer.GetDeclRef(static_cast<T*>(D)), + Writer.GetDeclRef(D->getMostRecentDeclaration()) + }; + Writer.LocalRedeclarations.push_back(LocalInfo); + } else { + Record.push_back(PointsToPrevious); + Writer.AddDeclRef(First, Record); + Writer.AddDeclRef(D->getPreviousDeclaration(), Record); } } @@ -1374,7 +1394,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration + Abv->Add(BitCodeAbbrevOp(0)); // First in file + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1421,7 +1442,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration + Abv->Add(BitCodeAbbrevOp(0)); // First in file + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1462,7 +1484,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration + Abv->Add(BitCodeAbbrevOp(0)); // First in file + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1511,6 +1534,9 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // Abbreviation for DECL_TYPEDEF Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); + // Redeclarable + Abv->Add(BitCodeAbbrevOp(0)); // First in file + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1538,7 +1564,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration + Abv->Add(BitCodeAbbrevOp(0)); // First in file + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext |