[cfe-commits] r166166 - in /cfe/trunk: include/clang/Serialization/ASTBitCodes.h include/clang/Serialization/ASTReader.h include/clang/Serialization/ASTWriter.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp

Douglas Gregor dgregor at apple.com
Wed Oct 17 22:31:06 PDT 2012


Author: dgregor
Date: Thu Oct 18 00:31:06 2012
New Revision: 166166

URL: http://llvm.org/viewvc/llvm-project?rev=166166&view=rev
Log:
Start factoring the on-disk records for an AST file into a control
block, which stores information about how the AST file to generated,
from the AST block, which stores the actual serialized AST. The
information in the control block should be enough to determine whether
the AST file is up-to-date and compatible with the current translation
unit, and reading it should not cause any side effects that aren't
easy to undo. That way, we can back out from an attempt to read an
incompatible or out-of-date AST file.

Note that there is still more factoring to do. In particular,
information about the source files used to generate the AST file
(along with their time stamps, sizes, etc.) still resides in the
source manager block. 

Modified:
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=166166&r1=166165&r2=166166&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Oct 18 00:31:06 2012
@@ -216,7 +216,46 @@
       SUBMODULE_BLOCK_ID,
 
       /// \brief The block containing comments.
-      COMMENTS_BLOCK_ID
+      COMMENTS_BLOCK_ID,
+
+      /// \brief The control block, which contains all of the
+      /// information that needs to be validated prior to committing
+      /// to loading the AST file.
+      CONTROL_BLOCK_ID
+    };
+
+    /// \brief Record types that occur within the control block.
+    enum ControlRecordTypes {
+      /// \brief AST file metadata, including the AST file version number
+      /// and the target triple used to build the AST file.
+      METADATA = 1,
+
+      /// \brief Record code for the list of other AST files imported by
+      /// this AST file.
+      IMPORTS = 2,
+
+      /// \brief Record code for the language options table.
+      ///
+      /// The record with this code contains the contents of the
+      /// LangOptions structure. We serialize the entire contents of
+      /// the structure, and let the reader decide which options are
+      /// actually important to check.
+      LANGUAGE_OPTIONS = 3,
+
+      /// \brief Record code for the original file that was used to
+      /// generate the AST file.
+      ORIGINAL_FILE_NAME = 4,
+
+      /// \brief Record code for the file ID of the original file used to 
+      /// generate the AST file.
+      ORIGINAL_FILE_ID = 5,
+      
+      /// \brief The directory that the PCH was originally created in.
+      ORIGINAL_PCH_DIR = 6,
+
+      /// \brief Record code for the version control branch and revision
+      /// information of the compiler used to build this AST file.
+      VERSION_CONTROL_BRANCH_REVISION = 7
     };
 
     /// \brief Record types that occur within the AST block itself.
@@ -247,25 +286,13 @@
       /// reserved for the translation unit declaration.
       DECL_OFFSET = 2,
 
-      /// \brief Record code for the language options table.
-      ///
-      /// The record with this code contains the contents of the
-      /// LangOptions structure. We serialize the entire contents of
-      /// the structure, and let the reader decide which options are
-      /// actually important to check.
-      LANGUAGE_OPTIONS = 3,
-
-      /// \brief AST file metadata, including the AST file version number
-      /// and the target triple used to build the AST file.
-      METADATA = 4,
-
       /// \brief Record code for the table of offsets of each
       /// identifier ID.
       ///
       /// The offset table contains offsets into the blob stored in
       /// the IDENTIFIER_TABLE record. Each offset points to the
       /// NULL-terminated string that corresponds to that identifier.
-      IDENTIFIER_OFFSET = 5,
+      IDENTIFIER_OFFSET = 3,
 
       /// \brief Record code for the identifier table.
       ///
@@ -279,7 +306,7 @@
       /// between offsets (for unresolved identifier IDs) and
       /// IdentifierInfo pointers (for already-resolved identifier
       /// IDs).
-      IDENTIFIER_TABLE = 6,
+      IDENTIFIER_TABLE = 4,
 
       /// \brief Record code for the array of external definitions.
       ///
@@ -289,7 +316,7 @@
       /// reported to the AST consumer after the AST file has been
       /// read, since their presence can affect the semantics of the
       /// program (e.g., for code generation).
-      EXTERNAL_DEFINITIONS = 7,
+      EXTERNAL_DEFINITIONS = 5,
 
       /// \brief Record code for the set of non-builtin, special
       /// types.
@@ -298,33 +325,33 @@
       /// that are constructed during semantic analysis (e.g.,
       /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
       /// offsets into this record.
-      SPECIAL_TYPES = 8,
+      SPECIAL_TYPES = 6,
 
       /// \brief Record code for the extra statistics we gather while
       /// generating an AST file.
-      STATISTICS = 9,
+      STATISTICS = 7,
 
       /// \brief Record code for the array of tentative definitions.
-      TENTATIVE_DEFINITIONS = 10,
+      TENTATIVE_DEFINITIONS = 8,
 
       /// \brief Record code for the array of locally-scoped external
       /// declarations.
-      LOCALLY_SCOPED_EXTERNAL_DECLS = 11,
+      LOCALLY_SCOPED_EXTERNAL_DECLS = 9,
 
       /// \brief Record code for the table of offsets into the
       /// Objective-C method pool.
-      SELECTOR_OFFSETS = 12,
+      SELECTOR_OFFSETS = 10,
 
       /// \brief Record code for the Objective-C method pool,
-      METHOD_POOL = 13,
+      METHOD_POOL = 11,
 
       /// \brief The value of the next __COUNTER__ to dispense.
       /// [PP_COUNTER_VALUE, Val]
-      PP_COUNTER_VALUE = 14,
+      PP_COUNTER_VALUE = 12,
 
       /// \brief Record code for the table of offsets into the block
       /// of source-location information.
-      SOURCE_LOCATION_OFFSETS = 15,
+      SOURCE_LOCATION_OFFSETS = 13,
 
       /// \brief Record code for the set of source location entries
       /// that need to be preloaded by the AST reader.
@@ -332,164 +359,145 @@
       /// This set contains the source location entry for the
       /// predefines buffer and for any file entries that need to be
       /// preloaded.
-      SOURCE_LOCATION_PRELOADS = 16,
+      SOURCE_LOCATION_PRELOADS = 14,
 
       /// \brief Record code for the stat() cache.
-      STAT_CACHE = 17,
+      STAT_CACHE = 15,
 
       /// \brief Record code for the set of ext_vector type names.
-      EXT_VECTOR_DECLS = 18,
-
-      /// \brief Record code for the original file that was used to
-      /// generate the AST file.
-      ORIGINAL_FILE_NAME = 19,
-
-      /// \brief Record code for the file ID of the original file used to 
-      /// generate the AST file.
-      ORIGINAL_FILE_ID = 20,
-      
-      /// \brief Record code for the version control branch and revision
-      /// information of the compiler used to build this AST file.
-      VERSION_CONTROL_BRANCH_REVISION = 21,
+      EXT_VECTOR_DECLS = 16,
       
       /// \brief Record code for the array of unused file scoped decls.
-      UNUSED_FILESCOPED_DECLS = 22,
+      UNUSED_FILESCOPED_DECLS = 17,
       
       /// \brief Record code for the table of offsets to entries in the
       /// preprocessing record.
-      PPD_ENTITIES_OFFSETS = 23,
+      PPD_ENTITIES_OFFSETS = 18,
 
       /// \brief Record code for the array of VTable uses.
-      VTABLE_USES = 24,
+      VTABLE_USES = 19,
 
       /// \brief Record code for the array of dynamic classes.
-      DYNAMIC_CLASSES = 25,
-
-      /// \brief Record code for the list of other AST files imported by
-      /// this AST file.
-      IMPORTS = 26,
+      DYNAMIC_CLASSES = 20,
 
       /// \brief Record code for referenced selector pool.
-      REFERENCED_SELECTOR_POOL = 27,
+      REFERENCED_SELECTOR_POOL = 21,
 
       /// \brief Record code for an update to the TU's lexically contained
       /// declarations.
-      TU_UPDATE_LEXICAL = 28,
+      TU_UPDATE_LEXICAL = 22,
       
       /// \brief Record code for the array describing the locations (in the
       /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by
       /// the first known ID.
-      LOCAL_REDECLARATIONS_MAP = 29,
+      LOCAL_REDECLARATIONS_MAP = 23,
 
       /// \brief Record code for declarations that Sema keeps references of.
-      SEMA_DECL_REFS = 30,
+      SEMA_DECL_REFS = 24,
 
       /// \brief Record code for weak undeclared identifiers.
-      WEAK_UNDECLARED_IDENTIFIERS = 31,
+      WEAK_UNDECLARED_IDENTIFIERS = 25,
 
       /// \brief Record code for pending implicit instantiations.
-      PENDING_IMPLICIT_INSTANTIATIONS = 32,
+      PENDING_IMPLICIT_INSTANTIATIONS = 26,
 
       /// \brief Record code for a decl replacement block.
       ///
       /// If a declaration is modified after having been deserialized, and then
       /// written to a dependent AST file, its ID and offset must be added to
       /// the replacement block.
-      DECL_REPLACEMENTS = 33,
+      DECL_REPLACEMENTS = 27,
 
       /// \brief Record code for an update to a decl context's lookup table.
       ///
       /// In practice, this should only be used for the TU and namespaces.
-      UPDATE_VISIBLE = 34,
+      UPDATE_VISIBLE = 28,
 
       /// \brief Record for offsets of DECL_UPDATES records for declarations
       /// that were modified after being deserialized and need updates.
-      DECL_UPDATE_OFFSETS = 35,
+      DECL_UPDATE_OFFSETS = 29,
 
       /// \brief Record of updates for a declaration that was modified after
       /// being deserialized.
-      DECL_UPDATES = 36,
+      DECL_UPDATES = 30,
       
       /// \brief Record code for the table of offsets to CXXBaseSpecifier
       /// sets.
-      CXX_BASE_SPECIFIER_OFFSETS = 37,
+      CXX_BASE_SPECIFIER_OFFSETS = 31,
 
       /// \brief Record code for \#pragma diagnostic mappings.
-      DIAG_PRAGMA_MAPPINGS = 38,
+      DIAG_PRAGMA_MAPPINGS = 32,
 
       /// \brief Record code for special CUDA declarations.
-      CUDA_SPECIAL_DECL_REFS = 39,
+      CUDA_SPECIAL_DECL_REFS = 33,
       
       /// \brief Record code for header search information.
-      HEADER_SEARCH_TABLE = 40,
-
-      /// \brief The directory that the PCH was originally created in.
-      ORIGINAL_PCH_DIR = 41,
+      HEADER_SEARCH_TABLE = 34,
 
       /// \brief Record code for floating point \#pragma options.
-      FP_PRAGMA_OPTIONS = 42,
+      FP_PRAGMA_OPTIONS = 35,
 
       /// \brief Record code for enabled OpenCL extensions.
-      OPENCL_EXTENSIONS = 43,
+      OPENCL_EXTENSIONS = 36,
 
       /// \brief The list of delegating constructor declarations.
-      DELEGATING_CTORS = 44,
+      DELEGATING_CTORS = 37,
 
       /// \brief Record code for the table of offsets into the block
       /// of file source-location information.
-      FILE_SOURCE_LOCATION_OFFSETS = 45,
+      FILE_SOURCE_LOCATION_OFFSETS = 38,
       
       /// \brief Record code for the set of known namespaces, which are used
       /// for typo correction.
-      KNOWN_NAMESPACES = 46,
+      KNOWN_NAMESPACES = 39,
 
       /// \brief Record code for the remapping information used to relate
       /// loaded modules to the various offsets and IDs(e.g., source location 
       /// offests, declaration and type IDs) that are used in that module to
       /// refer to other modules.
-      MODULE_OFFSET_MAP = 47,
+      MODULE_OFFSET_MAP = 40,
 
       /// \brief Record code for the source manager line table information,
       /// which stores information about \#line directives.
-      SOURCE_MANAGER_LINE_TABLE = 48,
+      SOURCE_MANAGER_LINE_TABLE = 41,
 
       /// \brief Record code for map of Objective-C class definition IDs to the 
       /// ObjC categories in a module that are attached to that class.
-      OBJC_CATEGORIES_MAP = 49,
+      OBJC_CATEGORIES_MAP = 42,
 
       /// \brief Record code for a file sorted array of DeclIDs in a module.
-      FILE_SORTED_DECLS = 50,
+      FILE_SORTED_DECLS = 43,
       
       /// \brief Record code for an array of all of the (sub)modules that were
       /// imported by the AST file.
-      IMPORTED_MODULES = 51,
+      IMPORTED_MODULES = 44,
       
       /// \brief Record code for the set of merged declarations in an AST file.
-      MERGED_DECLARATIONS = 52,
+      MERGED_DECLARATIONS = 45,
       
       /// \brief Record code for the array of redeclaration chains.
       ///
       /// This array can only be interpreted properly using the local 
       /// redeclarations map.
-      LOCAL_REDECLARATIONS = 53,
+      LOCAL_REDECLARATIONS = 46,
       
       /// \brief Record code for the array of Objective-C categories (including
       /// extensions).
       ///
       /// This array can only be interpreted properly using the Objective-C
       /// categories map.
-      OBJC_CATEGORIES = 54,
+      OBJC_CATEGORIES = 47,
 
       /// \brief Record code for the table of offsets of each macro ID.
       ///
       /// The offset table contains offsets into the blob stored in
       /// the preprocessor block. Each offset points to the corresponding
       /// macro definition.
-      MACRO_OFFSET = 55,
+      MACRO_OFFSET = 48,
 
       /// \brief Record of updates for a macro that was modified after
       /// being deserialized.
-      MACRO_UPDATES = 56
+      MACRO_UPDATES = 49
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=166166&r1=166165&r2=166166&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Oct 18 00:31:06 2012
@@ -886,7 +886,10 @@
   void MaybeAddSystemRootToFilename(std::string &Filename);
 
   ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type,
-                            ModuleFile *ImportedBy);
+                            ModuleFile *ImportedBy,
+                            llvm::SmallVectorImpl<ModuleFile *> &Loaded);
+  ASTReadResult ReadControlBlock(ModuleFile &F,
+                                 llvm::SmallVectorImpl<ModuleFile *> &Loaded);
   ASTReadResult ReadASTBlock(ModuleFile &F);
   bool CheckPredefinesBuffers();
   bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=166166&r1=166165&r2=166166&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Thu Oct 18 00:31:06 2012
@@ -409,9 +409,8 @@
                     llvm::DenseSet<Stmt *> &ParentStmts);
 
   void WriteBlockInfoBlock();
-  void WriteMetadata(ASTContext &Context, StringRef isysroot,
-                     const std::string &OutputFile);
-  void WriteLanguageOptions(const LangOptions &LangOpts);
+  void WriteControlBlock(ASTContext &Context, StringRef isysroot,
+                         const std::string &OutputFile);
   void WriteStatCache(MemorizeStatCalls &StatCalls);
   void WriteSourceManagerBlock(SourceManager &SourceMgr,
                                const Preprocessor &PP,

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=166166&r1=166165&r2=166166&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Oct 18 00:31:06 2012
@@ -1744,6 +1744,152 @@
   Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
 }
 
+ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F,
+                           llvm::SmallVectorImpl<ModuleFile *> &Loaded) {
+  llvm::BitstreamCursor &Stream = F.Stream;
+
+  if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+    Error("malformed block record in AST file");
+    return Failure;
+  }
+
+  // Read all of the records and blocks in the control block.
+  RecordData Record;
+  while (!Stream.AtEndOfStream()) {
+    unsigned Code = Stream.ReadCode();
+    if (Code == llvm::bitc::END_BLOCK) {
+      if (Stream.ReadBlockEnd()) {
+        Error("error at end of control block in AST file");
+        return Failure;
+      }
+
+      return Success;
+    }
+
+    if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+      Stream.ReadSubBlockID();
+      if (!Stream.SkipBlock())
+        continue;
+
+      Error("malformed block record in AST file");
+      return Failure;
+    }
+
+    if (Code == llvm::bitc::DEFINE_ABBREV) {
+      Stream.ReadAbbrevRecord();
+      continue;
+    }
+
+    // Read and process a record.
+    Record.clear();
+    const char *BlobStart = 0;
+    unsigned BlobLen = 0;
+    switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record,
+                                                  &BlobStart, &BlobLen)) {
+    case METADATA: {
+      if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+        Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+                                      : diag::warn_pch_version_too_new);
+        return IgnorePCH;
+      }
+
+      bool hasErrors = Record[5];
+      if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
+        Diag(diag::err_pch_with_compiler_errors);
+        return IgnorePCH;
+      }
+
+      RelocatablePCH = Record[4];
+      if (Listener && &F == *ModuleMgr.begin()) {
+        unsigned Idx = 6;
+        TargetOptions TargetOpts;
+        TargetOpts.Triple = ReadString(Record, Idx);
+        TargetOpts.CPU = ReadString(Record, Idx);
+        TargetOpts.ABI = ReadString(Record, Idx);
+        TargetOpts.CXXABI = ReadString(Record, Idx);
+        TargetOpts.LinkerVersion = ReadString(Record, Idx);
+        for (unsigned N = Record[Idx++]; N; --N) {
+          TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
+        }
+        for (unsigned N = Record[Idx++]; N; --N) {
+          TargetOpts.Features.push_back(ReadString(Record, Idx));
+        }
+
+        if (Listener->ReadTargetOptions(F, TargetOpts))
+          return IgnorePCH;
+      }
+      break;
+    }
+
+    case IMPORTS: {
+      // Load each of the imported PCH files. 
+      unsigned Idx = 0, N = Record.size();
+      while (Idx < N) {
+        // Read information about the AST file.
+        ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
+        unsigned Length = Record[Idx++];
+        SmallString<128> ImportedFile(Record.begin() + Idx,
+                                      Record.begin() + Idx + Length);
+        Idx += Length;
+
+        // Load the AST file.
+        switch(ReadASTCore(ImportedFile, ImportedKind, &F, Loaded)) {
+        case Failure: return Failure;
+          // If we have to ignore the dependency, we'll have to ignore this too.
+        case IgnorePCH: return IgnorePCH;
+        case Success: break;
+        }
+      }
+      break;
+    }
+
+    case LANGUAGE_OPTIONS:
+      if (&F == *ModuleMgr.begin() && 
+          ParseLanguageOptions(F, Record) && !DisableValidation)
+        return IgnorePCH;
+      break;
+
+    case ORIGINAL_FILE_NAME:
+      // Only record from the primary AST file.
+      if (&F == *ModuleMgr.begin()) {
+        // The primary AST will be the last to get here, so it will be the one
+        // that's used.
+        ActualOriginalFileName.assign(BlobStart, BlobLen);
+        OriginalFileName = ActualOriginalFileName;
+        MaybeAddSystemRootToFilename(OriginalFileName);
+      }
+      break;
+
+    case ORIGINAL_FILE_ID:
+      // Only record from the primary AST file.
+      if (&F == *ModuleMgr.begin()) {
+        OriginalFileID = FileID::get(Record[0]);
+      }
+      break;
+        
+    case ORIGINAL_PCH_DIR:
+      // Only record from the primary AST file.
+      if (&F == *ModuleMgr.begin()) {
+        OriginalDir.assign(BlobStart, BlobLen);
+      }
+      break;
+
+    case VERSION_CONTROL_BRANCH_REVISION: {
+      const std::string &CurBranch = getClangFullRepositoryVersion();
+      StringRef ASTBranch(BlobStart, BlobLen);
+      if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
+        Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
+        return IgnorePCH;
+      }
+      break;
+    }
+    }
+  }
+
+  Error("premature end of bitstream in AST file");
+  return Failure;
+}
+
 ASTReader::ASTReadResult
 ASTReader::ReadASTBlock(ModuleFile &F) {
   llvm::BitstreamCursor &Stream = F.Stream;
@@ -1753,7 +1899,7 @@
     return Failure;
   }
 
-  // Read all of the records and blocks for the ASt file.
+  // Read all of the records and blocks for the AST file.
   RecordData Record;
   while (!Stream.AtEndOfStream()) {
     unsigned Code = Stream.ReadCode();
@@ -1885,63 +2031,6 @@
     default:  // Default behavior: ignore.
       break;
 
-    case METADATA: {
-      if (Record[0] != VERSION_MAJOR && !DisableValidation) {
-        Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
-                                      : diag::warn_pch_version_too_new);
-        return IgnorePCH;
-      }
-
-      bool hasErrors = Record[5];
-      if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
-        Diag(diag::err_pch_with_compiler_errors);
-        return IgnorePCH;
-      }
-
-      RelocatablePCH = Record[4];
-      if (Listener) {
-        unsigned Idx = 6;
-        TargetOptions TargetOpts;
-        TargetOpts.Triple = ReadString(Record, Idx);
-        TargetOpts.CPU = ReadString(Record, Idx);
-        TargetOpts.ABI = ReadString(Record, Idx);
-        TargetOpts.CXXABI = ReadString(Record, Idx);
-        TargetOpts.LinkerVersion = ReadString(Record, Idx);
-        for (unsigned N = Record[Idx++]; N; --N) {
-          TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
-        }
-        for (unsigned N = Record[Idx++]; N; --N) {
-          TargetOpts.Features.push_back(ReadString(Record, Idx));
-        }
-
-        if (Listener->ReadTargetOptions(F, TargetOpts))
-          return IgnorePCH;
-      }
-      break;
-    }
-
-    case IMPORTS: {
-      // Load each of the imported PCH files. 
-      unsigned Idx = 0, N = Record.size();
-      while (Idx < N) {
-        // Read information about the AST file.
-        ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
-        unsigned Length = Record[Idx++];
-        SmallString<128> ImportedFile(Record.begin() + Idx,
-                                            Record.begin() + Idx + Length);
-        Idx += Length;
-
-        // Load the AST file.
-        switch(ReadASTCore(ImportedFile, ImportedKind, &F)) {
-        case Failure: return Failure;
-          // If we have to ignore the dependency, we'll have to ignore this too.
-        case IgnorePCH: return IgnorePCH;
-        case Success: break;
-        }
-      }
-      break;
-    }
-
     case TYPE_OFFSET: {
       if (F.LocalNumTypes != 0) {
         Error("duplicate TYPE_OFFSET record in AST file");
@@ -2023,11 +2112,6 @@
       break;
     }
 
-    case LANGUAGE_OPTIONS:
-      if (ParseLanguageOptions(F, Record) && !DisableValidation)
-        return IgnorePCH;
-      break;
-
     case IDENTIFIER_TABLE:
       F.IdentifierTableData = BlobStart;
       if (Record[0]) {
@@ -2364,34 +2448,6 @@
         SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
       break;
 
-    case ORIGINAL_FILE_NAME:
-      // The primary AST will be the last to get here, so it will be the one
-      // that's used.
-      ActualOriginalFileName.assign(BlobStart, BlobLen);
-      OriginalFileName = ActualOriginalFileName;
-      MaybeAddSystemRootToFilename(OriginalFileName);
-      break;
-
-    case ORIGINAL_FILE_ID:
-      OriginalFileID = FileID::get(Record[0]);
-      break;
-        
-    case ORIGINAL_PCH_DIR:
-      // The primary AST will be the last to get here, so it will be the one
-      // that's used.
-      OriginalDir.assign(BlobStart, BlobLen);
-      break;
-
-    case VERSION_CONTROL_BRANCH_REVISION: {
-      const std::string &CurBranch = getClangFullRepositoryVersion();
-      StringRef ASTBranch(BlobStart, BlobLen);
-      if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
-        Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
-        return IgnorePCH;
-      }
-      break;
-    }
-
     case PPD_ENTITIES_OFFSETS: {
       F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart;
       assert(BlobLen % sizeof(PPEntityOffset) == 0);
@@ -2839,8 +2895,10 @@
                                             ModuleKind Type) {
   // Bump the generation number.
   unsigned PreviousGeneration = CurrentGeneration++;
-  
-  switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) {
+
+  // Load the core of the AST files.
+  llvm::SmallVector<ModuleFile *, 4> Loaded;
+  switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0, Loaded)) {
   case Failure: return Failure;
   case IgnorePCH: return IgnorePCH;
   case Success: break;
@@ -2848,6 +2906,47 @@
 
   // Here comes stuff that we only do once the entire chain is loaded.
 
+  // Load the AST blocks of all of the modules that we loaded.
+  for (llvm::SmallVectorImpl<ModuleFile *>::iterator M = Loaded.begin(),
+                                                  MEnd = Loaded.end();
+       M != MEnd; ++M) {
+    ModuleFile &F = **M;
+
+    // Read the AST block.
+    switch(ReadASTBlock(F)) {
+    case Failure: return Failure;
+    case IgnorePCH: return IgnorePCH;
+    case Success: break;
+    }
+
+    // Once read, set the ModuleFile bit base offset and update the size in 
+    // bits of all files we've seen.
+    F.GlobalBitOffset = TotalModulesSizeInBits;
+    TotalModulesSizeInBits += F.SizeInBits;
+    GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
+    
+    // Make sure that the files this module was built against are
+    // still available.
+    // FIXME: Move this validation into ReadControlBlock.
+    if (!DisableValidation) {
+      switch(validateFileEntries(F)) {
+      case Failure: return Failure;
+      case IgnorePCH: return IgnorePCH;
+      case Success: break;
+      }
+    }
+  
+    // Preload SLocEntries.
+    for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
+      int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
+      // Load it through the SourceManager and don't call ReadSLocEntryRecord()
+      // directly because the entry may have already been loaded in which case
+      // calling ReadSLocEntryRecord() directly would trigger an assertion in
+      // SourceManager.
+      SourceMgr.getLoadedSLocEntryByID(Index);
+    }
+  }
+
   // Check the predefines buffers.
   if (!DisableValidation && Type == MK_PCH &&
       // FIXME: CheckPredefinesBuffers also sets the SuggestedPredefines;
@@ -2914,7 +3013,8 @@
 
 ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
                                                 ModuleKind Type,
-                                                ModuleFile *ImportedBy) {
+                                                ModuleFile *ImportedBy,
+                           llvm::SmallVectorImpl<ModuleFile *> &Loaded) {
   ModuleFile *M;
   bool NewModule;
   std::string ErrorStr;
@@ -2973,8 +3073,8 @@
         return Failure;
       }
       break;
-    case AST_BLOCK_ID:
-      switch (ReadASTBlock(F)) {
+    case CONTROL_BLOCK_ID:
+      switch (ReadControlBlock(F, Loaded)) {
       case Success:
         break;
 
@@ -2985,17 +3085,14 @@
         // FIXME: We could consider reading through to the end of this
         // AST block, skipping subblocks, to see if there are other
         // AST blocks elsewhere.
-
-        // FIXME: We can't clear loaded slocentries anymore.
-        //SourceMgr.ClearPreallocatedSLocEntries();
-
-        // Remove the stat cache.
-        if (F.StatCache)
-          FileMgr.removeStatCache((ASTStatCache*)F.StatCache);
-
         return IgnorePCH;
       }
       break;
+    case AST_BLOCK_ID:
+      // Record that we've loaded this module.
+      Loaded.push_back(M);
+      return Success;
+
     default:
       if (Stream.SkipBlock()) {
         Error("malformed block record in AST file");
@@ -3005,32 +3102,6 @@
     }
   }
   
-  // Once read, set the ModuleFile bit base offset and update the size in 
-  // bits of all files we've seen.
-  F.GlobalBitOffset = TotalModulesSizeInBits;
-  TotalModulesSizeInBits += F.SizeInBits;
-  GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
-
-  // Make sure that the files this module was built against are still available.
-  if (!DisableValidation) {
-    switch(validateFileEntries(*M)) {
-    case Failure: return Failure;
-    case IgnorePCH: return IgnorePCH;
-    case Success: break;
-    }
-  }
-  
-  // Preload SLocEntries.
-  for (unsigned I = 0, N = M->PreloadSLocEntries.size(); I != N; ++I) {
-    int Index = int(M->PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
-    // Load it through the SourceManager and don't call ReadSLocEntryRecord()
-    // directly because the entry may have already been loaded in which case
-    // calling ReadSLocEntryRecord() directly would trigger an assertion in
-    // SourceManager.
-    SourceMgr.getLoadedSLocEntryByID(Index);
-  }
-
-
   return Success;
 }
 
@@ -3218,8 +3289,8 @@
 
       // We only know the AST subblock ID.
       switch (BlockID) {
-      case AST_BLOCK_ID:
-        if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+      case CONTROL_BLOCK_ID:
+        if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
           Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
           return std::string();
         }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=166166&r1=166165&r2=166166&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Oct 18 00:31:06 2012
@@ -978,11 +978,12 @@
   return Filename + Pos;
 }
 
-/// \brief Write the AST metadata (e.g., i686-apple-darwin9).
-void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot,
-                              const std::string &OutputFile) {
+/// \brief Write the control block.
+void ASTWriter::WriteControlBlock(ASTContext &Context, StringRef isysroot,
+                                  const std::string &OutputFile) {
   using namespace llvm;
-
+  Stream.EnterSubblock(CONTROL_BLOCK_ID, 4);
+  
   // Metadata
   const TargetInfo &Target = Context.getTargetInfo();
   const TargetOptions &TargetOpts = Target.getTargetOpts();
@@ -1008,6 +1009,7 @@
   }
   Stream.EmitRecord(METADATA, Record);
 
+  // Imports
   if (Chain) {
     serialization::ModuleManager &Mgr = Chain->getModuleManager();
     llvm::SmallVector<char, 128> ModulePaths;
@@ -1029,6 +1031,22 @@
     Stream.EmitRecord(IMPORTS, Record);
   }
 
+  // Language options.
+  Record.clear();
+  const LangOptions &LangOpts = Context.getLangOpts();
+#define LANGOPT(Name, Bits, Default, Description) \
+  Record.push_back(LangOpts.Name);
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+  Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));
+#include "clang/Basic/LangOptions.def"  
+
+  Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());
+  AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);
+  
+  Record.push_back(LangOpts.CurrentModule.size());
+  Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end());
+  Stream.EmitRecord(LANGUAGE_OPTIONS, Record);
+
   // Original file name and file ID
   SourceManager &SM = Context.getSourceManager();
   if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
@@ -1079,23 +1097,8 @@
   Record.push_back(VERSION_CONTROL_BRANCH_REVISION);
   Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
                             getClangFullRepositoryVersion());
-}
 
-/// \brief Write the LangOptions structure.
-void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
-  RecordData Record;
-#define LANGOPT(Name, Bits, Default, Description) \
-  Record.push_back(LangOpts.Name);
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
-  Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));
-#include "clang/Basic/LangOptions.def"  
-
-  Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());
-  AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);
-  
-  Record.push_back(LangOpts.CurrentModule.size());
-  Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end());
-  Stream.EmitRecord(LANGUAGE_OPTIONS, Record);
+  Stream.ExitBlock();
 }
 
 //===----------------------------------------------------------------------===//
@@ -3433,12 +3436,13 @@
     if (!I->second)
       AddDeclRef(I->first, KnownNamespaces);
   }
-  
+
+  // Write the control block
+  WriteControlBlock(Context, isysroot, OutputFile);
+
   // Write the remaining AST contents.
   RecordData Record;
   Stream.EnterSubblock(AST_BLOCK_ID, 5);
-  WriteLanguageOptions(Context.getLangOpts());
-  WriteMetadata(Context, isysroot, OutputFile);
   if (StatCalls && isysroot.empty())
     WriteStatCache(*StatCalls);
 





More information about the cfe-commits mailing list