diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/Serialization/ASTWriter.cpp | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 781 |
1 files changed, 509 insertions, 272 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 425d2e3..a2e8b71 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -25,9 +25,11 @@ #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/Serialization/ASTReader.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemStatCache.h" @@ -35,6 +37,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/APFloat.h" @@ -485,6 +488,8 @@ void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { } void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { Writer.AddSourceLocation(TL.getLocalRangeBegin(), Record); + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); Writer.AddSourceLocation(TL.getLocalRangeEnd(), Record); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) Writer.AddDeclRef(TL.getArg(i), Record); @@ -667,7 +672,8 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(STMT_BREAK); RECORD(STMT_RETURN); RECORD(STMT_DECL); - RECORD(STMT_ASM); + RECORD(STMT_GCCASM); + RECORD(STMT_MSASM); RECORD(EXPR_PREDEFINED); RECORD(EXPR_DECL_REF); RECORD(EXPR_INTEGER_LITERAL); @@ -763,14 +769,27 @@ void ASTWriter::WriteBlockInfoBlock() { #define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record) #define RECORD(X) EmitRecordID(X, #X, Stream, Record) + // Control Block. + BLOCK(CONTROL_BLOCK); + RECORD(METADATA); + RECORD(IMPORTS); + RECORD(LANGUAGE_OPTIONS); + RECORD(TARGET_OPTIONS); + RECORD(ORIGINAL_FILE); + RECORD(ORIGINAL_PCH_DIR); + RECORD(INPUT_FILE_OFFSETS); + RECORD(DIAGNOSTIC_OPTIONS); + RECORD(FILE_SYSTEM_OPTIONS); + RECORD(HEADER_SEARCH_OPTIONS); + RECORD(PREPROCESSOR_OPTIONS); + + BLOCK(INPUT_FILES_BLOCK); + RECORD(INPUT_FILE); + // AST Top-Level Block. BLOCK(AST_BLOCK); - RECORD(ORIGINAL_FILE_NAME); - RECORD(ORIGINAL_FILE_ID); RECORD(TYPE_OFFSET); RECORD(DECL_OFFSET); - RECORD(LANGUAGE_OPTIONS); - RECORD(METADATA); RECORD(IDENTIFIER_OFFSET); RECORD(IDENTIFIER_TABLE); RECORD(EXTERNAL_DEFINITIONS); @@ -784,11 +803,8 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(PP_COUNTER_VALUE); RECORD(SOURCE_LOCATION_OFFSETS); RECORD(SOURCE_LOCATION_PRELOADS); - RECORD(STAT_CACHE); RECORD(EXT_VECTOR_DECLS); - RECORD(VERSION_CONTROL_BRANCH_REVISION); RECORD(PPD_ENTITIES_OFFSETS); - RECORD(IMPORTS); RECORD(REFERENCED_SELECTOR_POOL); RECORD(TU_UPDATE_LEXICAL); RECORD(LOCAL_REDECLARATIONS_MAP); @@ -803,11 +819,9 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DIAG_PRAGMA_MAPPINGS); RECORD(CUDA_SPECIAL_DECL_REFS); RECORD(HEADER_SEARCH_TABLE); - RECORD(ORIGINAL_PCH_DIR); RECORD(FP_PRAGMA_OPTIONS); RECORD(OPENCL_EXTENSIONS); RECORD(DELEGATING_CTORS); - RECORD(FILE_SOURCE_LOCATION_OFFSETS); RECORD(KNOWN_NAMESPACES); RECORD(MODULE_OFFSET_MAP); RECORD(SOURCE_MANAGER_LINE_TABLE); @@ -817,6 +831,8 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MERGED_DECLARATIONS); RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); + RECORD(MACRO_OFFSET); + RECORD(MACRO_UPDATES); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -972,25 +988,25 @@ 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(Preprocessor &PP, ASTContext &Context, + StringRef isysroot, + const std::string &OutputFile) { using namespace llvm; - - // Metadata - const TargetInfo &Target = Context.getTargetInfo(); - BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); - MetaAbbrev->Add(BitCodeAbbrevOp(METADATA)); - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST minor - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Has errors - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple - unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); - + Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); RecordData Record; + + // Metadata + BitCodeAbbrev *MetadataAbbrev = new BitCodeAbbrev(); + MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA)); + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj. + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min. + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors + MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag + unsigned MetadataAbbrevCode = Stream.EmitAbbrev(MetadataAbbrev); Record.push_back(METADATA); Record.push_back(VERSION_MAJOR); Record.push_back(VERSION_MINOR); @@ -998,9 +1014,10 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, Record.push_back(CLANG_VERSION_MINOR); Record.push_back(!isysroot.empty()); Record.push_back(ASTHasCompilerErrors); - const std::string &Triple = Target.getTriple().getTriple(); - Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple); + Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, + getClangFullRepositoryVersion()); + // Imports if (Chain) { serialization::ModuleManager &Mgr = Chain->getModuleManager(); llvm::SmallVector<char, 128> ModulePaths; @@ -1022,11 +1039,131 @@ 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); + + // Target options. + Record.clear(); + const TargetInfo &Target = Context.getTargetInfo(); + const TargetOptions &TargetOpts = Target.getTargetOpts(); + AddString(TargetOpts.Triple, Record); + AddString(TargetOpts.CPU, Record); + AddString(TargetOpts.ABI, Record); + AddString(TargetOpts.CXXABI, Record); + AddString(TargetOpts.LinkerVersion, Record); + Record.push_back(TargetOpts.FeaturesAsWritten.size()); + for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) { + AddString(TargetOpts.FeaturesAsWritten[I], Record); + } + Record.push_back(TargetOpts.Features.size()); + for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) { + AddString(TargetOpts.Features[I], Record); + } + Stream.EmitRecord(TARGET_OPTIONS, Record); + + // Diagnostic options. + Record.clear(); + const DiagnosticOptions &DiagOpts + = Context.getDiagnostics().getDiagnosticOptions(); +#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name); +#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ + Record.push_back(static_cast<unsigned>(DiagOpts.get##Name())); +#include "clang/Basic/DiagnosticOptions.def" + Record.push_back(DiagOpts.Warnings.size()); + for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I) + AddString(DiagOpts.Warnings[I], Record); + // Note: we don't serialize the log or serialization file names, because they + // are generally transient files and will almost always be overridden. + Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); + + // File system options. + Record.clear(); + const FileSystemOptions &FSOpts + = Context.getSourceManager().getFileManager().getFileSystemOptions(); + AddString(FSOpts.WorkingDir, Record); + Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record); + + // Header search options. + Record.clear(); + const HeaderSearchOptions &HSOpts + = PP.getHeaderSearchInfo().getHeaderSearchOpts(); + AddString(HSOpts.Sysroot, Record); + + // Include entries. + Record.push_back(HSOpts.UserEntries.size()); + for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { + const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; + AddString(Entry.Path, Record); + Record.push_back(static_cast<unsigned>(Entry.Group)); + Record.push_back(Entry.IsUserSupplied); + Record.push_back(Entry.IsFramework); + Record.push_back(Entry.IgnoreSysRoot); + Record.push_back(Entry.IsInternal); + Record.push_back(Entry.ImplicitExternC); + } + + // System header prefixes. + Record.push_back(HSOpts.SystemHeaderPrefixes.size()); + for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { + AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); + Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); + } + + AddString(HSOpts.ResourceDir, Record); + AddString(HSOpts.ModuleCachePath, Record); + Record.push_back(HSOpts.DisableModuleHash); + Record.push_back(HSOpts.UseBuiltinIncludes); + Record.push_back(HSOpts.UseStandardSystemIncludes); + Record.push_back(HSOpts.UseStandardCXXIncludes); + Record.push_back(HSOpts.UseLibcxx); + Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record); + + // Preprocessor options. + Record.clear(); + const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts(); + + // Macro definitions. + Record.push_back(PPOpts.Macros.size()); + for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) { + AddString(PPOpts.Macros[I].first, Record); + Record.push_back(PPOpts.Macros[I].second); + } + + // Includes + Record.push_back(PPOpts.Includes.size()); + for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I) + AddString(PPOpts.Includes[I], Record); + + // Macro includes + Record.push_back(PPOpts.MacroIncludes.size()); + for (unsigned I = 0, N = PPOpts.MacroIncludes.size(); I != N; ++I) + AddString(PPOpts.MacroIncludes[I], Record); + + Record.push_back(PPOpts.UsePredefines); + AddString(PPOpts.ImplicitPCHInclude, Record); + AddString(PPOpts.ImplicitPTHInclude, Record); + Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary)); + Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record); + // Original file name and file ID SourceManager &SM = Context.getSourceManager(); if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); - FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE_NAME)); + FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE)); + FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); @@ -1037,13 +1174,10 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, const char *MainFileNameStr = MainFilePath.c_str(); MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, isysroot); - RecordData Record; - Record.push_back(ORIGINAL_FILE_NAME); - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); - Record.clear(); + Record.push_back(ORIGINAL_FILE); Record.push_back(SM.getMainFileID().getOpaqueValue()); - Stream.EmitRecord(ORIGINAL_FILE_ID, Record); + Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); } // Original PCH directory @@ -1063,32 +1197,86 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot, Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); } - // Repository branch/version information. - BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev(); - RepoAbbrev->Add(BitCodeAbbrevOp(VERSION_CONTROL_BRANCH_REVISION)); - RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag - unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev); - Record.clear(); - Record.push_back(VERSION_CONTROL_BRANCH_REVISION); - Stream.EmitRecordWithBlob(RepoAbbrevCode, Record, - getClangFullRepositoryVersion()); + WriteInputFiles(Context.SourceMgr, isysroot); + Stream.ExitBlock(); } -/// \brief Write the LangOptions structure. -void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { +void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { + using namespace llvm; + Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); 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" + + // Create input-file abbreviation. + BitCodeAbbrev *IFAbbrev = new BitCodeAbbrev(); + IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE)); + IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID + IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size + IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time + IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden + IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name + unsigned IFAbbrevCode = Stream.EmitAbbrev(IFAbbrev); + + // Write out all of the input files. + std::vector<uint32_t> InputFileOffsets; + for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { + // Get this source location entry. + const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); + assert(&SourceMgr.getSLocEntry(FileID::get(I)) == SLoc); - Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind()); - AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record); + // We only care about file entries that were not overridden. + if (!SLoc->isFile()) + continue; + const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); + if (!Cache->OrigEntry) + continue; + + // Record this entry's offset. + InputFileOffsets.push_back(Stream.GetCurrentBitNo()); + InputFileIDs[Cache->OrigEntry] = InputFileOffsets.size(); + + Record.clear(); + Record.push_back(INPUT_FILE); + Record.push_back(InputFileOffsets.size()); + + // Emit size/modification time for this file. + Record.push_back(Cache->OrigEntry->getSize()); + Record.push_back(Cache->OrigEntry->getModificationTime()); + + // Whether this file was overridden. + Record.push_back(Cache->BufferOverridden); + + // Turn the file name into an absolute path, if it isn't already. + const char *Filename = Cache->OrigEntry->getName(); + SmallString<128> FilePath(Filename); + + // Ask the file manager to fixup the relative path for us. This will + // honor the working directory. + SourceMgr.getFileManager().FixupRelativePath(FilePath); + + // FIXME: This call to make_absolute shouldn't be necessary, the + // call to FixupRelativePath should always return an absolute path. + llvm::sys::fs::make_absolute(FilePath); + Filename = FilePath.c_str(); + + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); + + Stream.EmitRecordWithBlob(IFAbbrevCode, Record, Filename); + } - Record.push_back(LangOpts.CurrentModule.size()); - Record.append(LangOpts.CurrentModule.begin(), LangOpts.CurrentModule.end()); - Stream.EmitRecord(LANGUAGE_OPTIONS, Record); + Stream.ExitBlock(); + + // Create input file offsets abbreviation. + BitCodeAbbrev *OffsetsAbbrev = new BitCodeAbbrev(); + OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS)); + OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files + OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Array + unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(OffsetsAbbrev); + + // Write input file offsets. + Record.clear(); + Record.push_back(INPUT_FILE_OFFSETS); + Record.push_back(InputFileOffsets.size()); + Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets)); } //===----------------------------------------------------------------------===// @@ -1139,46 +1327,6 @@ public: }; } // end anonymous namespace -/// \brief Write the stat() system call cache to the AST file. -void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { - // Build the on-disk hash table containing information about every - // stat() call. - OnDiskChainedHashTableGenerator<ASTStatCacheTrait> Generator; - unsigned NumStatEntries = 0; - for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), - StatEnd = StatCalls.end(); - Stat != StatEnd; ++Stat, ++NumStatEntries) { - StringRef Filename = Stat->first(); - Generator.insert(Filename.data(), Stat->second); - } - - // Create the on-disk hash table in a buffer. - SmallString<4096> StatCacheData; - uint32_t BucketOffset; - { - llvm::raw_svector_ostream Out(StatCacheData); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out); - } - - // Create a blob abbreviation - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(STAT_CACHE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the stat cache - RecordData Record; - Record.push_back(STAT_CACHE); - Record.push_back(BucketOffset); - Record.push_back(NumStatEntries); - Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str()); -} - //===----------------------------------------------------------------------===// // Source Manager Serialization //===----------------------------------------------------------------------===// @@ -1194,13 +1342,10 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives // FileEntry fields. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // BufferOverridden + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name return Stream.EmitAbbrev(Abbrev); } @@ -1329,8 +1474,6 @@ namespace { /// \brief Write the header search block for the list of files that /// /// \param HS The header search structure to save. -/// -/// \param Chain Whether we're creating a chained AST file. void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) { SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); @@ -1427,15 +1570,14 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Write out the source location entry table. We skip the first // entry, which is always the same dummy entry. std::vector<uint32_t> SLocEntryOffsets; - // Write out the offsets of only source location file entries. - // We will go through them in ASTReader::validateFileEntries(). - std::vector<uint32_t> SLocFileEntryOffsets; RecordData PreloadSLocs; SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1); for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); + FileID FID = FileID::get(I); + assert(&SourceMgr.getSLocEntry(FID) == SLoc); // Record the offset of this source-location entry. SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); @@ -1446,7 +1588,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); if (Cache->OrigEntry) { Code = SM_SLOC_FILE_ENTRY; - SLocFileEntryOffsets.push_back(Stream.GetCurrentBitNo()); } else Code = SM_SLOC_BUFFER_ENTRY; } else @@ -1467,16 +1608,13 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, assert(Content->OrigEntry == Content->ContentsEntry && "Writing to AST an overridden file is not supported"); - // The source location entry is a file. The blob associated - // with this entry is the file name. + // The source location entry is a file. Emit input file ID. + assert(InputFileIDs[Content->OrigEntry] != 0 && "Missed file entry"); + Record.push_back(InputFileIDs[Content->OrigEntry]); - // Emit size/modification time for this file. - Record.push_back(Content->OrigEntry->getSize()); - Record.push_back(Content->OrigEntry->getModificationTime()); - Record.push_back(Content->BufferOverridden); Record.push_back(File.NumCreatedFIDs); - FileDeclIDsTy::iterator FDI = FileDeclIDs.find(SLoc); + FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); if (FDI != FileDeclIDs.end()) { Record.push_back(FDI->second->FirstDeclIndex); Record.push_back(FDI->second->DeclIDs.size()); @@ -1485,21 +1623,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(0); } - // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Content->OrigEntry->getName(); - SmallString<128> FilePath(Filename); - - // Ask the file manager to fixup the relative path for us. This will - // honor the working directory. - SourceMgr.getFileManager().FixupRelativePath(FilePath); - - // FIXME: This call to make_absolute shouldn't be necessary, the - // call to FixupRelativePath should always return an absolute path. - llvm::sys::fs::make_absolute(FilePath); - Filename = FilePath.c_str(); - - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename); + Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record); if (Content->BufferOverridden) { Record.clear(); @@ -1570,18 +1694,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets)); - Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(FILE_SOURCE_LOCATION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets - unsigned SLocFileOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); - - Record.clear(); - Record.push_back(FILE_SOURCE_LOCATION_OFFSETS); - Record.push_back(SLocFileEntryOffsets.size()); - Stream.EmitRecordWithBlob(SLocFileOffsetsAbbrev, Record, - data(SLocFileEntryOffsets)); - // Write the source location entry preloads array, telling the AST // reader which source locations entries it should load eagerly. Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs); @@ -1675,102 +1787,129 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { SmallVector<std::pair<const IdentifierInfo *, MacroInfo *>, 2> MacrosToEmit; llvm::SmallPtrSet<const IdentifierInfo*, 4> MacroDefinitionsSeen; - for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), + for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), E = PP.macro_end(Chain == 0); I != E; ++I) { - const IdentifierInfo *Name = I->first; if (!IsModule || I->second->isPublic()) { - MacroDefinitionsSeen.insert(Name); + MacroDefinitionsSeen.insert(I->first); MacrosToEmit.push_back(std::make_pair(I->first, I->second)); } } - + // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. - llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(), + llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(), &compareMacroDefinitions); - - // Resolve any identifiers that defined macros at the time they were - // deserialized, adding them to the list of macros to emit (if appropriate). - for (unsigned I = 0, N = DeserializedMacroNames.size(); I != N; ++I) { - IdentifierInfo *Name - = const_cast<IdentifierInfo *>(DeserializedMacroNames[I]); - if (Name->hasMacroDefinition() && MacroDefinitionsSeen.insert(Name)) - MacrosToEmit.push_back(std::make_pair(Name, PP.getMacroInfo(Name))); - } - + + /// \brief Offsets of each of the macros into the bitstream, indexed by + /// the local macro ID + /// + /// For each identifier that is associated with a macro, this map + /// provides the offset into the bitstream where that macro is + /// defined. + std::vector<uint32_t> MacroOffsets; + for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { const IdentifierInfo *Name = MacrosToEmit[I].first; - MacroInfo *MI = MacrosToEmit[I].second; - if (!MI) - continue; - - // Don't emit builtin macros like __LINE__ to the AST file unless they have - // been redefined by the header (in which case they are not isBuiltinMacro). - // Also skip macros from a AST file if we're chaining. - - // FIXME: There is a (probably minor) optimization we could do here, if - // the macro comes from the original PCH but the identifier comes from a - // chained PCH, by storing the offset into the original PCH rather than - // writing the macro definition a second time. - if (MI->isBuiltinMacro() || - (Chain && - Name->isFromAST() && !Name->hasChangedSinceDeserialization() && - MI->isFromAST() && !MI->hasChangedAfterLoad())) - continue; - AddIdentifierRef(Name, Record); - MacroOffsets[Name] = Stream.GetCurrentBitNo(); - Record.push_back(MI->getDefinitionLoc().getRawEncoding()); - Record.push_back(MI->isUsed()); - Record.push_back(MI->isPublic()); - AddSourceLocation(MI->getVisibilityLocation(), Record); - unsigned Code; - if (MI->isObjectLike()) { - Code = PP_MACRO_OBJECT_LIKE; - } else { - Code = PP_MACRO_FUNCTION_LIKE; + for (MacroInfo *MI = MacrosToEmit[I].second; MI; + MI = MI->getPreviousDefinition()) { + MacroID ID = getMacroRef(MI); + if (!ID) + continue; - Record.push_back(MI->isC99Varargs()); - Record.push_back(MI->isGNUVarargs()); - Record.push_back(MI->getNumArgs()); - for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); - I != E; ++I) - AddIdentifierRef(*I, Record); - } + // Skip macros from a AST file if we're chaining. + if (Chain && MI->isFromAST() && !MI->hasChangedAfterLoad()) + continue; - // If we have a detailed preprocessing record, record the macro definition - // ID that corresponds to this macro. - if (PPRec) - Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); + if (ID < FirstMacroID) { + // This will have been dealt with via an update record. + assert(MacroUpdates.count(MI) > 0 && "Missing macro update"); + continue; + } - Stream.EmitRecord(Code, Record); - Record.clear(); + // Record the local offset of this macro. + unsigned Index = ID - FirstMacroID; + if (Index == MacroOffsets.size()) + MacroOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > MacroOffsets.size()) + MacroOffsets.resize(Index + 1); - // Emit the tokens array. - for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { - // Note that we know that the preprocessor does not have any annotation - // tokens in it because they are created by the parser, and thus can't be - // in a macro definition. - const Token &Tok = MI->getReplacementToken(TokNo); - - Record.push_back(Tok.getLocation().getRawEncoding()); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer if - // it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); - // FIXME: Should translate token kind to a stable encoding. - Record.push_back(Tok.getKind()); - // FIXME: Should translate token flags to a stable encoding. - Record.push_back(Tok.getFlags()); - - Stream.EmitRecord(PP_TOKEN, Record); + MacroOffsets[Index] = Stream.GetCurrentBitNo(); + } + + AddIdentifierRef(Name, Record); + addMacroRef(MI, Record); + Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc())); + AddSourceLocation(MI->getDefinitionLoc(), Record); + AddSourceLocation(MI->getUndefLoc(), Record); + Record.push_back(MI->isUsed()); + Record.push_back(MI->isPublic()); + AddSourceLocation(MI->getVisibilityLocation(), Record); + unsigned Code; + if (MI->isObjectLike()) { + Code = PP_MACRO_OBJECT_LIKE; + } else { + Code = PP_MACRO_FUNCTION_LIKE; + + Record.push_back(MI->isC99Varargs()); + Record.push_back(MI->isGNUVarargs()); + Record.push_back(MI->getNumArgs()); + for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); + I != E; ++I) + AddIdentifierRef(*I, Record); + } + + // If we have a detailed preprocessing record, record the macro definition + // ID that corresponds to this macro. + if (PPRec) + Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); + + Stream.EmitRecord(Code, Record); Record.clear(); + + // Emit the tokens array. + for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { + // Note that we know that the preprocessor does not have any annotation + // tokens in it because they are created by the parser, and thus can't + // be in a macro definition. + const Token &Tok = MI->getReplacementToken(TokNo); + + Record.push_back(Tok.getLocation().getRawEncoding()); + Record.push_back(Tok.getLength()); + + // FIXME: When reading literal tokens, reconstruct the literal pointer + // if it is needed. + AddIdentifierRef(Tok.getIdentifierInfo(), Record); + // FIXME: Should translate token kind to a stable encoding. + Record.push_back(Tok.getKind()); + // FIXME: Should translate token flags to a stable encoding. + Record.push_back(Tok.getFlags()); + + Stream.EmitRecord(PP_TOKEN, Record); + Record.clear(); + } + ++NumMacros; } - ++NumMacros; } Stream.ExitBlock(); + + // Write the offsets table for macro IDs. + using namespace llvm; + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + + unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + Record.clear(); + Record.push_back(MACRO_OFFSET); + Record.push_back(MacroOffsets.size()); + Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS); + Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, + data(MacroOffsets)); } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { @@ -1794,6 +1933,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // imported module Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); InclusionAbbrev = Stream.EmitAbbrev(Abbrev); } @@ -1836,6 +1976,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { Record.push_back(ID->getFileName().size()); Record.push_back(ID->wasInQuotes()); Record.push_back(static_cast<unsigned>(ID->getKind())); + Record.push_back(ID->importedModule()); SmallString<64> Buffer; Buffer += ID->getFileName(); // Check that the FileEntry is not null because it was not resolved and @@ -1935,6 +2076,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { unsigned HeaderAbbrev = Stream.EmitAbbrev(Abbrev); Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TOPHEADER)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned TopHeaderAbbrev = Stream.EmitAbbrev(Abbrev); + + Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(Abbrev); @@ -1944,6 +2090,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev); + Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name + unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev); + // Write the submodule metadata block. RecordData Record; Record.push_back(getNumberOfModules(WritingModule)); @@ -2005,6 +2156,19 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecordWithBlob(HeaderAbbrev, Record, Mod->Headers[I]->getName()); } + // Emit the excluded headers. + for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_EXCLUDED_HEADER); + Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record, + Mod->ExcludedHeaders[I]->getName()); + } + for (unsigned I = 0, N = Mod->TopHeaders.size(); I != N; ++I) { + Record.clear(); + Record.push_back(SUBMODULE_TOPHEADER); + Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, + Mod->TopHeaders[I]->getName()); + } // Emit the imports. if (!Mod->Imports.empty()) { @@ -2067,24 +2231,35 @@ ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) { } void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag) { + // FIXME: Make it work properly with modules. + llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64> + DiagStateIDMap; + unsigned CurrID = 0; + DiagStateIDMap[&Diag.DiagStates.front()] = ++CurrID; // the command-line one. RecordData Record; for (DiagnosticsEngine::DiagStatePointsTy::const_iterator I = Diag.DiagStatePoints.begin(), E = Diag.DiagStatePoints.end(); I != E; ++I) { - const DiagnosticsEngine::DiagStatePoint &point = *I; + const DiagnosticsEngine::DiagStatePoint &point = *I; if (point.Loc.isInvalid()) continue; Record.push_back(point.Loc.getRawEncoding()); - for (DiagnosticsEngine::DiagState::const_iterator - I = point.State->begin(), E = point.State->end(); I != E; ++I) { - if (I->second.isPragma()) { - Record.push_back(I->first); - Record.push_back(I->second.getMapping()); + unsigned &DiagStateID = DiagStateIDMap[point.State]; + Record.push_back(DiagStateID); + + if (DiagStateID == 0) { + DiagStateID = ++CurrID; + for (DiagnosticsEngine::DiagState::const_iterator + I = point.State->begin(), E = point.State->end(); I != E; ++I) { + if (I->second.isPragma()) { + Record.push_back(I->first); + Record.push_back(I->second.getMapping()); + } } + Record.push_back(-1); // mark the end of the diag/map pairs for this + // location. } - Record.push_back(-1); // mark the end of the diag/map pairs for this - // location. } if (!Record.empty()) @@ -2238,9 +2413,11 @@ void ASTWriter::WriteFileDeclIDsMap() { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); Record.push_back(FILE_SORTED_DECLS); + Record.push_back(FileSortedIDs.size()); Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs)); } @@ -2495,17 +2672,17 @@ class ASTIdentifierTableTrait { II->getFETokenInfo<void>()) return true; - return hasMacroDefinition(II, Macro); + return hadMacroDefinition(II, Macro); } - - bool hasMacroDefinition(IdentifierInfo *II, MacroInfo *&Macro) { - if (!II->hasMacroDefinition()) + + bool hadMacroDefinition(IdentifierInfo *II, MacroInfo *&Macro) { + if (!II->hadMacroDefinition()) return false; - - if (Macro || (Macro = PP.getMacroInfo(II))) + + if (Macro || (Macro = PP.getMacroInfoHistory(II))) return !Macro->isBuiltinMacro() && (!IsModule || Macro->isPublic()); - - return false; + + return false; } public: @@ -2529,10 +2706,17 @@ public: unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 MacroInfo *Macro = 0; if (isInterestingIdentifier(II, Macro)) { - DataLen += 2; // 2 bytes for builtin ID, flags - if (hasMacroDefinition(II, Macro)) - DataLen += 8; - + DataLen += 2; // 2 bytes for builtin ID + DataLen += 2; // 2 bytes for flags + if (hadMacroDefinition(II, Macro)) { + for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) { + if (Writer.getMacroRef(M) != 0) + DataLen += 4; + } + + DataLen += 4; + } + for (IdentifierResolver::iterator D = IdResolver.begin(II), DEnd = IdResolver.end(); D != DEnd; ++D) @@ -2563,23 +2747,28 @@ public: } clang::io::Emit32(Out, (ID << 1) | 0x01); - uint32_t Bits = 0; - bool HasMacroDefinition = hasMacroDefinition(II, Macro); - Bits = (uint32_t)II->getObjCOrBuiltinID(); - assert((Bits & 0x7ff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); - Bits = (Bits << 1) | unsigned(HasMacroDefinition); + uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID(); + assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); + clang::io::Emit16(Out, Bits); + Bits = 0; + bool HadMacroDefinition = hadMacroDefinition(II, Macro); + Bits = (Bits << 1) | unsigned(HadMacroDefinition); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); clang::io::Emit16(Out, Bits); - if (HasMacroDefinition) { - clang::io::Emit32(Out, Writer.getMacroOffset(II)); - clang::io::Emit32(Out, - Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc())); + if (HadMacroDefinition) { + // Write all of the macro IDs associated with this identifier. + for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) { + if (MacroID ID = Writer.getMacroRef(M)) + clang::io::Emit32(Out, ID); + } + + clang::io::Emit32(Out, 0); } - + // Emit the declaration IDs in reverse order, because the // IdentifierResolver provides the declarations as they would be // visible (e.g., the function "stat" would come before the struct @@ -2756,30 +2945,32 @@ public: void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) { using namespace clang::io; - assert(Name.getNameKind() < 0x100 && "Invalid name kind ?"); Emit8(Out, Name.getNameKind()); switch (Name.getNameKind()) { case DeclarationName::Identifier: Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo())); - break; + return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector())); - break; + return; case DeclarationName::CXXOperatorName: - assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?"); + assert(Name.getCXXOverloadedOperator() < NUM_OVERLOADED_OPERATORS && + "Invalid operator?"); Emit8(Out, Name.getCXXOverloadedOperator()); - break; + return; case DeclarationName::CXXLiteralOperatorName: Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier())); - break; + return; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXUsingDirective: - break; + return; } + + llvm_unreachable("Invalid name kind?"); } void EmitData(raw_ostream& Out, key_type_ref, @@ -3147,7 +3338,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), - FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID), FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), NextSubmoduleID(FirstSubmoduleID), FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), @@ -3171,7 +3363,7 @@ ASTWriter::~ASTWriter() { delete I->second; } -void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, +void ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors) { @@ -3190,7 +3382,7 @@ void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, Context = &SemaRef.Context; PP = &SemaRef.PP; this->WritingModule = WritingModule; - WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, WritingModule); + WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); Context = 0; PP = 0; this->WritingModule = 0; @@ -3207,7 +3399,7 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, } } -void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, +void ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, const std::string &OutputFile, Module *WritingModule) { @@ -3357,14 +3549,13 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, if (!I->second) AddDeclRef(I->first, KnownNamespaces); } - + + // Write the control block + WriteControlBlock(PP, Context, isysroot, OutputFile); + // Write the remaining AST contents. RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); - WriteMetadata(Context, isysroot, OutputFile); - WriteLanguageOptions(Context.getLangOpts()); - if (StatCalls && isysroot.empty()) - WriteStatCache(*StatCalls); // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. @@ -3482,6 +3673,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Out.write(FileName.data(), FileName.size()); io::Emit32(Out, (*M)->SLocEntryBaseOffset); io::Emit32(Out, (*M)->BaseIdentifierID); + io::Emit32(Out, (*M)->BaseMacroID); io::Emit32(Out, (*M)->BasePreprocessedEntityID); io::Emit32(Out, (*M)->BaseSubmoduleID); io::Emit32(Out, (*M)->BaseSelectorID); @@ -3595,7 +3787,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); } } - + + WriteMacroUpdates(); WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); WriteMergedDecls(); @@ -3612,6 +3805,21 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.ExitBlock(); } +void ASTWriter::WriteMacroUpdates() { + if (MacroUpdates.empty()) + return; + + RecordData Record; + for (MacroUpdatesMap::iterator I = MacroUpdates.begin(), + E = MacroUpdates.end(); + I != E; ++I) { + addMacroRef(I->first, Record); + AddSourceLocation(I->second.UndefLoc, Record); + Record.push_back(inferSubmoduleIDFromLocation(I->second.UndefLoc)); + } + Stream.EmitRecord(MACRO_UPDATES, Record); +} + /// \brief Go through the declaration update blocks and resolve declaration /// pointers into declaration IDs. void ASTWriter::ResolveDeclUpdatesBlocks() { @@ -3707,6 +3915,10 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } +void ASTWriter::addMacroRef(MacroInfo *MI, RecordDataImpl &Record) { + Record.push_back(getMacroRef(MI)); +} + IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (II == 0) return 0; @@ -3717,6 +3929,19 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { return ID; } +MacroID ASTWriter::getMacroRef(MacroInfo *MI) { + // Don't emit builtin macros like __LINE__ to the AST file unless they + // have been redefined by the header (in which case they are not + // isBuiltinMacro). + if (MI == 0 || MI->isBuiltinMacro()) + return 0; + + MacroID &ID = MacroIDs[MI]; + if (ID == 0) + ID = NextMacroID++; + return ID; +} + void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { Record.push_back(getSelectorRef(SelRef)); } @@ -3774,7 +3999,9 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: case TemplateArgument::Pack: + // FIXME: Is this right? break; } } @@ -3931,10 +4158,9 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); if (FID.isInvalid()) return; - const SrcMgr::SLocEntry *Entry = &SM.getSLocEntry(FID); - assert(Entry->isFile()); + assert(SM.getSLocEntry(FID).isFile()); - DeclIDInFileInfo *&Info = FileDeclIDs[Entry]; + DeclIDInFileInfo *&Info = FileDeclIDs[FID]; if (!Info) Info = new DeclIDInFileInfo(); @@ -4191,6 +4417,10 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, break; case TemplateArgument::Declaration: AddDeclRef(Arg.getAsDecl(), Record); + Record.push_back(Arg.isDeclForReferenceParam()); + break; + case TemplateArgument::NullPtr: + AddTypeRef(Arg.getNullPtrType(), Record); break; case TemplateArgument::Integral: AddAPSInt(Arg.getAsIntegral(), Record); @@ -4403,6 +4633,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Lambda.NumExplicitCaptures); Record.push_back(Lambda.ManglingNumber); AddDeclRef(Lambda.ContextDecl, Record); + AddTypeSourceInfo(Lambda.MethodTyInfo, Record); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { LambdaExpr::Capture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation(), Record); @@ -4423,6 +4654,7 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && + FirstMacroID == NextMacroID && FirstSubmoduleID == NextSubmoduleID && FirstSelectorID == NextSelectorID && "Setting chain after writing has started."); @@ -4432,19 +4664,23 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); + FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; + NextMacroID = FirstMacroID; NextSelectorID = FirstSelectorID; NextSubmoduleID = FirstSubmoduleID; } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { IdentifierIDs[II] = ID; - if (II->hasMacroDefinition()) - DeserializedMacroNames.push_back(II); +} + +void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { + MacroIDs[MI] = ID; } void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { @@ -4468,15 +4704,15 @@ void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinitions[MD] = ID; } -void ASTWriter::MacroVisible(IdentifierInfo *II) { - DeserializedMacroNames.push_back(II); -} - void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end()); SubmoduleIDs[Mod] = ID; } +void ASTWriter::UndefinedMacro(MacroInfo *MI) { + MacroUpdates[MI].UndefLoc = MI->getUndefLoc(); +} + void ASTWriter::CompletedTagDefinition(const TagDecl *D) { assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); @@ -4490,6 +4726,7 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { } } } + void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { assert(!WritingAST && "Already writing the AST!"); |