[cfe-commits] r138582 - in /cfe/trunk: include/clang/Serialization/ASTReader.h include/clang/Serialization/Module.h include/clang/Serialization/ModuleManager.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderInternals.h lib/Serialization/CMakeLists.txt lib/Serialization/Module.cpp lib/Serialization/ModuleManager.cpp

Douglas Gregor dgregor at apple.com
Thu Aug 25 13:47:51 PDT 2011


Author: dgregor
Date: Thu Aug 25 15:47:51 2011
New Revision: 138582

URL: http://llvm.org/viewvc/llvm-project?rev=138582&view=rev
Log:
Factor the Module and ModuleManager classes out into separate headers
and .cpp files, since ASTReader.cpp was getting way too large. No
functionality change.

Added:
    cfe/trunk/include/clang/Serialization/Module.h
    cfe/trunk/include/clang/Serialization/ModuleManager.h
    cfe/trunk/lib/Serialization/ASTReaderInternals.h
    cfe/trunk/lib/Serialization/Module.cpp
    cfe/trunk/lib/Serialization/ModuleManager.cpp
Modified:
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/CMakeLists.txt

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=138582&r1=138581&r2=138582&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Aug 25 15:47:51 2011
@@ -16,6 +16,8 @@
 
 #include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/Module.h"
+#include "clang/Serialization/ModuleManager.h"
 #include "clang/Sema/ExternalSemaSource.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/DeclObjC.h"
@@ -32,7 +34,6 @@
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitcode/BitstreamReader.h"
@@ -73,7 +74,6 @@
 class ASTReader;
 class ASTDeclReader;
 class ASTStmtReader;
-class ASTIdentifierLookupTrait;
 class TypeLocReader;
 struct HeaderFileInfo;
 class VersionTuple;
@@ -161,421 +161,14 @@
   void Error(const char *Msg);
 };
 
-namespace serialization {
-    
-/// \brief Specifies the kind of module that has been loaded.
-enum ModuleKind {
-  MK_Module,   ///< File is a module proper.
-  MK_PCH,      ///< File is a PCH file treated as such.
-  MK_Preamble, ///< File is a PCH file treated as the preamble.
-  MK_MainFile  ///< File is a PCH file treated as the actual main file.
-};
-
-/// \brief Information about the contents of a DeclContext.
-struct DeclContextInfo {
-  DeclContextInfo() 
-    : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
-
-  void *NameLookupTableData; // an ASTDeclContextNameLookupTable.
-  const KindDeclIDPair *LexicalDecls;
-  unsigned NumLexicalDecls;
-};
-
-/// \brief Information about a module that has been loaded by the ASTReader.
-///
-/// Each instance of the Module class corresponds to a single AST file, which 
-/// may be a precompiled header, precompiled preamble, or an AST file of some 
-/// sort loaded as the main file, all of which are specific formulations of
-/// the general notion of a "module". A module may depend on another module.
-class Module {
-public:  
-  Module(ModuleKind Kind);
-  ~Module();
-  
-  // === General information ===
-  
-  /// \brief The type of this module.
-  ModuleKind Kind;
-  
-  /// \brief The file name of the module file.
-  std::string FileName;
-  
-  /// \brief Whether this module has been directly imported by the
-  /// user.
-  bool DirectlyImported;
-
-  /// \brief The memory buffer that stores the data associated with
-  /// this AST file.
-  llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
-  
-  /// \brief The size of this file, in bits.
-  uint64_t SizeInBits;
-  
-  /// \brief The global bit offset (or base) of this module
-  uint64_t GlobalBitOffset;
-  
-  /// \brief The bitstream reader from which we'll read the AST file.
-  llvm::BitstreamReader StreamFile;
-  
-  /// \brief The main bitstream cursor for the main block.
-  llvm::BitstreamCursor Stream;
-  
-  /// \brief The source location where this module was first imported.
-  SourceLocation ImportLoc;
-  
-  /// \brief The first source location in this module.
-  SourceLocation FirstLoc;
-  
-  // === Source Locations ===
-  
-  /// \brief Cursor used to read source location entries.
-  llvm::BitstreamCursor SLocEntryCursor;
-  
-  /// \brief The number of source location entries in this AST file.
-  unsigned LocalNumSLocEntries;
-  
-  /// \brief The base ID in the source manager's view of this module.
-  int SLocEntryBaseID;
-  
-  /// \brief The base offset in the source manager's view of this module.
-  unsigned SLocEntryBaseOffset;
-  
-  /// \brief Offsets for all of the source location entries in the
-  /// AST file.
-  const uint32_t *SLocEntryOffsets;
-  
-  /// \brief The number of source location file entries in this AST file.
-  unsigned LocalNumSLocFileEntries;
-  
-  /// \brief Offsets for all of the source location file entries in the
-  /// AST file.
-  const uint32_t *SLocFileOffsets;
-  
-  /// \brief Remapping table for source locations in this module.
-  ContinuousRangeMap<uint32_t, int, 2> SLocRemap;
-  
-  // === Identifiers ===
-  
-  /// \brief The number of identifiers in this AST file.
-  unsigned LocalNumIdentifiers;
-  
-  /// \brief Offsets into the identifier table data.
-  ///
-  /// This array is indexed by the identifier ID (-1), and provides
-  /// the offset into IdentifierTableData where the string data is
-  /// stored.
-  const uint32_t *IdentifierOffsets;
-  
-  /// \brief Base identifier ID for identifiers local to this module.
-  serialization::IdentID BaseIdentifierID;
-
-  /// \brief Remapping table for identifier IDs in this module.
-  ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap;
-
-  /// \brief Actual data for the on-disk hash table of identifiers.
-  ///
-  /// This pointer points into a memory buffer, where the on-disk hash
-  /// table for identifiers actually lives.
-  const char *IdentifierTableData;
-  
-  /// \brief A pointer to an on-disk hash table of opaque type
-  /// IdentifierHashTable.
-  void *IdentifierLookupTable;
-  
-  // === Macros ===
-  
-  /// \brief The cursor to the start of the preprocessor block, which stores
-  /// all of the macro definitions.
-  llvm::BitstreamCursor MacroCursor;
-  
-  /// \brief The offset of the start of the set of defined macros.
-  uint64_t MacroStartOffset;
-  
-  // === Detailed PreprocessingRecord ===
-  
-  /// \brief The cursor to the start of the (optional) detailed preprocessing 
-  /// record block.
-  llvm::BitstreamCursor PreprocessorDetailCursor;
-  
-  /// \brief The offset of the start of the preprocessor detail cursor.
-  uint64_t PreprocessorDetailStartOffset;
-  
-  /// \brief Base preprocessed entity ID for preprocessed entities local to 
-  /// this module.
-  serialization::PreprocessedEntityID BasePreprocessedEntityID;
-  
-  /// \brief Remapping table for preprocessed entity IDs in this module.
-  ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap;
-
-  /// \brief The number of macro definitions in this file.
-  unsigned LocalNumMacroDefinitions;
-  
-  /// \brief Offsets of all of the macro definitions in the preprocessing
-  /// record in the AST file.
-  const uint32_t *MacroDefinitionOffsets;
-  
-  /// \brief Base macro definition ID for macro definitions local to this 
-  /// module.
-  serialization::MacroID BaseMacroDefinitionID;
-
-  /// \brief Remapping table for macro definition IDs in this module.
-  ContinuousRangeMap<uint32_t, int, 2> MacroDefinitionRemap;
-
-  // === Header search information ===
-  
-  /// \brief The number of local HeaderFileInfo structures.
-  unsigned LocalNumHeaderFileInfos;
-  
-  /// \brief Actual data for the on-disk hash table of header file 
-  /// information.
-  ///
-  /// This pointer points into a memory buffer, where the on-disk hash
-  /// table for header file information actually lives.
-  const char *HeaderFileInfoTableData;
-    
-  /// \brief The on-disk hash table that contains information about each of
-  /// the header files.
-  void *HeaderFileInfoTable;
-  
-  /// \brief Actual data for the list of framework names used in the header
-  /// search information.
-  const char *HeaderFileFrameworkStrings;
-
-  // === Selectors ===
-  
-  /// \brief The number of selectors new to this file.
-  ///
-  /// This is the number of entries in SelectorOffsets.
-  unsigned LocalNumSelectors;
-  
-  /// \brief Offsets into the selector lookup table's data array
-  /// where each selector resides.
-  const uint32_t *SelectorOffsets;
-  
-  /// \brief Base selector ID for selectors local to this module.
-  serialization::SelectorID BaseSelectorID;
-
-  /// \brief Remapping table for selector IDs in this module.
-  ContinuousRangeMap<uint32_t, int, 2> SelectorRemap;
-
-  /// \brief A pointer to the character data that comprises the selector table
-  ///
-  /// The SelectorOffsets table refers into this memory.
-  const unsigned char *SelectorLookupTableData;
-  
-  /// \brief A pointer to an on-disk hash table of opaque type
-  /// ASTSelectorLookupTable.
-  ///
-  /// This hash table provides the IDs of all selectors, and the associated
-  /// instance and factory methods.
-  void *SelectorLookupTable;
-  
-  // === Declarations ===
-  
-  /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
-  /// has read all the abbreviations at the start of the block and is ready to
-  /// jump around with these in context.
-  llvm::BitstreamCursor DeclsCursor;
-  
-  /// \brief The number of declarations in this AST file.
-  unsigned LocalNumDecls;
-  
-  /// \brief Offset of each declaration within the bitstream, indexed
-  /// by the declaration ID (-1).
-  const uint32_t *DeclOffsets;
-  
-  /// \brief Base declaration ID for declarations local to this module.
-  serialization::DeclID BaseDeclID;
-
-  /// \brief Remapping table for declaration IDs in this module.
-  ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
-
-  /// \brief The number of C++ base specifier sets in this AST file.
-  unsigned LocalNumCXXBaseSpecifiers;
-  
-  /// \brief Offset of each C++ base specifier set within the bitstream,
-  /// indexed by the C++ base specifier set ID (-1).
-  const uint32_t *CXXBaseSpecifiersOffsets;
-
-  typedef llvm::DenseMap<const DeclContext *, DeclContextInfo>
-      DeclContextInfosMap;
-
-  /// \brief Information about the lexical and visible declarations
-  /// for each DeclContext.
-  DeclContextInfosMap DeclContextInfos;
-
-  // === Types ===
-  
-  /// \brief The number of types in this AST file.
-  unsigned LocalNumTypes;
-  
-  /// \brief Offset of each type within the bitstream, indexed by the
-  /// type ID, or the representation of a Type*.
-  const uint32_t *TypeOffsets;
-  
-  /// \brief Base type ID for types local to this module as represented in 
-  /// the global type ID space.
-  serialization::TypeID BaseTypeIndex;
-  
-  /// \brief Remapping table for type IDs in this module.
-  ContinuousRangeMap<uint32_t, int, 2> TypeRemap;
-
-  // === Miscellaneous ===
-  
-  /// \brief Diagnostic IDs and their mappings that the user changed.
-  SmallVector<uint64_t, 8> PragmaDiagMappings;
-  
-  /// \brief The AST stat cache installed for this file, if any.
-  ///
-  /// The dynamic type of this stat cache is always ASTStatCache
-  void *StatCache;
-  
-  /// \brief The number of preallocated preprocessing entities in the
-  /// preprocessing record.
-  unsigned NumPreallocatedPreprocessingEntities;
-  
-  /// \brief List of modules which depend on this module
-  llvm::SetVector<Module *> ImportedBy;
-  
-  /// \brief List of modules which this module depends on
-  llvm::SetVector<Module *> Imports;
-
-  /// \brief Determine whether this module was directly imported at
-  /// any point during translation.
-  bool isDirectlyImported() const { return DirectlyImported; }
-
-  /// \brief Dump debugging output for this module.
-  void dump();
-};
-
-/// \brief The manager for modules loaded by the ASTReader.
-class ModuleManager {
-  /// \brief The chain of AST files. The first entry is the one named by the
-  /// user, the last one is the one that doesn't depend on anything further.
-  SmallVector<Module*, 2> Chain;
-
-  /// \brief All loaded modules, indexed by name.
-  llvm::DenseMap<const FileEntry *, Module *> Modules;
-
-  /// \brief FileManager that handles translating between filenames and
-  /// FileEntry *.
-  FileManager FileMgr;
-  
-  /// \brief A lookup of in-memory (virtual file) buffers
-  llvm::DenseMap<const FileEntry *, llvm::MemoryBuffer *> InMemoryBuffers;
-
-public:
-  typedef SmallVector<Module*, 2>::iterator ModuleIterator;
-  typedef SmallVector<Module*, 2>::const_iterator ModuleConstIterator;
-  typedef SmallVector<Module*, 2>::reverse_iterator ModuleReverseIterator;
-  typedef std::pair<uint32_t, StringRef> ModuleOffset;
-
-  ModuleManager(const FileSystemOptions &FSO);
-  ~ModuleManager();
-
-  /// \brief Forward iterator to traverse all loaded modules.  This is reverse
-  /// source-order.
-  ModuleIterator begin() { return Chain.begin(); }
-  /// \brief Forward iterator end-point to traverse all loaded modules
-  ModuleIterator end() { return Chain.end(); }
-
-  /// \brief Const forward iterator to traverse all loaded modules.  This is 
-  /// in reverse source-order.
-  ModuleConstIterator begin() const { return Chain.begin(); }
-  /// \brief Const forward iterator end-point to traverse all loaded modules
-  ModuleConstIterator end() const { return Chain.end(); }
-
-  /// \brief Reverse iterator to traverse all loaded modules.  This is in 
-  /// source order.
-  ModuleReverseIterator rbegin() { return Chain.rbegin(); }
-  /// \brief Reverse iterator end-point to traverse all loaded modules.
-  ModuleReverseIterator rend() { return Chain.rend(); }
-
-  /// \brief Returns the primary module associated with the manager, that is,
-  /// the first module loaded
-  Module &getPrimaryModule() { return *Chain[0]; }
-
-  /// \brief Returns the primary module associated with the manager, that is,
-  /// the first module loaded.
-  Module &getPrimaryModule() const { return *Chain[0]; }
-
-  /// \brief Returns the module associated with the given index
-  Module &operator[](unsigned Index) const { return *Chain[Index]; }
-
-  /// \brief Returns the module associated with the given name
-  Module *lookup(StringRef Name);
-  
-  /// \brief Returns the in-memory (virtual file) buffer with the given name
-  llvm::MemoryBuffer *lookupBuffer(StringRef Name);
-
-  /// \brief Number of modules loaded
-  unsigned size() const { return Chain.size(); }
-
-  /// \brief Attempts to create a new module and add it to the list of known
-  /// modules.
-  ///
-  /// \param FileName The file name of the module to be loaded.
-  ///
-  /// \param Type The kind of module being loaded.
-  ///
-  /// \param ImportedBy The module that is importing this module, or NULL if
-  /// this module is imported directly by the user.
-  ///
-  /// \param ErrorStr Will be set to a non-empty string if any errors occurred
-  /// while trying to load the module.
-  ///
-  /// \return A pointer to the module that corresponds to this file name,
-  /// and a boolean indicating whether the module was newly added.
-  std::pair<Module *, bool> 
-  addModule(StringRef FileName, ModuleKind Type, Module *ImportedBy,
-            std::string &ErrorStr);
-  
-  /// \brief Add an in-memory buffer the list of known buffers
-  void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer);
-
-  /// \brief Visit each of the modules.
-  ///
-  /// This routine visits each of the modules, starting with the
-  /// "root" modules that no other loaded modules depend on, and
-  /// proceeding to the leaf modules, visiting each module only once
-  /// during the traversal.
-  ///
-  /// This traversal is intended to support various "lookup"
-  /// operations that can find data in any of the loaded modules.
-  ///
-  /// \param Visitor A visitor function that will be invoked with each
-  /// module and the given user data pointer. The return value must be
-  /// convertible to bool; when false, the visitation continues to
-  /// modules that the current module depends on. When true, the
-  /// visitation skips any modules that the current module depends on.
-  ///
-  /// \param UserData User data associated with the visitor object, which
-  /// will be passed along to the visitor.
-  void visit(bool (*Visitor)(Module &M, void *UserData), void *UserData);
-
-  /// \brief Visit each of the modules with a depth-first traversal.
-  ///
-  /// This routine visits each of the modules known to the module
-  /// manager using a depth-first search, starting with the first
-  /// loaded module. The traversal invokes the callback both before
-  /// traversing the children (preorder traversal) and after
-  /// traversing the children (postorder traversal).
-  ///
-  /// \param Visitor A visitor function that will be invoked with each
-  /// module and given a \c Preorder flag that indicates whether we're
-  /// visiting the module before or after visiting its children.  The
-  /// visitor may return true at any time to abort the depth-first
-  /// visitation.
-  ///
-  /// \param UserData User data ssociated with the visitor object,
-  /// which will be passed along to the user.
-  void visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, 
-                                       void *UserData), 
-                       void *UserData);
-};
+namespace serialization {    
 
 class ReadMethodPoolVisitor;
   
+namespace reader {
+  class ASTIdentifierLookupTrait;
+}
+  
 } // end namespace serialization
   
 /// \brief Reads an AST files chain containing the contents of a translation
@@ -606,7 +199,7 @@
   friend class ASTDeclReader;
   friend class ASTStmtReader;
   friend class ASTIdentifierIterator;
-  friend class ASTIdentifierLookupTrait;
+  friend class serialization::reader::ASTIdentifierLookupTrait;
   friend class TypeLocReader;
   friend class ASTWriter;
   friend class ASTUnit; // ASTUnit needs to remap source locations.

Added: cfe/trunk/include/clang/Serialization/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=138582&view=auto
==============================================================================
--- cfe/trunk/include/clang/Serialization/Module.h (added)
+++ cfe/trunk/include/clang/Serialization/Module.h Thu Aug 25 15:47:51 2011
@@ -0,0 +1,322 @@
+//===--- Module.h - Module description --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the Module class, which describes a module that has
+//  been loaded from an AST file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_MODULE_H
+#define LLVM_CLANG_SERIALIZATION_MODULE_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include <string>
+
+namespace clang { 
+
+class DeclContext;
+  
+namespace serialization {
+   
+/// \brief Specifies the kind of module that has been loaded.
+enum ModuleKind {
+  MK_Module,   ///< File is a module proper.
+  MK_PCH,      ///< File is a PCH file treated as such.
+  MK_Preamble, ///< File is a PCH file treated as the preamble.
+  MK_MainFile  ///< File is a PCH file treated as the actual main file.
+};
+
+/// \brief Information about the contents of a DeclContext.
+struct DeclContextInfo {
+  DeclContextInfo() 
+    : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
+  
+  void *NameLookupTableData; // an ASTDeclContextNameLookupTable.
+  const KindDeclIDPair *LexicalDecls;
+  unsigned NumLexicalDecls;
+};
+
+/// \brief Information about a module that has been loaded by the ASTReader.
+///
+/// Each instance of the Module class corresponds to a single AST file, which 
+/// may be a precompiled header, precompiled preamble, a module, or an AST file 
+/// of some sort loaded as the main file, all of which are specific formulations of
+/// the general notion of a "module". A module may depend on any number of
+/// other modules.
+class Module {
+public:  
+  Module(ModuleKind Kind);
+  ~Module();
+  
+  // === General information ===
+  
+  /// \brief The type of this module.
+  ModuleKind Kind;
+  
+  /// \brief The file name of the module file.
+  std::string FileName;
+  
+  /// \brief Whether this module has been directly imported by the
+  /// user.
+  bool DirectlyImported;
+  
+  /// \brief The memory buffer that stores the data associated with
+  /// this AST file.
+  llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+  
+  /// \brief The size of this file, in bits.
+  uint64_t SizeInBits;
+  
+  /// \brief The global bit offset (or base) of this module
+  uint64_t GlobalBitOffset;
+  
+  /// \brief The bitstream reader from which we'll read the AST file.
+  llvm::BitstreamReader StreamFile;
+  
+  /// \brief The main bitstream cursor for the main block.
+  llvm::BitstreamCursor Stream;
+  
+  /// \brief The source location where this module was first imported.
+  SourceLocation ImportLoc;
+  
+  /// \brief The first source location in this module.
+  SourceLocation FirstLoc;
+  
+  // === Source Locations ===
+  
+  /// \brief Cursor used to read source location entries.
+  llvm::BitstreamCursor SLocEntryCursor;
+  
+  /// \brief The number of source location entries in this AST file.
+  unsigned LocalNumSLocEntries;
+  
+  /// \brief The base ID in the source manager's view of this module.
+  int SLocEntryBaseID;
+  
+  /// \brief The base offset in the source manager's view of this module.
+  unsigned SLocEntryBaseOffset;
+  
+  /// \brief Offsets for all of the source location entries in the
+  /// AST file.
+  const uint32_t *SLocEntryOffsets;
+  
+  /// \brief The number of source location file entries in this AST file.
+  unsigned LocalNumSLocFileEntries;
+  
+  /// \brief Offsets for all of the source location file entries in the
+  /// AST file.
+  const uint32_t *SLocFileOffsets;
+  
+  /// \brief Remapping table for source locations in this module.
+  ContinuousRangeMap<uint32_t, int, 2> SLocRemap;
+  
+  // === Identifiers ===
+  
+  /// \brief The number of identifiers in this AST file.
+  unsigned LocalNumIdentifiers;
+  
+  /// \brief Offsets into the identifier table data.
+  ///
+  /// This array is indexed by the identifier ID (-1), and provides
+  /// the offset into IdentifierTableData where the string data is
+  /// stored.
+  const uint32_t *IdentifierOffsets;
+  
+  /// \brief Base identifier ID for identifiers local to this module.
+  serialization::IdentID BaseIdentifierID;
+  
+  /// \brief Remapping table for identifier IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap;
+  
+  /// \brief Actual data for the on-disk hash table of identifiers.
+  ///
+  /// This pointer points into a memory buffer, where the on-disk hash
+  /// table for identifiers actually lives.
+  const char *IdentifierTableData;
+  
+  /// \brief A pointer to an on-disk hash table of opaque type
+  /// IdentifierHashTable.
+  void *IdentifierLookupTable;
+  
+  // === Macros ===
+  
+  /// \brief The cursor to the start of the preprocessor block, which stores
+  /// all of the macro definitions.
+  llvm::BitstreamCursor MacroCursor;
+  
+  /// \brief The offset of the start of the set of defined macros.
+  uint64_t MacroStartOffset;
+  
+  // === Detailed PreprocessingRecord ===
+  
+  /// \brief The cursor to the start of the (optional) detailed preprocessing 
+  /// record block.
+  llvm::BitstreamCursor PreprocessorDetailCursor;
+  
+  /// \brief The offset of the start of the preprocessor detail cursor.
+  uint64_t PreprocessorDetailStartOffset;
+  
+  /// \brief Base preprocessed entity ID for preprocessed entities local to 
+  /// this module.
+  serialization::PreprocessedEntityID BasePreprocessedEntityID;
+  
+  /// \brief Remapping table for preprocessed entity IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap;
+  
+  /// \brief The number of macro definitions in this file.
+  unsigned LocalNumMacroDefinitions;
+  
+  /// \brief Offsets of all of the macro definitions in the preprocessing
+  /// record in the AST file.
+  const uint32_t *MacroDefinitionOffsets;
+  
+  /// \brief Base macro definition ID for macro definitions local to this 
+  /// module.
+  serialization::MacroID BaseMacroDefinitionID;
+  
+  /// \brief Remapping table for macro definition IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> MacroDefinitionRemap;
+  
+  // === Header search information ===
+  
+  /// \brief The number of local HeaderFileInfo structures.
+  unsigned LocalNumHeaderFileInfos;
+  
+  /// \brief Actual data for the on-disk hash table of header file 
+  /// information.
+  ///
+  /// This pointer points into a memory buffer, where the on-disk hash
+  /// table for header file information actually lives.
+  const char *HeaderFileInfoTableData;
+  
+  /// \brief The on-disk hash table that contains information about each of
+  /// the header files.
+  void *HeaderFileInfoTable;
+  
+  /// \brief Actual data for the list of framework names used in the header
+  /// search information.
+  const char *HeaderFileFrameworkStrings;
+  
+  // === Selectors ===
+  
+  /// \brief The number of selectors new to this file.
+  ///
+  /// This is the number of entries in SelectorOffsets.
+  unsigned LocalNumSelectors;
+  
+  /// \brief Offsets into the selector lookup table's data array
+  /// where each selector resides.
+  const uint32_t *SelectorOffsets;
+  
+  /// \brief Base selector ID for selectors local to this module.
+  serialization::SelectorID BaseSelectorID;
+  
+  /// \brief Remapping table for selector IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> SelectorRemap;
+  
+  /// \brief A pointer to the character data that comprises the selector table
+  ///
+  /// The SelectorOffsets table refers into this memory.
+  const unsigned char *SelectorLookupTableData;
+  
+  /// \brief A pointer to an on-disk hash table of opaque type
+  /// ASTSelectorLookupTable.
+  ///
+  /// This hash table provides the IDs of all selectors, and the associated
+  /// instance and factory methods.
+  void *SelectorLookupTable;
+  
+  // === Declarations ===
+  
+  /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
+  /// has read all the abbreviations at the start of the block and is ready to
+  /// jump around with these in context.
+  llvm::BitstreamCursor DeclsCursor;
+  
+  /// \brief The number of declarations in this AST file.
+  unsigned LocalNumDecls;
+  
+  /// \brief Offset of each declaration within the bitstream, indexed
+  /// by the declaration ID (-1).
+  const uint32_t *DeclOffsets;
+  
+  /// \brief Base declaration ID for declarations local to this module.
+  serialization::DeclID BaseDeclID;
+  
+  /// \brief Remapping table for declaration IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
+  
+  /// \brief The number of C++ base specifier sets in this AST file.
+  unsigned LocalNumCXXBaseSpecifiers;
+  
+  /// \brief Offset of each C++ base specifier set within the bitstream,
+  /// indexed by the C++ base specifier set ID (-1).
+  const uint32_t *CXXBaseSpecifiersOffsets;
+  
+  typedef llvm::DenseMap<const DeclContext *, DeclContextInfo>
+  DeclContextInfosMap;
+  
+  /// \brief Information about the lexical and visible declarations
+  /// for each DeclContext.
+  DeclContextInfosMap DeclContextInfos;
+  
+  // === Types ===
+  
+  /// \brief The number of types in this AST file.
+  unsigned LocalNumTypes;
+  
+  /// \brief Offset of each type within the bitstream, indexed by the
+  /// type ID, or the representation of a Type*.
+  const uint32_t *TypeOffsets;
+  
+  /// \brief Base type ID for types local to this module as represented in 
+  /// the global type ID space.
+  serialization::TypeID BaseTypeIndex;
+  
+  /// \brief Remapping table for type IDs in this module.
+  ContinuousRangeMap<uint32_t, int, 2> TypeRemap;
+  
+  // === Miscellaneous ===
+  
+  /// \brief Diagnostic IDs and their mappings that the user changed.
+  SmallVector<uint64_t, 8> PragmaDiagMappings;
+  
+  /// \brief The AST stat cache installed for this file, if any.
+  ///
+  /// The dynamic type of this stat cache is always ASTStatCache
+  void *StatCache;
+  
+  /// \brief The number of preallocated preprocessing entities in the
+  /// preprocessing record.
+  unsigned NumPreallocatedPreprocessingEntities;
+  
+  /// \brief List of modules which depend on this module
+  llvm::SetVector<Module *> ImportedBy;
+  
+  /// \brief List of modules which this module depends on
+  llvm::SetVector<Module *> Imports;
+  
+  /// \brief Determine whether this module was directly imported at
+  /// any point during translation.
+  bool isDirectlyImported() const { return DirectlyImported; }
+  
+  /// \brief Dump debugging output for this module.
+  void dump();
+};
+
+} // end namespace serialization
+
+} // end namespace clang
+
+#endif

Added: cfe/trunk/include/clang/Serialization/ModuleManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ModuleManager.h?rev=138582&view=auto
==============================================================================
--- cfe/trunk/include/clang/Serialization/ModuleManager.h (added)
+++ cfe/trunk/include/clang/Serialization/ModuleManager.h Thu Aug 25 15:47:51 2011
@@ -0,0 +1,153 @@
+//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the ModuleManager class, which manages a set of loaded
+//  modules for the ASTReader.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H
+#define LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H
+
+#include "clang/Serialization/Module.h"
+#include "clang/Basic/FileManager.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang { 
+
+namespace serialization {
+  
+/// \brief Manages the set of modules loaded by an AST reader.
+class ModuleManager {
+  /// \brief The chain of AST files. The first entry is the one named by the
+  /// user, the last one is the one that doesn't depend on anything further.
+  llvm::SmallVector<Module*, 2> Chain;
+  
+  /// \brief All loaded modules, indexed by name.
+  llvm::DenseMap<const FileEntry *, Module *> Modules;
+  
+  /// \brief FileManager that handles translating between filenames and
+  /// FileEntry *.
+  FileManager FileMgr;
+  
+  /// \brief A lookup of in-memory (virtual file) buffers
+  llvm::DenseMap<const FileEntry *, llvm::MemoryBuffer *> InMemoryBuffers;
+  
+public:
+  typedef SmallVector<Module*, 2>::iterator ModuleIterator;
+  typedef SmallVector<Module*, 2>::const_iterator ModuleConstIterator;
+  typedef SmallVector<Module*, 2>::reverse_iterator ModuleReverseIterator;
+  typedef std::pair<uint32_t, StringRef> ModuleOffset;
+  
+  ModuleManager(const FileSystemOptions &FSO);
+  ~ModuleManager();
+  
+  /// \brief Forward iterator to traverse all loaded modules.  This is reverse
+  /// source-order.
+  ModuleIterator begin() { return Chain.begin(); }
+  /// \brief Forward iterator end-point to traverse all loaded modules
+  ModuleIterator end() { return Chain.end(); }
+  
+  /// \brief Const forward iterator to traverse all loaded modules.  This is 
+  /// in reverse source-order.
+  ModuleConstIterator begin() const { return Chain.begin(); }
+  /// \brief Const forward iterator end-point to traverse all loaded modules
+  ModuleConstIterator end() const { return Chain.end(); }
+  
+  /// \brief Reverse iterator to traverse all loaded modules.  This is in 
+  /// source order.
+  ModuleReverseIterator rbegin() { return Chain.rbegin(); }
+  /// \brief Reverse iterator end-point to traverse all loaded modules.
+  ModuleReverseIterator rend() { return Chain.rend(); }
+  
+  /// \brief Returns the primary module associated with the manager, that is,
+  /// the first module loaded
+  Module &getPrimaryModule() { return *Chain[0]; }
+  
+  /// \brief Returns the primary module associated with the manager, that is,
+  /// the first module loaded.
+  Module &getPrimaryModule() const { return *Chain[0]; }
+  
+  /// \brief Returns the module associated with the given index
+  Module &operator[](unsigned Index) const { return *Chain[Index]; }
+  
+  /// \brief Returns the module associated with the given name
+  Module *lookup(StringRef Name);
+  
+  /// \brief Returns the in-memory (virtual file) buffer with the given name
+  llvm::MemoryBuffer *lookupBuffer(StringRef Name);
+  
+  /// \brief Number of modules loaded
+  unsigned size() const { return Chain.size(); }
+  /// \brief Attempts to create a new module and add it to the list of known
+  /// modules.
+  ///
+  /// \param FileName The file name of the module to be loaded.
+  ///
+  /// \param Type The kind of module being loaded.
+  ///
+  /// \param ImportedBy The module that is importing this module, or NULL if
+  /// this module is imported directly by the user.
+  ///
+  /// \param ErrorStr Will be set to a non-empty string if any errors occurred
+  /// while trying to load the module.
+  ///
+  /// \return A pointer to the module that corresponds to this file name,
+  /// and a boolean indicating whether the module was newly added.
+  std::pair<Module *, bool> 
+  addModule(StringRef FileName, ModuleKind Type, Module *ImportedBy,
+            std::string &ErrorStr);
+  
+  /// \brief Add an in-memory buffer the list of known buffers
+  void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer);
+  
+  /// \brief Visit each of the modules.
+  ///
+  /// This routine visits each of the modules, starting with the
+  /// "root" modules that no other loaded modules depend on, and
+  /// proceeding to the leaf modules, visiting each module only once
+  /// during the traversal.
+  ///
+  /// This traversal is intended to support various "lookup"
+  /// operations that can find data in any of the loaded modules.
+  ///
+  /// \param Visitor A visitor function that will be invoked with each
+  /// module and the given user data pointer. The return value must be
+  /// convertible to bool; when false, the visitation continues to
+  /// modules that the current module depends on. When true, the
+  /// visitation skips any modules that the current module depends on.
+  ///
+  /// \param UserData User data associated with the visitor object, which
+  /// will be passed along to the visitor.
+  void visit(bool (*Visitor)(Module &M, void *UserData), void *UserData);
+  
+  /// \brief Visit each of the modules with a depth-first traversal.
+  ///
+  /// This routine visits each of the modules known to the module
+  /// manager using a depth-first search, starting with the first
+  /// loaded module. The traversal invokes the callback both before
+  /// traversing the children (preorder traversal) and after
+  /// traversing the children (postorder traversal).
+  ///
+  /// \param Visitor A visitor function that will be invoked with each
+  /// module and given a \c Preorder flag that indicates whether we're
+  /// visiting the module before or after visiting its children.  The
+  /// visitor may return true at any time to abort the depth-first
+  /// visitation.
+  ///
+  /// \param UserData User data ssociated with the visitor object,
+  /// which will be passed along to the user.
+  void visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, 
+                                       void *UserData), 
+                       void *UserData);
+};
+
+} } // end namespace clang::serialization
+
+#endif

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=138582&r1=138581&r2=138582&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Aug 25 15:47:51 2011
@@ -13,7 +13,9 @@
 
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Serialization/ModuleManager.h"
 #include "ASTCommon.h"
+#include "ASTReaderInternals.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Sema/Sema.h"
@@ -52,6 +54,7 @@
 
 using namespace clang;
 using namespace clang::serialization;
+using namespace clang::serialization::reader;
 
 //===----------------------------------------------------------------------===//
 // PCH validator implementation
@@ -479,425 +482,321 @@
 }
 
 
-namespace {
-class ASTSelectorLookupTrait {
-  ASTReader &Reader;
-  Module &F;
-  
-public:
-  struct data_type {
-    SelectorID ID;
-    llvm::SmallVector<ObjCMethodDecl *, 2> Instance;
-    llvm::SmallVector<ObjCMethodDecl *, 2> Factory;
-  };
-
-  typedef Selector external_key_type;
-  typedef external_key_type internal_key_type;
-
-  ASTSelectorLookupTrait(ASTReader &Reader, Module &F) 
-    : Reader(Reader), F(F) { }
-
-  static bool EqualKey(const internal_key_type& a,
-                       const internal_key_type& b) {
-    return a == b;
-  }
-
-  static unsigned ComputeHash(Selector Sel) {
-    return serialization::ComputeHash(Sel);
-  }
-
-  // This hopefully will just get inlined and removed by the optimizer.
-  static const internal_key_type&
-  GetInternalKey(const external_key_type& x) { return x; }
-
-  static std::pair<unsigned, unsigned>
-  ReadKeyDataLength(const unsigned char*& d) {
-    using namespace clang::io;
-    unsigned KeyLen = ReadUnalignedLE16(d);
-    unsigned DataLen = ReadUnalignedLE16(d);
-    return std::make_pair(KeyLen, DataLen);
-  }
-
-  internal_key_type ReadKey(const unsigned char* d, unsigned) {
-    using namespace clang::io;
-    SelectorTable &SelTable = Reader.getContext()->Selectors;
-    unsigned N = ReadUnalignedLE16(d);
-    IdentifierInfo *FirstII
-      = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
-    if (N == 0)
-      return SelTable.getNullarySelector(FirstII);
-    else if (N == 1)
-      return SelTable.getUnarySelector(FirstII);
-
-    SmallVector<IdentifierInfo *, 16> Args;
-    Args.push_back(FirstII);
-    for (unsigned I = 1; I != N; ++I)
-      Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));
-
-    return SelTable.getSelector(N, Args.data());
-  }
-
-  data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
-    using namespace clang::io;
-
-    data_type Result;
-
-    Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
-    unsigned NumInstanceMethods = ReadUnalignedLE16(d);
-    unsigned NumFactoryMethods = ReadUnalignedLE16(d);
-
-    // Load instance methods
-    ObjCMethodList *Prev = 0;
-    for (unsigned I = 0; I != NumInstanceMethods; ++I) {
-      if (ObjCMethodDecl *Method
-            = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
-        Result.Instance.push_back(Method);
-    }
-
-    // Load factory methods
-    Prev = 0;
-    for (unsigned I = 0; I != NumFactoryMethods; ++I) {
-      if (ObjCMethodDecl *Method
-            = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
-        Result.Factory.push_back(Method);
-    }
-
-    return Result;
-  }
-};
-
-} // end anonymous namespace
-
-/// \brief The on-disk hash table used for the global method pool.
-typedef OnDiskChainedHashTable<ASTSelectorLookupTrait>
-  ASTSelectorLookupTable;
 
-namespace clang {
-class ASTIdentifierLookupTrait {
-  ASTReader &Reader;
-  Module &F;
-
-  // If we know the IdentifierInfo in advance, it is here and we will
-  // not build a new one. Used when deserializing information about an
-  // identifier that was constructed before the AST file was read.
-  IdentifierInfo *KnownII;
-
-public:
-  typedef IdentifierInfo * data_type;
-
-  typedef const std::pair<const char*, unsigned> external_key_type;
-
-  typedef external_key_type internal_key_type;
-
-  ASTIdentifierLookupTrait(ASTReader &Reader, Module &F,
-                           IdentifierInfo *II = 0)
-    : Reader(Reader), F(F), KnownII(II) { }
-
-  static bool EqualKey(const internal_key_type& a,
-                       const internal_key_type& b) {
-    return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
-                                  : false;
-  }
-
-  static unsigned ComputeHash(const internal_key_type& a) {
-    return llvm::HashString(StringRef(a.first, a.second));
-  }
-
-  // This hopefully will just get inlined and removed by the optimizer.
-  static const internal_key_type&
-  GetInternalKey(const external_key_type& x) { return x; }
-
-  // This hopefully will just get inlined and removed by the optimizer.
-  static const external_key_type&
-  GetExternalKey(const internal_key_type& x) { return x; }
+unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
+  return serialization::ComputeHash(Sel);
+}
 
-  static std::pair<unsigned, unsigned>
-  ReadKeyDataLength(const unsigned char*& d) {
-    using namespace clang::io;
-    unsigned DataLen = ReadUnalignedLE16(d);
-    unsigned KeyLen = ReadUnalignedLE16(d);
-    return std::make_pair(KeyLen, DataLen);
-  }
 
-  static std::pair<const char*, unsigned>
-  ReadKey(const unsigned char* d, unsigned n) {
-    assert(n >= 2 && d[n-1] == '\0');
-    return std::make_pair((const char*) d, n-1);
+std::pair<unsigned, unsigned>
+ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+  using namespace clang::io;
+  unsigned KeyLen = ReadUnalignedLE16(d);
+  unsigned DataLen = ReadUnalignedLE16(d);
+  return std::make_pair(KeyLen, DataLen);
+}
+
+ASTSelectorLookupTrait::internal_key_type 
+ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+  using namespace clang::io;
+  SelectorTable &SelTable = Reader.getContext()->Selectors;
+  unsigned N = ReadUnalignedLE16(d);
+  IdentifierInfo *FirstII
+    = Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+  if (N == 0)
+    return SelTable.getNullarySelector(FirstII);
+  else if (N == 1)
+    return SelTable.getUnarySelector(FirstII);
+
+  SmallVector<IdentifierInfo *, 16> Args;
+  Args.push_back(FirstII);
+  for (unsigned I = 1; I != N; ++I)
+    Args.push_back(Reader.getLocalIdentifier(F, ReadUnalignedLE32(d)));
+
+  return SelTable.getSelector(N, Args.data());
+}
+
+ASTSelectorLookupTrait::data_type 
+ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d, 
+                                 unsigned DataLen) {
+  using namespace clang::io;
+
+  data_type Result;
+
+  Result.ID = Reader.getGlobalSelectorID(F, ReadUnalignedLE32(d));
+  unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+  unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
+  // Load instance methods
+  ObjCMethodList *Prev = 0;
+  for (unsigned I = 0; I != NumInstanceMethods; ++I) {
+    if (ObjCMethodDecl *Method
+          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+      Result.Instance.push_back(Method);
+  }
+
+  // Load factory methods
+  Prev = 0;
+  for (unsigned I = 0; I != NumFactoryMethods; ++I) {
+    if (ObjCMethodDecl *Method
+          = Reader.GetLocalDeclAs<ObjCMethodDecl>(F, ReadUnalignedLE32(d)))
+      Result.Factory.push_back(Method);
   }
 
-  IdentifierInfo *ReadData(const internal_key_type& k,
-                           const unsigned char* d,
-                           unsigned DataLen) {
-    using namespace clang::io;
-    unsigned RawID = ReadUnalignedLE32(d);
-    bool IsInteresting = RawID & 0x01;
-
-    // Wipe out the "is interesting" bit.
-    RawID = RawID >> 1;
-
-    IdentID ID = Reader.getGlobalIdentifierID(F, RawID);
-    if (!IsInteresting) {
-      // For uninteresting identifiers, just build the IdentifierInfo
-      // and associate it with the persistent ID.
-      IdentifierInfo *II = KnownII;
-      if (!II)
-        II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
-      Reader.SetIdentifierInfo(ID, II);
-      II->setIsFromAST();
-      return II;
-    }
-
-    unsigned Bits = ReadUnalignedLE16(d);
-    bool CPlusPlusOperatorKeyword = Bits & 0x01;
-    Bits >>= 1;
-    bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
-    Bits >>= 1;
-    bool Poisoned = Bits & 0x01;
-    Bits >>= 1;
-    bool ExtensionToken = Bits & 0x01;
-    Bits >>= 1;
-    bool hasMacroDefinition = Bits & 0x01;
-    Bits >>= 1;
-    unsigned ObjCOrBuiltinID = Bits & 0x3FF;
-    Bits >>= 10;
+  return Result;
+}
 
-    assert(Bits == 0 && "Extra bits in the identifier?");
-    DataLen -= 6;
+unsigned ASTIdentifierLookupTrait::ComputeHash(const internal_key_type& a) {
+  return llvm::HashString(StringRef(a.first, a.second));
+}
 
-    // Build the IdentifierInfo itself and link the identifier ID with
-    // the new IdentifierInfo.
+std::pair<unsigned, unsigned>
+ASTIdentifierLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+  using namespace clang::io;
+  unsigned DataLen = ReadUnalignedLE16(d);
+  unsigned KeyLen = ReadUnalignedLE16(d);
+  return std::make_pair(KeyLen, DataLen);
+}
+
+std::pair<const char*, unsigned>
+ASTIdentifierLookupTrait::ReadKey(const unsigned char* d, unsigned n) {
+  assert(n >= 2 && d[n-1] == '\0');
+  return std::make_pair((const char*) d, n-1);
+}
+
+IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
+                                                   const unsigned char* d,
+                                                   unsigned DataLen) {
+  using namespace clang::io;
+  unsigned RawID = ReadUnalignedLE32(d);
+  bool IsInteresting = RawID & 0x01;
+
+  // Wipe out the "is interesting" bit.
+  RawID = RawID >> 1;
+
+  IdentID ID = Reader.getGlobalIdentifierID(F, RawID);
+  if (!IsInteresting) {
+    // For uninteresting identifiers, just build the IdentifierInfo
+    // and associate it with the persistent ID.
     IdentifierInfo *II = KnownII;
     if (!II)
       II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
     Reader.SetIdentifierInfo(ID, II);
-
-    // Set or check the various bits in the IdentifierInfo structure.
-    // Token IDs are read-only.
-    if (HasRevertedTokenIDToIdentifier)
-      II->RevertTokenIDToIdentifier();
-    II->setObjCOrBuiltinID(ObjCOrBuiltinID);
-    assert(II->isExtensionToken() == ExtensionToken &&
-           "Incorrect extension token flag");
-    (void)ExtensionToken;
-    if (Poisoned)
-      II->setIsPoisoned(true);
-    assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
-           "Incorrect C++ operator keyword flag");
-    (void)CPlusPlusOperatorKeyword;
-
-    // If this identifier is a macro, deserialize the macro
-    // definition.
-    if (hasMacroDefinition) {
-      // FIXME: Check for conflicts?
-      uint32_t Offset = ReadUnalignedLE32(d);
-      Reader.SetIdentifierIsMacro(II, F, Offset);
-      DataLen -= 4;
-    }
-
-    // Read all of the declarations visible at global scope with this
-    // name.
-    if (Reader.getContext() == 0) return II;
-    if (DataLen > 0) {
-      SmallVector<uint32_t, 4> DeclIDs;
-      for (; DataLen > 0; DataLen -= 4)
-        DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));
-      Reader.SetGloballyVisibleDecls(II, DeclIDs);
-    }
-
     II->setIsFromAST();
     return II;
   }
-};
-
-} // end anonymous namespace
 
-/// \brief The on-disk hash table used to contain information about
-/// all of the identifiers in the program.
-typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
-  ASTIdentifierLookupTable;
+  unsigned Bits = ReadUnalignedLE16(d);
+  bool CPlusPlusOperatorKeyword = Bits & 0x01;
+  Bits >>= 1;
+  bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
+  Bits >>= 1;
+  bool Poisoned = Bits & 0x01;
+  Bits >>= 1;
+  bool ExtensionToken = Bits & 0x01;
+  Bits >>= 1;
+  bool hasMacroDefinition = Bits & 0x01;
+  Bits >>= 1;
+  unsigned ObjCOrBuiltinID = Bits & 0x3FF;
+  Bits >>= 10;
+
+  assert(Bits == 0 && "Extra bits in the identifier?");
+  DataLen -= 6;
+
+  // Build the IdentifierInfo itself and link the identifier ID with
+  // the new IdentifierInfo.
+  IdentifierInfo *II = KnownII;
+  if (!II)
+    II = &Reader.getIdentifierTable().getOwn(StringRef(k.first, k.second));
+  Reader.SetIdentifierInfo(ID, II);
+
+  // Set or check the various bits in the IdentifierInfo structure.
+  // Token IDs are read-only.
+  if (HasRevertedTokenIDToIdentifier)
+    II->RevertTokenIDToIdentifier();
+  II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+  assert(II->isExtensionToken() == ExtensionToken &&
+         "Incorrect extension token flag");
+  (void)ExtensionToken;
+  if (Poisoned)
+    II->setIsPoisoned(true);
+  assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
+         "Incorrect C++ operator keyword flag");
+  (void)CPlusPlusOperatorKeyword;
+
+  // If this identifier is a macro, deserialize the macro
+  // definition.
+  if (hasMacroDefinition) {
+    // FIXME: Check for conflicts?
+    uint32_t Offset = ReadUnalignedLE32(d);
+    Reader.SetIdentifierIsMacro(II, F, Offset);
+    DataLen -= 4;
+  }
+
+  // Read all of the declarations visible at global scope with this
+  // name.
+  if (Reader.getContext() == 0) return II;
+  if (DataLen > 0) {
+    SmallVector<uint32_t, 4> DeclIDs;
+    for (; DataLen > 0; DataLen -= 4)
+      DeclIDs.push_back(Reader.getGlobalDeclID(F, ReadUnalignedLE32(d)));
+    Reader.SetGloballyVisibleDecls(II, DeclIDs);
+  }
+
+  II->setIsFromAST();
+  return II;
+}
+
+unsigned 
+ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
+  llvm::FoldingSetNodeID ID;
+  ID.AddInteger(Key.Kind);
 
-namespace {
-class ASTDeclContextNameLookupTrait {
-  ASTReader &Reader;
-  Module &F;
-  
-public:
-  /// \brief Pair of begin/end iterators for DeclIDs.
-  ///
-  /// Note that these declaration IDs are local to the module that contains this
-  /// particular lookup t
-  typedef std::pair<DeclID *, DeclID *> data_type;
-
-  /// \brief Special internal key for declaration names.
-  /// The hash table creates keys for comparison; we do not create
-  /// a DeclarationName for the internal key to avoid deserializing types.
-  struct DeclNameKey {
-    DeclarationName::NameKind Kind;
-    uint64_t Data;
-    DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { }
-  };
-
-  typedef DeclarationName external_key_type;
-  typedef DeclNameKey internal_key_type;
-
-  explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, 
-                                         Module &F) 
-    : Reader(Reader), F(F) { }
-
-  static bool EqualKey(const internal_key_type& a,
-                       const internal_key_type& b) {
-    return a.Kind == b.Kind && a.Data == b.Data;
-  }
-
-  unsigned ComputeHash(const DeclNameKey &Key) const {
-    llvm::FoldingSetNodeID ID;
-    ID.AddInteger(Key.Kind);
-
-    switch (Key.Kind) {
-    case DeclarationName::Identifier:
-    case DeclarationName::CXXLiteralOperatorName:
-      ID.AddString(((IdentifierInfo*)Key.Data)->getName());
-      break;
-    case DeclarationName::ObjCZeroArgSelector:
-    case DeclarationName::ObjCOneArgSelector:
-    case DeclarationName::ObjCMultiArgSelector:
-      ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
-      break;
-    case DeclarationName::CXXOperatorName:
-      ID.AddInteger((OverloadedOperatorKind)Key.Data);
-      break;
-    case DeclarationName::CXXConstructorName:
-    case DeclarationName::CXXDestructorName:
-    case DeclarationName::CXXConversionFunctionName:
-    case DeclarationName::CXXUsingDirective:
-      break;
-    }
-
-    return ID.ComputeHash();
+  switch (Key.Kind) {
+  case DeclarationName::Identifier:
+  case DeclarationName::CXXLiteralOperatorName:
+    ID.AddString(((IdentifierInfo*)Key.Data)->getName());
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
+    break;
+  case DeclarationName::CXXOperatorName:
+    ID.AddInteger((OverloadedOperatorKind)Key.Data);
+    break;
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXUsingDirective:
+    break;
   }
 
-  internal_key_type GetInternalKey(const external_key_type& Name) const {
-    DeclNameKey Key;
-    Key.Kind = Name.getNameKind();
-    switch (Name.getNameKind()) {
-    case DeclarationName::Identifier:
-      Key.Data = (uint64_t)Name.getAsIdentifierInfo();
-      break;
-    case DeclarationName::ObjCZeroArgSelector:
-    case DeclarationName::ObjCOneArgSelector:
-    case DeclarationName::ObjCMultiArgSelector:
-      Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
-      break;
-    case DeclarationName::CXXOperatorName:
-      Key.Data = Name.getCXXOverloadedOperator();
-      break;
-    case DeclarationName::CXXLiteralOperatorName:
-      Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
-      break;
-    case DeclarationName::CXXConstructorName:
-    case DeclarationName::CXXDestructorName:
-    case DeclarationName::CXXConversionFunctionName:
-    case DeclarationName::CXXUsingDirective:
-      Key.Data = 0;
-      break;
-    }
+  return ID.ComputeHash();
+}
 
-    return Key;
+ASTDeclContextNameLookupTrait::internal_key_type 
+ASTDeclContextNameLookupTrait::GetInternalKey(
+                                          const external_key_type& Name) const {
+  DeclNameKey Key;
+  Key.Kind = Name.getNameKind();
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+    Key.Data = (uint64_t)Name.getAsIdentifierInfo();
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
+    break;
+  case DeclarationName::CXXOperatorName:
+    Key.Data = Name.getCXXOverloadedOperator();
+    break;
+  case DeclarationName::CXXLiteralOperatorName:
+    Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
+    break;
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXUsingDirective:
+    Key.Data = 0;
+    break;
   }
 
-  external_key_type GetExternalKey(const internal_key_type& Key) const {
-    ASTContext *Context = Reader.getContext();
-    switch (Key.Kind) {
-    case DeclarationName::Identifier:
-      return DeclarationName((IdentifierInfo*)Key.Data);
-
-    case DeclarationName::ObjCZeroArgSelector:
-    case DeclarationName::ObjCOneArgSelector:
-    case DeclarationName::ObjCMultiArgSelector:
-      return DeclarationName(Selector(Key.Data));
+  return Key;
+}
 
-    case DeclarationName::CXXConstructorName:
-      return Context->DeclarationNames.getCXXConstructorName(
-               Context->getCanonicalType(Reader.getLocalType(F, Key.Data)));
+ASTDeclContextNameLookupTrait::external_key_type 
+ASTDeclContextNameLookupTrait::GetExternalKey(
+                                          const internal_key_type& Key) const {
+  ASTContext *Context = Reader.getContext();
+  switch (Key.Kind) {
+  case DeclarationName::Identifier:
+    return DeclarationName((IdentifierInfo*)Key.Data);
 
-    case DeclarationName::CXXDestructorName:
-      return Context->DeclarationNames.getCXXDestructorName(
-               Context->getCanonicalType(Reader.getLocalType(F, Key.Data)));
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    return DeclarationName(Selector(Key.Data));
 
-    case DeclarationName::CXXConversionFunctionName:
-      return Context->DeclarationNames.getCXXConversionFunctionName(
-               Context->getCanonicalType(Reader.getLocalType(F, Key.Data)));
+  case DeclarationName::CXXConstructorName:
+    return Context->DeclarationNames.getCXXConstructorName(
+             Context->getCanonicalType(Reader.getLocalType(F, Key.Data)));
 
-    case DeclarationName::CXXOperatorName:
-      return Context->DeclarationNames.getCXXOperatorName(
-                                         (OverloadedOperatorKind)Key.Data);
+  case DeclarationName::CXXDestructorName:
+    return Context->DeclarationNames.getCXXDestructorName(
+             Context->getCanonicalType(Reader.getLocalType(F, Key.Data)));
 
-    case DeclarationName::CXXLiteralOperatorName:
-      return Context->DeclarationNames.getCXXLiteralOperatorName(
-                                                     (IdentifierInfo*)Key.Data);
+  case DeclarationName::CXXConversionFunctionName:
+    return Context->DeclarationNames.getCXXConversionFunctionName(
+             Context->getCanonicalType(Reader.getLocalType(F, Key.Data)));
 
-    case DeclarationName::CXXUsingDirective:
-      return DeclarationName::getUsingDirectiveName();
-    }
+  case DeclarationName::CXXOperatorName:
+    return Context->DeclarationNames.getCXXOperatorName(
+                                       (OverloadedOperatorKind)Key.Data);
 
-    llvm_unreachable("Invalid Name Kind ?");
-  }
+  case DeclarationName::CXXLiteralOperatorName:
+    return Context->DeclarationNames.getCXXLiteralOperatorName(
+                                                   (IdentifierInfo*)Key.Data);
 
-  static std::pair<unsigned, unsigned>
-  ReadKeyDataLength(const unsigned char*& d) {
-    using namespace clang::io;
-    unsigned KeyLen = ReadUnalignedLE16(d);
-    unsigned DataLen = ReadUnalignedLE16(d);
-    return std::make_pair(KeyLen, DataLen);
+  case DeclarationName::CXXUsingDirective:
+    return DeclarationName::getUsingDirectiveName();
   }
 
-  internal_key_type ReadKey(const unsigned char* d, unsigned) {
-    using namespace clang::io;
+  llvm_unreachable("Invalid Name Kind ?");
+}
 
-    DeclNameKey Key;
-    Key.Kind = (DeclarationName::NameKind)*d++;
-    switch (Key.Kind) {
-    case DeclarationName::Identifier:
-      Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
-      break;
-    case DeclarationName::ObjCZeroArgSelector:
-    case DeclarationName::ObjCOneArgSelector:
-    case DeclarationName::ObjCMultiArgSelector:
-      Key.Data =
-         (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))
-                     .getAsOpaquePtr();
-      break;
-    case DeclarationName::CXXOperatorName:
-      Key.Data = *d++; // OverloadedOperatorKind
-      break;
-    case DeclarationName::CXXLiteralOperatorName:
-      Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
-      break;
-    case DeclarationName::CXXConstructorName:
-    case DeclarationName::CXXDestructorName:
-    case DeclarationName::CXXConversionFunctionName:
-    case DeclarationName::CXXUsingDirective:
-      Key.Data = 0;
-      break;
-    }
+std::pair<unsigned, unsigned>
+ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+  using namespace clang::io;
+  unsigned KeyLen = ReadUnalignedLE16(d);
+  unsigned DataLen = ReadUnalignedLE16(d);
+  return std::make_pair(KeyLen, DataLen);
+}
 
-    return Key;
-  }
+ASTDeclContextNameLookupTrait::internal_key_type 
+ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+  using namespace clang::io;
 
-  data_type ReadData(internal_key_type, const unsigned char* d,
-                     unsigned DataLen) {
-    using namespace clang::io;
-    unsigned NumDecls = ReadUnalignedLE16(d);
-    DeclID *Start = (DeclID *)d;
-    return std::make_pair(Start, Start + NumDecls);
+  DeclNameKey Key;
+  Key.Kind = (DeclarationName::NameKind)*d++;
+  switch (Key.Kind) {
+  case DeclarationName::Identifier:
+    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+    break;
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    Key.Data =
+       (uint64_t)Reader.getLocalSelector(F, ReadUnalignedLE32(d))
+                   .getAsOpaquePtr();
+    break;
+  case DeclarationName::CXXOperatorName:
+    Key.Data = *d++; // OverloadedOperatorKind
+    break;
+  case DeclarationName::CXXLiteralOperatorName:
+    Key.Data = (uint64_t)Reader.getLocalIdentifier(F, ReadUnalignedLE32(d));
+    break;
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+  case DeclarationName::CXXUsingDirective:
+    Key.Data = 0;
+    break;
   }
-};
 
-} // end anonymous namespace
+  return Key;
+}
 
-/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
-typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
-  ASTDeclContextNameLookupTable;
+ASTDeclContextNameLookupTrait::data_type 
+ASTDeclContextNameLookupTrait::ReadData(internal_key_type, 
+                                        const unsigned char* d,
+                                      unsigned DataLen) {
+  using namespace clang::io;
+  unsigned NumDecls = ReadUnalignedLE16(d);
+  DeclID *Start = (DeclID *)d;
+  return std::make_pair(Start, Start + NumDecls);
+}
 
 bool ASTReader::ReadDeclContextStorage(Module &M,
                                        llvm::BitstreamCursor &Cursor,
@@ -1631,116 +1530,65 @@
   return LocalID + I->second;
 }
 
-namespace {
-  /// \brief Trait class used to search the on-disk hash table containing all of
-  /// the header search information.
-  ///
-  /// The on-disk hash table contains a mapping from each header path to 
-  /// information about that header (how many times it has been included, its
-  /// controlling macro, etc.). Note that we actually hash based on the 
-  /// filename, and support "deep" comparisons of file names based on current
-  /// inode numbers, so that the search can cope with non-normalized path names
-  /// and symlinks.
-  class HeaderFileInfoTrait {
-    ASTReader &Reader;
-    Module &M;
-    HeaderSearch *HS;
-    const char *FrameworkStrings;
-    const char *SearchPath;
-    struct stat SearchPathStatBuf;
-    llvm::Optional<int> SearchPathStatResult;
-    
-    int StatSimpleCache(const char *Path, struct stat *StatBuf) {
-      if (Path == SearchPath) {
-        if (!SearchPathStatResult)
-          SearchPathStatResult = stat(Path, &SearchPathStatBuf);
-        
-        *StatBuf = SearchPathStatBuf;
-        return *SearchPathStatResult;
-      }
-      
-      return stat(Path, StatBuf);
-    }
-    
-  public:
-    typedef const char *external_key_type;
-    typedef const char *internal_key_type;
-    
-    typedef HeaderFileInfo data_type;
-    
-    HeaderFileInfoTrait(ASTReader &Reader, Module &M, HeaderSearch *HS,
-                        const char *FrameworkStrings,
-                        const char *SearchPath = 0) 
-      : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings), 
-        SearchPath(SearchPath) { }
-    
-    static unsigned ComputeHash(const char *path) {
-      return llvm::HashString(llvm::sys::path::filename(path));
-    }
+unsigned HeaderFileInfoTrait::ComputeHash(const char *path) {
+  return llvm::HashString(llvm::sys::path::filename(path));
+}
     
-    static internal_key_type GetInternalKey(const char *path) { return path; }
+HeaderFileInfoTrait::internal_key_type 
+HeaderFileInfoTrait::GetInternalKey(const char *path) { return path; }
     
-    bool EqualKey(internal_key_type a, internal_key_type b) {
-      if (strcmp(a, b) == 0)
-        return true;
-      
-      if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))
-        return false;
-      
-      // The file names match, but the path names don't. stat() the files to
-      // see if they are the same.      
-      struct stat StatBufA, StatBufB;
-      if (StatSimpleCache(a, &StatBufA) || StatSimpleCache(b, &StatBufB))
-        return false;
-      
-      return StatBufA.st_ino == StatBufB.st_ino;
-    }
-    
-    static std::pair<unsigned, unsigned>
-    ReadKeyDataLength(const unsigned char*& d) {
-      unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
-      unsigned DataLen = (unsigned) *d++;
-      return std::make_pair(KeyLen + 1, DataLen);
-    }
+bool HeaderFileInfoTrait::EqualKey(internal_key_type a, internal_key_type b) {
+  if (strcmp(a, b) == 0)
+    return true;
+  
+  if (llvm::sys::path::filename(a) != llvm::sys::path::filename(b))
+    return false;
+  
+  // The file names match, but the path names don't. stat() the files to
+  // see if they are the same.      
+  struct stat StatBufA, StatBufB;
+  if (StatSimpleCache(a, &StatBufA) || StatSimpleCache(b, &StatBufB))
+    return false;
+  
+  return StatBufA.st_ino == StatBufB.st_ino;
+}
     
-    static internal_key_type ReadKey(const unsigned char *d, unsigned) {
-      return (const char *)d;
-    }
+std::pair<unsigned, unsigned>
+HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
+  unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
+  unsigned DataLen = (unsigned) *d++;
+  return std::make_pair(KeyLen + 1, DataLen);
+}
     
-    data_type ReadData(const internal_key_type, const unsigned char *d,
-                       unsigned DataLen) {
-      const unsigned char *End = d + DataLen;
-      using namespace clang::io;
-      HeaderFileInfo HFI;
-      unsigned Flags = *d++;
-      HFI.isImport = (Flags >> 5) & 0x01;
-      HFI.isPragmaOnce = (Flags >> 4) & 0x01;
-      HFI.DirInfo = (Flags >> 2) & 0x03;
-      HFI.Resolved = (Flags >> 1) & 0x01;
-      HFI.IndexHeaderMapHeader = Flags & 0x01;
-      HFI.NumIncludes = ReadUnalignedLE16(d);
-      HFI.ControllingMacroID = Reader.getGlobalDeclID(M, ReadUnalignedLE32(d));
-      if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {
-        // The framework offset is 1 greater than the actual offset, 
-        // since 0 is used as an indicator for "no framework name".
-        StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
-        HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
-      }
-      
-      assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
-      (void)End;
-            
-      // This HeaderFileInfo was externally loaded.
-      HFI.External = true;
-      return HFI;
-    }
-  };
+HeaderFileInfoTrait::data_type 
+HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,
+                              unsigned DataLen) {
+  const unsigned char *End = d + DataLen;
+  using namespace clang::io;
+  HeaderFileInfo HFI;
+  unsigned Flags = *d++;
+  HFI.isImport = (Flags >> 5) & 0x01;
+  HFI.isPragmaOnce = (Flags >> 4) & 0x01;
+  HFI.DirInfo = (Flags >> 2) & 0x03;
+  HFI.Resolved = (Flags >> 1) & 0x01;
+  HFI.IndexHeaderMapHeader = Flags & 0x01;
+  HFI.NumIncludes = ReadUnalignedLE16(d);
+  HFI.ControllingMacroID = Reader.getGlobalDeclID(M, ReadUnalignedLE32(d));
+  if (unsigned FrameworkOffset = ReadUnalignedLE32(d)) {
+    // The framework offset is 1 greater than the actual offset, 
+    // since 0 is used as an indicator for "no framework name".
+    StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
+    HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
+  }
+  
+  assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
+  (void)End;
+        
+  // This HeaderFileInfo was externally loaded.
+  HFI.External = true;
+  return HFI;
 }
 
-/// \brief The on-disk hash table used for the global method pool.
-typedef OnDiskChainedHashTable<HeaderFileInfoTrait>
-  HeaderFileInfoLookupTable;
-
 void ASTReader::SetIdentifierIsMacro(IdentifierInfo *II, Module &F,
                                      uint64_t LocalOffset) {
   // Note that this identifier has a macro definition.
@@ -5718,291 +5566,3 @@
       delete static_cast<ASTDeclContextNameLookupTable*>(J->first);
   }
 }
-
-//===----------------------------------------------------------------------===//
-// Module implementation
-//===----------------------------------------------------------------------===//
-Module::Module(ModuleKind Kind)
-  : Kind(Kind), DirectlyImported(false), SizeInBits(0), 
-    LocalNumSLocEntries(0), SLocEntryBaseID(0),
-    SLocEntryBaseOffset(0), SLocEntryOffsets(0),
-    SLocFileOffsets(0), LocalNumIdentifiers(0), 
-    IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0),
-    IdentifierLookupTable(0), BasePreprocessedEntityID(0),
-    LocalNumMacroDefinitions(0), MacroDefinitionOffsets(0), 
-    BaseMacroDefinitionID(0), LocalNumHeaderFileInfos(0), 
-    HeaderFileInfoTableData(0), HeaderFileInfoTable(0),
-    HeaderFileFrameworkStrings(0),
-    LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0),
-    SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
-    DeclOffsets(0), BaseDeclID(0),
-    LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
-    LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0),
-    NumPreallocatedPreprocessingEntities(0)
-{}
-
-Module::~Module() {
-  for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(),
-                                     E = DeclContextInfos.end();
-       I != E; ++I) {
-    if (I->second.NameLookupTableData)
-      delete static_cast<ASTDeclContextNameLookupTable*>(
-               I->second.NameLookupTableData);
-  }
-
-  delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
-  delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
-  delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
-}
-
-template<typename Key, typename Offset, unsigned InitialCapacity>
-static void 
-dumpLocalRemap(StringRef Name,
-               const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) {
-  if (Map.begin() == Map.end())
-    return;
-  
-  typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType;
-  llvm::errs() << "  " << Name << ":\n";
-  for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); 
-       I != IEnd; ++I) {
-    llvm::errs() << "    " << I->first << " -> " << I->second
-    << "\n";
-  }
-}
-
-void Module::dump() {
-  llvm::errs() << "\nModule: " << FileName << "\n";
-  if (!Imports.empty()) {
-    llvm::errs() << "  Imports: ";
-    for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
-      if (I)
-        llvm::errs() << ", ";
-      llvm::errs() << Imports[I]->FileName;
-    }
-    llvm::errs() << "\n";
-  }
-  
-  // Remapping tables.
-  llvm::errs() << "  Base source location offset: " << SLocEntryBaseOffset 
-               << '\n';
-  dumpLocalRemap("Source location offset local -> global map", SLocRemap);
-  
-  llvm::errs() << "  Base identifier ID: " << BaseIdentifierID << '\n'
-               << "  Number of identifiers: " << LocalNumIdentifiers << '\n';
-  dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap);
-  
-  llvm::errs() << "  Base selector ID: " << BaseSelectorID << '\n'
-               << "  Number of selectors: " << LocalNumSelectors << '\n';
-  dumpLocalRemap("Selector ID local -> global map", SelectorRemap);
-  
-  llvm::errs() << "  Base preprocessed entity ID: " << BasePreprocessedEntityID
-               << '\n'  
-               << "  Number of preprocessed entities: " 
-               << NumPreallocatedPreprocessingEntities << '\n';
-  dumpLocalRemap("Preprocessed entity ID local -> global map", 
-                 PreprocessedEntityRemap);
-  
-  llvm::errs() << "  Base macro definition ID: " << BaseMacroDefinitionID 
-               << '\n'
-               << "  Number of macro definitions: " << LocalNumMacroDefinitions
-               << '\n';
-  dumpLocalRemap("Macro definition ID local -> global map", 
-                 MacroDefinitionRemap);
-
-  llvm::errs() << "  Base type index: " << BaseTypeIndex << '\n'
-               << "  Number of types: " << LocalNumTypes << '\n';
-  dumpLocalRemap("Type index local -> global map", TypeRemap);
-    
-  llvm::errs() << "  Base decl ID: " << BaseDeclID << '\n'
-               << "  Number of decls: " << LocalNumDecls << '\n';
-  dumpLocalRemap("Decl ID local -> global map", DeclRemap);
-}
-
-//===----------------------------------------------------------------------===//
-// Module manager implementation
-//===----------------------------------------------------------------------===//
-
-Module *ModuleManager::lookup(StringRef Name) {
-  const FileEntry *Entry = FileMgr.getFile(Name);
-  return Modules[Entry];
-}
-
-llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
-  const FileEntry *Entry = FileMgr.getFile(Name);
-  return InMemoryBuffers[Entry];
-}
-
-std::pair<Module *, bool>
-ModuleManager::addModule(StringRef FileName, ModuleKind Type, 
-                         Module *ImportedBy, std::string &ErrorStr) {
-  const FileEntry *Entry = FileMgr.getFile(FileName);
-  if (!Entry && FileName != "-") {
-    ErrorStr = "file not found";
-    return std::make_pair(static_cast<Module*>(0), false);
-  }
-
-  // Check whether we already loaded this module, before 
-  Module *&ModuleEntry = Modules[Entry];
-  bool NewModule = false;
-  if (!ModuleEntry) {
-    // Allocate a new module.
-    Module *New = new Module(Type);
-    New->FileName = FileName.str();
-    Chain.push_back(New);
-    NewModule = true;
-    ModuleEntry = New;
-
-    // Load the contents of the module
-    if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) {
-      // The buffer was already provided for us.
-      assert(Buffer && "Passed null buffer");
-      New->Buffer.reset(Buffer);
-    } else {
-      // Open the AST file.
-      llvm::error_code ec;
-      if (FileName == "-") {
-        ec = llvm::MemoryBuffer::getSTDIN(New->Buffer);
-        if (ec)
-          ErrorStr = ec.message();
-      } else
-        New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr));
-
-      if (!New->Buffer)
-        return std::make_pair(static_cast<Module*>(0), false);
-    }
-
-    // Initialize the stream
-    New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
-                         (const unsigned char *)New->Buffer->getBufferEnd());     }
-
-  if (ImportedBy) {
-    ModuleEntry->ImportedBy.insert(ImportedBy);
-    ImportedBy->Imports.insert(ModuleEntry);
-  } else {
-    ModuleEntry->DirectlyImported = true;
-  }
-  
-  return std::make_pair(ModuleEntry, NewModule);
-}
-
-void ModuleManager::addInMemoryBuffer(StringRef FileName, 
-  llvm::MemoryBuffer *Buffer) {
-  
-  const FileEntry *Entry = FileMgr.getVirtualFile(FileName, 
-    Buffer->getBufferSize(), 0);
-  InMemoryBuffers[Entry] = Buffer;
-}
-
-ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { }
-
-ModuleManager::~ModuleManager() {
-  for (unsigned i = 0, e = Chain.size(); i != e; ++i)
-    delete Chain[e - i - 1];
-}
-
-void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), 
-                          void *UserData) {
-  unsigned N = size();
-
-  // Record the number of incoming edges for each module. When we
-  // encounter a module with no incoming edges, push it into the queue
-  // to seed the queue.
-  SmallVector<Module *, 4> Queue;
-  Queue.reserve(N);
-  llvm::DenseMap<Module *, unsigned> UnusedIncomingEdges; 
-  for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) {
-    if (unsigned Size = (*M)->ImportedBy.size())
-      UnusedIncomingEdges[*M] = Size;
-    else
-      Queue.push_back(*M);
-  }
-
-  llvm::SmallPtrSet<Module *, 4> Skipped;
-  unsigned QueueStart = 0;
-  while (QueueStart < Queue.size()) {
-    Module *CurrentModule = Queue[QueueStart++];
-
-    // Check whether this module should be skipped.
-    if (Skipped.count(CurrentModule))
-      continue;
-
-    if (Visitor(*CurrentModule, UserData)) {
-      // The visitor has requested that cut off visitation of any
-      // module that the current module depends on. To indicate this
-      // behavior, we mark all of the reachable modules as having N
-      // incoming edges (which is impossible otherwise).
-      SmallVector<Module *, 4> Stack;
-      Stack.push_back(CurrentModule);
-      Skipped.insert(CurrentModule);
-      while (!Stack.empty()) {
-        Module *NextModule = Stack.back();
-        Stack.pop_back();
-
-        // For any module that this module depends on, push it on the
-        // stack (if it hasn't already been marked as visited).
-        for (llvm::SetVector<Module *>::iterator 
-                  M = NextModule->Imports.begin(),
-               MEnd = NextModule->Imports.end();
-             M != MEnd; ++M) {
-          if (Skipped.insert(*M))
-            Stack.push_back(*M);
-        }
-      }
-      continue;
-    }
-
-    // For any module that this module depends on, push it on the
-    // stack (if it hasn't already been marked as visited).
-    for (llvm::SetVector<Module *>::iterator M = CurrentModule->Imports.begin(),
-                                          MEnd = CurrentModule->Imports.end();
-         M != MEnd; ++M) {
-
-      // Remove our current module as an impediment to visiting the
-      // module we depend on. If we were the last unvisited module
-      // that depends on this particular module, push it into the
-      // queue to be visited.
-      unsigned &NumUnusedEdges = UnusedIncomingEdges[*M];
-      if (NumUnusedEdges && (--NumUnusedEdges == 0))
-        Queue.push_back(*M);
-    }
-  }
-}
-
-/// \brief Perform a depth-first visit of the current module.
-static bool visitDepthFirst(Module &M, 
-                            bool (*Visitor)(Module &M, bool Preorder, 
-                                            void *UserData), 
-                            void *UserData,
-                            llvm::SmallPtrSet<Module *, 4> &Visited) {
-  // Preorder visitation
-  if (Visitor(M, /*Preorder=*/true, UserData))
-    return true;
-
-  // Visit children
-  for (llvm::SetVector<Module *>::iterator IM = M.Imports.begin(),
-                                        IMEnd = M.Imports.end();
-       IM != IMEnd; ++IM) {
-    if (!Visited.insert(*IM))
-      continue;
-
-    if (visitDepthFirst(**IM, Visitor, UserData, Visited))
-      return true;
-  }  
-
-  // Postorder visitation
-  return Visitor(M, /*Preorder=*/false, UserData);
-}
-
-void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, 
-                                                    void *UserData), 
-                                    void *UserData) {
-  llvm::SmallPtrSet<Module *, 4> Visited;
-  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
-    if (!Visited.insert(Chain[I]))
-      continue;
-
-    if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
-      return;
-  }
-}

Added: cfe/trunk/lib/Serialization/ASTReaderInternals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderInternals.h?rev=138582&view=auto
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderInternals.h (added)
+++ cfe/trunk/lib/Serialization/ASTReaderInternals.h Thu Aug 25 15:47:51 2011
@@ -0,0 +1,243 @@
+//===--- ASTReaderInternals.h - AST Reader Internals ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides internal definitions used in the AST reader.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H
+#define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H
+
+#include "clang/Basic/OnDiskHashTable.h"
+#include "clang/AST/DeclarationName.h"
+#include <utility>
+#include <sys/stat.h>
+
+namespace clang {
+
+class ASTReader;
+class HeaderSearch;
+struct HeaderFileInfo;
+  
+namespace serialization {
+
+class Module;
+
+namespace reader {
+
+/// \brief Class that performs name lookup into a DeclContext stored
+/// in an AST file.
+class ASTDeclContextNameLookupTrait {
+  ASTReader &Reader;
+  Module &F;
+  
+public:
+  /// \brief Pair of begin/end iterators for DeclIDs.
+  ///
+  /// Note that these declaration IDs are local to the module that contains this
+  /// particular lookup t
+  typedef std::pair<DeclID *, DeclID *> data_type;
+
+  /// \brief Special internal key for declaration names.
+  /// The hash table creates keys for comparison; we do not create
+  /// a DeclarationName for the internal key to avoid deserializing types.
+  struct DeclNameKey {
+    DeclarationName::NameKind Kind;
+    uint64_t Data;
+    DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { }
+  };
+
+  typedef DeclarationName external_key_type;
+  typedef DeclNameKey internal_key_type;
+
+  explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, 
+                                         Module &F) 
+    : Reader(Reader), F(F) { }
+
+  static bool EqualKey(const internal_key_type& a,
+                       const internal_key_type& b) {
+    return a.Kind == b.Kind && a.Data == b.Data;
+  }
+
+  unsigned ComputeHash(const DeclNameKey &Key) const;
+  internal_key_type GetInternalKey(const external_key_type& Name) const;
+  external_key_type GetExternalKey(const internal_key_type& Key) const;
+
+  static std::pair<unsigned, unsigned> 
+  ReadKeyDataLength(const unsigned char*& d);
+
+  internal_key_type ReadKey(const unsigned char* d, unsigned);
+
+  data_type ReadData(internal_key_type, const unsigned char* d,
+                     unsigned DataLen);
+};
+
+/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
+typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
+  ASTDeclContextNameLookupTable;
+
+/// \brief Class that performs lookup for an identifier stored in an AST file.
+class ASTIdentifierLookupTrait {
+  ASTReader &Reader;
+  Module &F;
+  
+  // If we know the IdentifierInfo in advance, it is here and we will
+  // not build a new one. Used when deserializing information about an
+  // identifier that was constructed before the AST file was read.
+  IdentifierInfo *KnownII;
+  
+public:
+  typedef IdentifierInfo * data_type;
+  
+  typedef const std::pair<const char*, unsigned> external_key_type;
+  
+  typedef external_key_type internal_key_type;
+  
+  ASTIdentifierLookupTrait(ASTReader &Reader, Module &F,
+                           IdentifierInfo *II = 0)
+    : Reader(Reader), F(F), KnownII(II) { }
+  
+  static bool EqualKey(const internal_key_type& a,
+                       const internal_key_type& b) {
+    return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
+    : false;
+  }
+  
+  static unsigned ComputeHash(const internal_key_type& a);
+  
+  // This hopefully will just get inlined and removed by the optimizer.
+  static const internal_key_type&
+  GetInternalKey(const external_key_type& x) { return x; }
+  
+  // This hopefully will just get inlined and removed by the optimizer.
+  static const external_key_type&
+  GetExternalKey(const internal_key_type& x) { return x; }
+ 
+  static std::pair<unsigned, unsigned>
+  ReadKeyDataLength(const unsigned char*& d);
+
+  static std::pair<const char*, unsigned>
+  ReadKey(const unsigned char* d, unsigned n);
+  
+  IdentifierInfo *ReadData(const internal_key_type& k,
+                           const unsigned char* d,
+                           unsigned DataLen);
+};
+  
+/// \brief The on-disk hash table used to contain information about
+/// all of the identifiers in the program.
+typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
+  ASTIdentifierLookupTable;
+
+/// \brief Class that performs lookup for a selector's entries in the global
+/// method pool stored in an AST file.
+class ASTSelectorLookupTrait {
+  ASTReader &Reader;
+  Module &F;
+  
+public:
+  struct data_type {
+    SelectorID ID;
+    llvm::SmallVector<ObjCMethodDecl *, 2> Instance;
+    llvm::SmallVector<ObjCMethodDecl *, 2> Factory;
+  };
+  
+  typedef Selector external_key_type;
+  typedef external_key_type internal_key_type;
+  
+  ASTSelectorLookupTrait(ASTReader &Reader, Module &F) 
+    : Reader(Reader), F(F) { }
+  
+  static bool EqualKey(const internal_key_type& a,
+                       const internal_key_type& b) {
+    return a == b;
+  }
+  
+  static unsigned ComputeHash(Selector Sel);
+  
+  static const internal_key_type&
+  GetInternalKey(const external_key_type& x) { return x; };
+  
+  static std::pair<unsigned, unsigned>
+  ReadKeyDataLength(const unsigned char*& d);
+  
+  internal_key_type ReadKey(const unsigned char* d, unsigned);
+  data_type ReadData(Selector, const unsigned char* d, unsigned DataLen);
+};
+  
+/// \brief The on-disk hash table used for the global method pool.
+typedef OnDiskChainedHashTable<ASTSelectorLookupTrait>
+  ASTSelectorLookupTable;
+  
+/// \brief Trait class used to search the on-disk hash table containing all of
+/// the header search information.
+///
+/// The on-disk hash table contains a mapping from each header path to 
+/// information about that header (how many times it has been included, its
+/// controlling macro, etc.). Note that we actually hash based on the 
+/// filename, and support "deep" comparisons of file names based on current
+/// inode numbers, so that the search can cope with non-normalized path names
+/// and symlinks.
+class HeaderFileInfoTrait {
+  ASTReader &Reader;
+  Module &M;
+  HeaderSearch *HS;
+  const char *FrameworkStrings;
+  const char *SearchPath;
+  struct stat SearchPathStatBuf;
+  llvm::Optional<int> SearchPathStatResult;
+  
+  int StatSimpleCache(const char *Path, struct stat *StatBuf) {
+    if (Path == SearchPath) {
+      if (!SearchPathStatResult)
+        SearchPathStatResult = stat(Path, &SearchPathStatBuf);
+      
+      *StatBuf = SearchPathStatBuf;
+      return *SearchPathStatResult;
+    }
+    
+    return stat(Path, StatBuf);
+  }
+  
+public:
+  typedef const char *external_key_type;
+  typedef const char *internal_key_type;
+  
+  typedef HeaderFileInfo data_type;
+  
+  HeaderFileInfoTrait(ASTReader &Reader, Module &M, HeaderSearch *HS,
+                      const char *FrameworkStrings,
+                      const char *SearchPath = 0) 
+  : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings), 
+    SearchPath(SearchPath) { }
+  
+  static unsigned ComputeHash(const char *path);
+  static internal_key_type GetInternalKey(const char *path);
+  bool EqualKey(internal_key_type a, internal_key_type b);
+  
+  static std::pair<unsigned, unsigned>
+  ReadKeyDataLength(const unsigned char*& d);
+  
+  static internal_key_type ReadKey(const unsigned char *d, unsigned) {
+    return (const char *)d;
+  }
+  
+  data_type ReadData(const internal_key_type, const unsigned char *d,
+                     unsigned DataLen);
+};
+
+/// \brief The on-disk hash table used for known header files.
+typedef OnDiskChainedHashTable<HeaderFileInfoTrait>
+  HeaderFileInfoLookupTable;
+  
+} // end namespace clang::serialization::reader
+} // end namespace clang::serialization
+} // end namespace clang
+
+
+#endif

Modified: cfe/trunk/lib/Serialization/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/CMakeLists.txt?rev=138582&r1=138581&r2=138582&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/CMakeLists.txt (original)
+++ cfe/trunk/lib/Serialization/CMakeLists.txt Thu Aug 25 15:47:51 2011
@@ -2,6 +2,8 @@
 #set(LLVM_USED_LIBS ???)
 
 add_clang_library(clangSerialization
+  ASTCommon.h
+  ASTReaderInternals.h
   ASTCommon.cpp
   ASTReader.cpp
   ASTReaderDecl.cpp
@@ -11,6 +13,8 @@
   ASTWriterStmt.cpp
   ChainedIncludesSource.cpp
   GeneratePCH.cpp
+  Module.cpp
+  ModuleManager.cpp
   )
 
 add_dependencies(clangSerialization

Added: cfe/trunk/lib/Serialization/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/Module.cpp?rev=138582&view=auto
==============================================================================
--- cfe/trunk/lib/Serialization/Module.cpp (added)
+++ cfe/trunk/lib/Serialization/Module.cpp Thu Aug 25 15:47:51 2011
@@ -0,0 +1,117 @@
+//===--- Module.cpp - Module description ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the Module class, which describes a module that has
+//  been loaded from an AST file.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Serialization/Module.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "ASTReaderInternals.h"
+
+using namespace clang;
+using namespace serialization;
+using namespace reader;
+
+Module::Module(ModuleKind Kind)
+  : Kind(Kind), DirectlyImported(false), SizeInBits(0), 
+    LocalNumSLocEntries(0), SLocEntryBaseID(0),
+    SLocEntryBaseOffset(0), SLocEntryOffsets(0),
+    SLocFileOffsets(0), LocalNumIdentifiers(0), 
+    IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0),
+    IdentifierLookupTable(0), BasePreprocessedEntityID(0),
+    LocalNumMacroDefinitions(0), MacroDefinitionOffsets(0), 
+    BaseMacroDefinitionID(0), LocalNumHeaderFileInfos(0), 
+    HeaderFileInfoTableData(0), HeaderFileInfoTable(0),
+    HeaderFileFrameworkStrings(0),
+    LocalNumSelectors(0), SelectorOffsets(0), BaseSelectorID(0),
+    SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
+    DeclOffsets(0), BaseDeclID(0),
+    LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
+    LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0),
+    NumPreallocatedPreprocessingEntities(0)
+{}
+
+Module::~Module() {
+  for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(),
+       E = DeclContextInfos.end();
+       I != E; ++I) {
+    if (I->second.NameLookupTableData)
+      delete static_cast<ASTDeclContextNameLookupTable*>(
+                                                 I->second.NameLookupTableData);
+  }
+  
+  delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
+  delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
+  delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
+}
+
+template<typename Key, typename Offset, unsigned InitialCapacity>
+static void 
+dumpLocalRemap(StringRef Name,
+               const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) {
+  if (Map.begin() == Map.end())
+    return;
+  
+  typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType;
+  llvm::errs() << "  " << Name << ":\n";
+  for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end(); 
+       I != IEnd; ++I) {
+    llvm::errs() << "    " << I->first << " -> " << I->second << "\n";
+  }
+}
+
+void Module::dump() {
+  llvm::errs() << "\nModule: " << FileName << "\n";
+  if (!Imports.empty()) {
+    llvm::errs() << "  Imports: ";
+    for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
+      if (I)
+        llvm::errs() << ", ";
+      llvm::errs() << Imports[I]->FileName;
+    }
+    llvm::errs() << "\n";
+  }
+  
+  // Remapping tables.
+  llvm::errs() << "  Base source location offset: " << SLocEntryBaseOffset 
+               << '\n';
+  dumpLocalRemap("Source location offset local -> global map", SLocRemap);
+  
+  llvm::errs() << "  Base identifier ID: " << BaseIdentifierID << '\n'
+               << "  Number of identifiers: " << LocalNumIdentifiers << '\n';
+  dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap);
+  
+  llvm::errs() << "  Base selector ID: " << BaseSelectorID << '\n'
+               << "  Number of selectors: " << LocalNumSelectors << '\n';
+  dumpLocalRemap("Selector ID local -> global map", SelectorRemap);
+  
+  llvm::errs() << "  Base preprocessed entity ID: " << BasePreprocessedEntityID
+               << '\n'  
+               << "  Number of preprocessed entities: " 
+               << NumPreallocatedPreprocessingEntities << '\n';
+  dumpLocalRemap("Preprocessed entity ID local -> global map", 
+                 PreprocessedEntityRemap);
+  
+  llvm::errs() << "  Base macro definition ID: " << BaseMacroDefinitionID 
+               << '\n'
+               << "  Number of macro definitions: " << LocalNumMacroDefinitions
+               << '\n';
+  dumpLocalRemap("Macro definition ID local -> global map", 
+                 MacroDefinitionRemap);
+  
+  llvm::errs() << "  Base type index: " << BaseTypeIndex << '\n'
+               << "  Number of types: " << LocalNumTypes << '\n';
+  dumpLocalRemap("Type index local -> global map", TypeRemap);
+  
+  llvm::errs() << "  Base decl ID: " << BaseDeclID << '\n'
+               << "  Number of decls: " << LocalNumDecls << '\n';
+  dumpLocalRemap("Decl ID local -> global map", DeclRemap);
+}

Added: cfe/trunk/lib/Serialization/ModuleManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ModuleManager.cpp?rev=138582&view=auto
==============================================================================
--- cfe/trunk/lib/Serialization/ModuleManager.cpp (added)
+++ cfe/trunk/lib/Serialization/ModuleManager.cpp Thu Aug 25 15:47:51 2011
@@ -0,0 +1,204 @@
+//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the ModuleManager class, which manages a set of loaded
+//  modules for the ASTReader.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Serialization/ModuleManager.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+using namespace clang;
+using namespace serialization;
+
+Module *ModuleManager::lookup(StringRef Name) {
+  const FileEntry *Entry = FileMgr.getFile(Name);
+  return Modules[Entry];
+}
+
+llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
+  const FileEntry *Entry = FileMgr.getFile(Name);
+  return InMemoryBuffers[Entry];
+}
+
+std::pair<Module *, bool>
+ModuleManager::addModule(StringRef FileName, ModuleKind Type, 
+                         Module *ImportedBy, std::string &ErrorStr) {
+  const FileEntry *Entry = FileMgr.getFile(FileName);
+  if (!Entry && FileName != "-") {
+    ErrorStr = "file not found";
+    return std::make_pair(static_cast<Module*>(0), false);
+  }
+  
+  // Check whether we already loaded this module, before 
+  Module *&ModuleEntry = Modules[Entry];
+  bool NewModule = false;
+  if (!ModuleEntry) {
+    // Allocate a new module.
+    Module *New = new Module(Type);
+    New->FileName = FileName.str();
+    Chain.push_back(New);
+    NewModule = true;
+    ModuleEntry = New;
+    
+    // Load the contents of the module
+    if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) {
+      // The buffer was already provided for us.
+      assert(Buffer && "Passed null buffer");
+      New->Buffer.reset(Buffer);
+    } else {
+      // Open the AST file.
+      llvm::error_code ec;
+      if (FileName == "-") {
+        ec = llvm::MemoryBuffer::getSTDIN(New->Buffer);
+        if (ec)
+          ErrorStr = ec.message();
+      } else
+        New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr));
+      
+      if (!New->Buffer)
+        return std::make_pair(static_cast<Module*>(0), false);
+    }
+    
+    // Initialize the stream
+    New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
+                         (const unsigned char *)New->Buffer->getBufferEnd());     }
+  
+  if (ImportedBy) {
+    ModuleEntry->ImportedBy.insert(ImportedBy);
+    ImportedBy->Imports.insert(ModuleEntry);
+  } else {
+    ModuleEntry->DirectlyImported = true;
+  }
+  
+  return std::make_pair(ModuleEntry, NewModule);
+}
+
+void ModuleManager::addInMemoryBuffer(StringRef FileName, 
+                                      llvm::MemoryBuffer *Buffer) {
+  
+  const FileEntry *Entry = FileMgr.getVirtualFile(FileName, 
+                                                  Buffer->getBufferSize(), 0);
+  InMemoryBuffers[Entry] = Buffer;
+}
+
+ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { }
+
+ModuleManager::~ModuleManager() {
+  for (unsigned i = 0, e = Chain.size(); i != e; ++i)
+    delete Chain[e - i - 1];
+}
+
+void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData), 
+                          void *UserData) {
+  unsigned N = size();
+  
+  // Record the number of incoming edges for each module. When we
+  // encounter a module with no incoming edges, push it into the queue
+  // to seed the queue.
+  SmallVector<Module *, 4> Queue;
+  Queue.reserve(N);
+  llvm::DenseMap<Module *, unsigned> UnusedIncomingEdges; 
+  for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) {
+    if (unsigned Size = (*M)->ImportedBy.size())
+      UnusedIncomingEdges[*M] = Size;
+    else
+      Queue.push_back(*M);
+  }
+  
+  llvm::SmallPtrSet<Module *, 4> Skipped;
+  unsigned QueueStart = 0;
+  while (QueueStart < Queue.size()) {
+    Module *CurrentModule = Queue[QueueStart++];
+    
+    // Check whether this module should be skipped.
+    if (Skipped.count(CurrentModule))
+      continue;
+    
+    if (Visitor(*CurrentModule, UserData)) {
+      // The visitor has requested that cut off visitation of any
+      // module that the current module depends on. To indicate this
+      // behavior, we mark all of the reachable modules as having N
+      // incoming edges (which is impossible otherwise).
+      SmallVector<Module *, 4> Stack;
+      Stack.push_back(CurrentModule);
+      Skipped.insert(CurrentModule);
+      while (!Stack.empty()) {
+        Module *NextModule = Stack.back();
+        Stack.pop_back();
+        
+        // For any module that this module depends on, push it on the
+        // stack (if it hasn't already been marked as visited).
+        for (llvm::SetVector<Module *>::iterator 
+             M = NextModule->Imports.begin(),
+             MEnd = NextModule->Imports.end();
+             M != MEnd; ++M) {
+          if (Skipped.insert(*M))
+            Stack.push_back(*M);
+        }
+      }
+      continue;
+    }
+    
+    // For any module that this module depends on, push it on the
+    // stack (if it hasn't already been marked as visited).
+    for (llvm::SetVector<Module *>::iterator M = CurrentModule->Imports.begin(),
+         MEnd = CurrentModule->Imports.end();
+         M != MEnd; ++M) {
+      
+      // Remove our current module as an impediment to visiting the
+      // module we depend on. If we were the last unvisited module
+      // that depends on this particular module, push it into the
+      // queue to be visited.
+      unsigned &NumUnusedEdges = UnusedIncomingEdges[*M];
+      if (NumUnusedEdges && (--NumUnusedEdges == 0))
+        Queue.push_back(*M);
+    }
+  }
+}
+
+/// \brief Perform a depth-first visit of the current module.
+static bool visitDepthFirst(Module &M, 
+                            bool (*Visitor)(Module &M, bool Preorder, 
+                                            void *UserData), 
+                            void *UserData,
+                            llvm::SmallPtrSet<Module *, 4> &Visited) {
+  // Preorder visitation
+  if (Visitor(M, /*Preorder=*/true, UserData))
+    return true;
+  
+  // Visit children
+  for (llvm::SetVector<Module *>::iterator IM = M.Imports.begin(),
+       IMEnd = M.Imports.end();
+       IM != IMEnd; ++IM) {
+    if (!Visited.insert(*IM))
+      continue;
+    
+    if (visitDepthFirst(**IM, Visitor, UserData, Visited))
+      return true;
+  }  
+  
+  // Postorder visitation
+  return Visitor(M, /*Preorder=*/false, UserData);
+}
+
+void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder, 
+                                                    void *UserData), 
+                                    void *UserData) {
+  llvm::SmallPtrSet<Module *, 4> Visited;
+  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+    if (!Visited.insert(Chain[I]))
+      continue;
+    
+    if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
+      return;
+  }
+}





More information about the cfe-commits mailing list