diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 58 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 40 |
2 files changed, 93 insertions, 5 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index fa6ad6f0a0..4998de371f 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -18,6 +18,7 @@ #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Bitcode/BitstreamReader.h" @@ -191,6 +192,50 @@ bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, return true; } +/// \brief Read the line table in the source manager block. +/// \returns true if ther was an error. +static bool ParseLineTable(SourceManager &SourceMgr, + llvm::SmallVectorImpl<uint64_t> &Record) { + unsigned Idx = 0; + LineTableInfo &LineTable = SourceMgr.getLineTable(); + + // Parse the file names + for (unsigned I = 0, N = Record[Idx++]; I != N; ++I) { + // Extract the file name + unsigned FilenameLen = Record[Idx++]; + std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen); + Idx += FilenameLen; + unsigned ID = LineTable.getLineTableFilenameID(Filename.c_str(), + Filename.size()); + if (ID != I) + return Error("Filename ID mismatch in PCH line table"); + } + + // Parse the line entries + std::vector<LineEntry> Entries; + while (Idx < Record.size()) { + unsigned FID = Record[Idx++]; + + // Extract the line entries + unsigned NumEntries = Record[Idx++]; + Entries.clear(); + Entries.reserve(NumEntries); + for (unsigned I = 0; I != NumEntries; ++I) { + unsigned FileOffset = Record[Idx++]; + unsigned LineNo = Record[Idx++]; + int FilenameID = Record[Idx++]; + SrcMgr::CharacteristicKind FileKind + = (SrcMgr::CharacteristicKind)Record[Idx++]; + unsigned IncludeOffset = Record[Idx++]; + Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID, + FileKind, IncludeOffset)); + } + LineTable.AddEntry(FID, Entries); + } + + return false; +} + /// \brief Read the source manager block PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { using namespace SrcMgr; @@ -242,9 +287,12 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { const FileEntry *File = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen); // FIXME: Error recovery if file cannot be found. - SourceMgr.createFileID(File, - SourceLocation::getFromRawEncoding(Record[1]), - (CharacteristicKind)Record[2]); + FileID ID = SourceMgr.createFileID(File, + SourceLocation::getFromRawEncoding(Record[1]), + (CharacteristicKind)Record[2]); + if (Record[3]) + const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(ID).getFile()) + .setHasLineDirectives(); break; } @@ -278,6 +326,10 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { break; } + case pch::SM_LINE_TABLE: { + if (ParseLineTable(SourceMgr, Record)) + return Failure; + } } } } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 2cf932ce9b..6056fbc539 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -21,6 +21,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/Compiler.h" @@ -503,8 +504,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) { const SrcMgr::FileInfo &File = SLoc->getFile(); Record.push_back(File.getIncludeLoc().getRawEncoding()); Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding - Record.push_back(File.hasLineDirectives()); // FIXME: encode the - // line directives? + Record.push_back(File.hasLineDirectives()); const SrcMgr::ContentCache *Content = File.getContentCache(); if (Content->Entry) { @@ -550,6 +550,42 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) { Record.clear(); } + // Write the line table. + if (SourceMgr.hasLineTable()) { + LineTableInfo &LineTable = SourceMgr.getLineTable(); + + // Emit the file names + Record.push_back(LineTable.getNumFilenames()); + for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { + // Emit the file name + const char *Filename = LineTable.getFilename(I); + unsigned FilenameLen = Filename? strlen(Filename) : 0; + Record.push_back(FilenameLen); + if (FilenameLen) + Record.insert(Record.end(), Filename, Filename + FilenameLen); + } + + // Emit the line entries + for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); + L != LEnd; ++L) { + // Emit the file ID + Record.push_back(L->first); + + // Emit the line entries + Record.push_back(L->second.size()); + for (std::vector<LineEntry>::iterator LE = L->second.begin(), + LEEnd = L->second.end(); + LE != LEEnd; ++LE) { + Record.push_back(LE->FileOffset); + Record.push_back(LE->LineNo); + Record.push_back(LE->FilenameID); + Record.push_back((unsigned)LE->FileKind); + Record.push_back(LE->IncludeOffset); + } + S.EmitRecord(pch::SM_LINE_TABLE, Record); + } + } + S.ExitBlock(); } |