diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 319 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 56 |
2 files changed, 174 insertions, 201 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index a0bfa10b85..4d23ee5890 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1112,55 +1112,16 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { return Failure; case SM_SLOC_FILE_ENTRY: { - if (Record.size() < 7) { - Error("source location entry is incorrect"); - return Failure; - } - // We will detect whether a file changed and return 'Failure' for it, but // we will also try to fail gracefully by setting up the SLocEntry. - ASTReader::ASTReadResult Result = Success; - - bool OverriddenBuffer = Record[6]; - - std::string OrigFilename(BlobStart, BlobStart + BlobLen); - std::string Filename = OrigFilename; - MaybeAddSystemRootToFilename(*F, Filename); - const FileEntry *File = - OverriddenBuffer? FileMgr.getVirtualFile(Filename, (off_t)Record[4], - (time_t)Record[5]) - : FileMgr.getFile(Filename, /*OpenFile=*/false); - if (File == 0 && !F->OriginalDir.empty() && !CurrentDir.empty() && - F->OriginalDir != CurrentDir) { - std::string resolved = resolveFileRelativeToOriginalDir(Filename, - F->OriginalDir, - CurrentDir); - if (!resolved.empty()) - File = FileMgr.getFile(resolved); - } - if (File == 0) - File = FileMgr.getVirtualFile(Filename, (off_t)Record[4], - (time_t)Record[5]); - if (File == 0) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by AST file"; - Error(ErrorStr.c_str()); - return Failure; - } + ASTReader::ASTReadResult Result = Success; + unsigned InputID = Record[4]; + InputFile IF = getInputFile(*F, InputID); + const FileEntry *File = IF.getPointer(); + bool OverriddenBuffer = IF.getInt(); - if (!DisableValidation && !OverriddenBuffer && - ((off_t)Record[4] != File->getSize() -#if !defined(LLVM_ON_WIN32) - // In our regression testing, the Windows file system seems to - // have inconsistent modification times that sometimes - // erroneously trigger this error-handling path. - || (time_t)Record[5] != File->getModificationTime() -#endif - )) { - Error(diag::err_fe_pch_file_modified, Filename); - Result = Failure; - } + if (!IF.getPointer()) + return IgnorePCH; SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) { @@ -1173,12 +1134,12 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { ID, BaseOffset + Record[0]); SrcMgr::FileInfo &FileInfo = const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); - FileInfo.NumCreatedFIDs = Record[7]; + FileInfo.NumCreatedFIDs = Record[5]; if (Record[3]) FileInfo.setHasLineDirectives(); - const DeclID *FirstDecl = F->FileSortedDecls + Record[8]; - unsigned NumFileDecls = Record[9]; + const DeclID *FirstDecl = F->FileSortedDecls + Record[6]; + unsigned NumFileDecls = Record[7]; if (NumFileDecls) { assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?"); FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl, @@ -1202,7 +1163,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), - Filename); + File->getName()); SourceMgr.overrideFileContents(File, Buffer); } @@ -1707,6 +1668,118 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) { IdentifierGeneration[II] = CurrentGeneration; } +llvm::PointerIntPair<const FileEntry *, 1, bool> +ASTReader::getInputFile(ModuleFile &F, unsigned ID) { + // If this ID is bogus, just return an empty input file. + if (ID == 0 || ID > F.InputFilesLoaded.size()) + return InputFile(); + + // If we've already loaded this input file, return it. + if (F.InputFilesLoaded[ID-1].getPointer()) + return F.InputFilesLoaded[ID-1]; + + // Go find this input file. + llvm::BitstreamCursor &Cursor = F.InputFilesCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(F.InputFileOffsets[ID-1]); + + unsigned Code = Cursor.ReadCode(); + RecordData Record; + const char *BlobStart = 0; + unsigned BlobLen = 0; + switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record, + &BlobStart, &BlobLen)) { + case INPUT_FILE: { + unsigned StoredID = Record[0]; + assert(ID == StoredID && "Bogus stored ID or offset"); + off_t StoredSize = (off_t)Record[1]; + time_t StoredTime = (time_t)Record[2]; + bool Overridden = (bool)Record[3]; + + // Get the file entry for this input file. + StringRef OrigFilename(BlobStart, BlobLen); + std::string Filename = OrigFilename; + MaybeAddSystemRootToFilename(F, Filename); + const FileEntry *File + = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime) + : FileMgr.getFile(Filename, /*OpenFile=*/false); + + // If we didn't find the file, resolve it relative to the + // original directory from which this AST file was created. + if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() && + F.OriginalDir != CurrentDir) { + std::string Resolved = resolveFileRelativeToOriginalDir(Filename, + F.OriginalDir, + CurrentDir); + if (!Resolved.empty()) + File = FileMgr.getFile(Resolved); + } + + // For an overridden file, create a virtual file with the stored + // size/timestamp. + if (Overridden && File == 0) { + File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); + } + + if (File == 0) { + std::string ErrorStr = "could not find file '"; + ErrorStr += Filename; + ErrorStr += "' referenced by AST file"; + Error(ErrorStr.c_str()); + return InputFile(); + } + + // Note that we've loaded this input file. + F.InputFilesLoaded[ID-1] = InputFile(File, Overridden); + + // Check if there was a request to override the contents of the file + // that was part of the precompiled header. Overridding such a file + // can lead to problems when lexing using the source locations from the + // PCH. + SourceManager &SM = getSourceManager(); + if (!Overridden && SM.isFileOverridden(File)) { + Error(diag::err_fe_pch_file_overridden, Filename); + // After emitting the diagnostic, recover by disabling the override so + // that the original file will be used. + SM.disableFileContentsOverride(File); + // The FileEntry is a virtual file entry with the size of the contents + // that would override the original contents. Set it to the original's + // size/time. + FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), + StoredSize, StoredTime); + } + + // For an overridden file, there is nothing to validate. + if (Overridden) + return InputFile(File, Overridden); + + // The stat info from the FileEntry came from the cached stat + // info of the PCH, so we cannot trust it. + struct stat StatBuf; + if (::stat(File->getName(), &StatBuf) != 0) { + StatBuf.st_size = File->getSize(); + StatBuf.st_mtime = File->getModificationTime(); + } + + if ((StoredSize != StatBuf.st_size +#if !defined(LLVM_ON_WIN32) + // In our regression testing, the Windows file system seems to + // have inconsistent modification times that sometimes + // erroneously trigger this error-handling path. + || StoredTime != StatBuf.st_mtime +#endif + )) { + Error(diag::err_fe_pch_file_modified, Filename); + return InputFile(); + } + + return InputFile(File, Overridden); + } + } + + return InputFile(); +} + const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { ModuleFile &M = ModuleMgr.getPrimaryModule(); std::string Filename = filenameStrRef; @@ -1727,19 +1800,19 @@ const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { /// \brief If we are loading a relocatable PCH file, and the filename is /// not an absolute path, add the system root to the beginning of the file /// name. -void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, - std::string &Filename) { +StringRef ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, + std::string &Filename) { // If this is not a relocatable PCH file, there's nothing to do. if (!M.RelocatablePCH) - return; + return Filename; if (Filename.empty() || llvm::sys::path::is_absolute(Filename)) - return; + return Filename; if (isysroot.empty()) { // If no system root was given, default to '/' Filename.insert(Filename.begin(), '/'); - return; + return Filename; } unsigned Length = isysroot.size(); @@ -1747,6 +1820,7 @@ void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M, Filename.insert(Filename.begin(), '/'); Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end()); + return Filename; } ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, @@ -1768,24 +1842,25 @@ ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, return Failure; } + // Validate all of the input files. + if (!DisableValidation) { + for (unsigned I = 0, N = Record[0]; I < N; ++I) + if (!getInputFile(F, I+1).getPointer()) + return IgnorePCH; + } + return Success; } if (Code == llvm::bitc::ENTER_SUBBLOCK) { switch (Stream.ReadSubBlockID()) { case INPUT_FILES_BLOCK_ID: - switch (ReadInputFilesBlock(F)) { - case Success: - break; - - case Failure: + F.InputFilesCursor = Stream; + if (Stream.SkipBlock() || // Skip with the main cursor + // Read the abbreviations + ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) { + Error("malformed block record in AST file"); return Failure; - - case IgnorePCH: - // FIXME: We could consider reading through to the end of this - // AST block, skipping subblocks, to see if there are other - // AST blocks elsewhere. - return IgnorePCH; } continue; @@ -1894,118 +1969,12 @@ ASTReader::ASTReadResult ASTReader::ReadControlBlock(ModuleFile &F, case ORIGINAL_PCH_DIR: F.OriginalDir.assign(BlobStart, BlobLen); break; - } - } - - Error("premature end of bitstream in AST file"); - return Failure; -} - -ASTReader::ASTReadResult ASTReader::ReadInputFilesBlock(ModuleFile &F) { - llvm::BitstreamCursor &Stream = F.Stream; - - // If we're not doing any validation, there's no reason to read this - // input-files block. - if (DisableValidation) { - return Stream.SkipBlock()? Failure : Success; - } - - if (Stream.EnterSubBlock(INPUT_FILES_BLOCK_ID)) { - Error("malformed block record in AST file"); - return Failure; - } - - // Read all of the records and blocks for the AST file. - RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Error("error at end of module block in AST file"); - return Failure; - } - - DeclContext *DC = Context.getTranslationUnitDecl(); - if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage()) - DC->setMustBuildLookupTable(); - - 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 ((InputFileRecordTypes)Stream.ReadRecord(Code, Record, - &BlobStart, &BlobLen)) { - case INPUT_FILE: { - // Check that the file exists. - StringRef Filename(BlobStart, BlobLen); - const FileEntry *File = getFileEntry(Filename); - if (File == 0) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by AST file"; - Error(ErrorStr.c_str()); - return IgnorePCH; - } - - off_t StoredSize = (off_t)Record[0]; - time_t StoredTime = (time_t)Record[1]; - - // Check if there was a request to override the contents of the file - // that was part of the precompiled header. Overridding such a file - // can lead to problems when lexing using the source locations from the - // PCH. - SourceManager &SM = getSourceManager(); - if (SM.isFileOverridden(File)) { - Error(diag::err_fe_pch_file_overridden, Filename); - // After emitting the diagnostic, recover by disabling the override so - // that the original file will be used. - SM.disableFileContentsOverride(File); - // The FileEntry is a virtual file entry with the size of the contents - // that would override the original contents. Set it to the original's - // size/time. - FileMgr.modifyFileEntry(const_cast<FileEntry*>(File), - StoredSize, StoredTime); - } - - // The stat info from the FileEntry came from the cached stat - // info of the PCH, so we cannot trust it. - struct stat StatBuf; - if (::stat(File->getName(), &StatBuf) != 0) { - StatBuf.st_size = File->getSize(); - StatBuf.st_mtime = File->getModificationTime(); - } - - if ((StoredSize != StatBuf.st_size -#if !defined(LLVM_ON_WIN32) - // In our regression testing, the Windows file system seems to - // have inconsistent modification times that sometimes - // erroneously trigger this error-handling path. - || StoredTime != StatBuf.st_mtime -#endif - )) { - Error(diag::err_fe_pch_file_modified, Filename); - return IgnorePCH; - } + case INPUT_FILE_OFFSETS: + F.InputFileOffsets = (const uint32_t *)BlobStart; + F.InputFilesLoaded.resize(Record[0]); break; } - } } Error("premature end of bitstream in AST file"); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 77b8cf93ec..801615280f 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -775,6 +775,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TARGET_OPTIONS); RECORD(ORIGINAL_FILE); RECORD(ORIGINAL_PCH_DIR); + RECORD(INPUT_FILE_OFFSETS); BLOCK(INPUT_FILES_BLOCK); RECORD(INPUT_FILE); @@ -1119,8 +1120,10 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { // 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); @@ -1135,16 +1138,24 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { if (!SLoc->isFile()) continue; const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); - if (!Cache->OrigEntry || Cache->BufferOverridden) + 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); @@ -1164,6 +1175,19 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { } 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)); } //===----------------------------------------------------------------------===// @@ -1269,13 +1293,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); } @@ -1538,13 +1559,10 @@ 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(FID); @@ -1556,21 +1574,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(); |