summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/DeclBase.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-04-09 22:27:44 +0000
committerDouglas Gregor <dgregor@apple.com>2009-04-09 22:27:44 +0000
commitef84c4b434ebd74aa44f2ac1206b8236463cb139 (patch)
tree895ebd296d57b73eeec8ce5da1a81f1eef36a9e7 /clang/lib/AST/DeclBase.cpp
parentf2489ea0431e81a1ba75d06bf9fab47ba08e187e (diff)
downloadbcm5719-llvm-ef84c4b434ebd74aa44f2ac1206b8236463cb139.tar.gz
bcm5719-llvm-ef84c4b434ebd74aa44f2ac1206b8236463cb139.zip
Implementation of pre-compiled headers (PCH) based on lazy
de-serialization of abstract syntax trees. PCH support serializes the contents of the abstract syntax tree (AST) to a bitstream. When the PCH file is read, declarations are serialized as-needed. For example, a declaration of a variable "x" will be deserialized only when its VarDecl can be found by a client, e.g., based on name lookup for "x" or traversing the entire contents of the owner of "x". This commit provides the framework for serialization and (lazy) deserialization, along with support for variable and typedef declarations (along with several kinds of types). More declarations/types, along with important auxiliary structures (source manager, preprocessor, etc.), will follow. llvm-svn: 68732
Diffstat (limited to 'clang/lib/AST/DeclBase.cpp')
-rw-r--r--clang/lib/AST/DeclBase.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 763998e852e..be349428ecf 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
@@ -439,11 +440,82 @@ DeclContext *DeclContext::getNextContext() {
}
}
+/// \brief Load the declarations within this lexical storage from an
+/// external source.
+void
+DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const {
+ ExternalASTSource *Source = Context.getExternalSource();
+ assert(hasExternalLexicalStorage() && Source && "No external storage?");
+
+ llvm::SmallVector<unsigned, 64> Decls;
+ if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this),
+ Decls))
+ return;
+
+ // There is no longer any lexical storage in this context
+ ExternalLexicalStorage = false;
+
+ if (Decls.empty())
+ return;
+
+ // Resolve all of the declaration IDs into declarations, building up
+ // a chain of declarations via the Decl::NextDeclInContext field.
+ Decl *FirstNewDecl = 0;
+ Decl *PrevDecl = 0;
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ Decl *D = Source->GetDecl(Decls[I]);
+ if (PrevDecl)
+ PrevDecl->NextDeclInContext = D;
+ else
+ FirstNewDecl = D;
+
+ PrevDecl = D;
+ }
+
+ // Splice the newly-read declarations into the beginning of the list
+ // of declarations.
+ PrevDecl->NextDeclInContext = FirstDecl;
+ FirstDecl = FirstNewDecl;
+ if (!LastDecl)
+ LastDecl = PrevDecl;
+}
+
+void
+DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const {
+ DeclContext *This = const_cast<DeclContext *>(this);
+ ExternalASTSource *Source = Context.getExternalSource();
+ assert(hasExternalVisibleStorage() && Source && "No external storage?");
+
+ llvm::SmallVector<VisibleDeclaration, 64> Decls;
+ if (Source->ReadDeclsVisibleInContext(This, Decls))
+ return;
+
+ // There is no longer any visible storage in this context
+ ExternalVisibleStorage = false;
+
+ // Load the declaration IDs for all of the names visible in this
+ // context.
+ assert(!LookupPtr && "Have a lookup map before de-serialization?");
+ StoredDeclsMap *Map = new StoredDeclsMap;
+ LookupPtr = Map;
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
+ }
+}
+
DeclContext::decl_iterator DeclContext::decls_begin(ASTContext &Context) const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage(Context);
+
+ // FIXME: Check whether we need to load some declarations from
+ // external storage.
return decl_iterator(FirstDecl);
}
DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const {
+ if (hasExternalLexicalStorage())
+ LoadLexicalDeclsFromExternalStorage(Context);
+
return decl_iterator();
}
@@ -491,6 +563,9 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
if (PrimaryContext != this)
return PrimaryContext->lookup(Context, Name);
+ if (hasExternalVisibleStorage())
+ LoadVisibleDeclsFromExternalStorage(Context);
+
/// If there is no lookup data structure, build one now by walking
/// all of the linked DeclContexts (in declaration order!) and
/// inserting their values.
@@ -595,3 +670,40 @@ DeclContext::getUsingDirectives(ASTContext &Context) const {
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
reinterpret_cast<udir_iterator>(Result.second));
}
+
+void StoredDeclsList::materializeDecls(ASTContext &Context) {
+ if (isNull())
+ return;
+
+ switch ((DataKind)(Data & 0x03)) {
+ case DK_Decl:
+ case DK_Decl_Vector:
+ break;
+
+ case DK_DeclID: {
+ // Resolve this declaration ID to an actual declaration by
+ // querying the external AST source.
+ unsigned DeclID = Data >> 2;
+
+ ExternalASTSource *Source = Context.getExternalSource();
+ assert(Source && "No external AST source available!");
+
+ Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID));
+ break;
+ }
+
+ case DK_ID_Vector: {
+ // We have a vector of declaration IDs. Resolve all of them to
+ // actual declarations.
+ VectorTy &Vector = *getAsVector();
+ ExternalASTSource *Source = Context.getExternalSource();
+ assert(Source && "No external AST source available!");
+
+ for (unsigned I = 0, N = Vector.size(); I != N; ++I)
+ Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I]));
+
+ Data = (Data & ~0x03) | DK_Decl_Vector;
+ break;
+ }
+ }
+}
OpenPOWER on IntegriCloud