diff options
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 166 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 5 | ||||
-rw-r--r-- | include/clang/Serialization/ASTWriter.h | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 335 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 50 |
5 files changed, 323 insertions, 238 deletions
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 68b8bf00cc..b5171f529b 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -216,7 +216,46 @@ namespace clang { 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 @@ namespace clang { /// 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 @@ namespace clang { /// 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 @@ namespace clang { /// 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 @@ namespace clang { /// 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 @@ namespace clang { /// 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. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 02e9927dbe..48b97c153e 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -886,7 +886,10 @@ private: 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); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index a4ff416bd8..3fb754dca9 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -409,9 +409,8 @@ private: 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, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 67a54caf64..5d2e8d6cfc 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1744,6 +1744,152 @@ void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) { 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 @@ ASTReader::ReadASTBlock(ModuleFile &F) { 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 @@ ASTReader::ReadASTBlock(ModuleFile &F) { 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 @@ ASTReader::ReadASTBlock(ModuleFile &F) { 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 @@ ASTReader::ReadASTBlock(ModuleFile &F) { 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 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, 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 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, // 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::ReadAST(const std::string &FileName, 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 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, 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 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, // 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 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, } } - // 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 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, // 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(); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index c37f881d98..b6f302605b 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -978,11 +978,12 @@ adjustFilenameForRelocatablePCH(const char *Filename, StringRef isysroot) { 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 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, } Stream.EmitRecord(METADATA, Record); + // Imports if (Chain) { serialization::ModuleManager &Mgr = Chain->getModuleManager(); llvm::SmallVector<char, 128> ModulePaths; @@ -1029,6 +1031,22 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, 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 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, 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 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, 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); |