diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 85 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 51 |
2 files changed, 125 insertions, 11 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 759865c7eb..ab7ad04e9d 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1218,6 +1218,10 @@ PCHReader::ReadPCHBlock() { } ObjCCategoryImpls.swap(Record); break; + + case pch::ORIGINAL_FILE_NAME: + OriginalFileName.assign(BlobStart, BlobLen); + break; } } Error("premature end of bitstream in PCH file"); @@ -1364,6 +1368,87 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { return Success; } +/// \brief Retrieve the name of the original source file name +/// directly from the PCH file, without actually loading the PCH +/// file. +std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { + // Open the PCH file. + std::string ErrStr; + llvm::OwningPtr<llvm::MemoryBuffer> Buffer; + Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr)); + if (!Buffer) { + fprintf(stderr, "error: %s\n", ErrStr.c_str()); + return std::string(); + } + + // Initialize the stream + llvm::BitstreamReader StreamFile; + llvm::BitstreamCursor Stream; + StreamFile.init((const unsigned char *)Buffer->getBufferStart(), + (const unsigned char *)Buffer->getBufferEnd()); + Stream.init(StreamFile); + + // Sniff for the signature. + if (Stream.Read(8) != 'C' || + Stream.Read(8) != 'P' || + Stream.Read(8) != 'C' || + Stream.Read(8) != 'H') { + fprintf(stderr, + "error: '%s' does not appear to be a precompiled header file\n", + PCHFileName.c_str()); + return std::string(); + } + + RecordData Record; + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + + if (Code == llvm::bitc::ENTER_SUBBLOCK) { + unsigned BlockID = Stream.ReadSubBlockID(); + + // We only know the PCH subblock ID. + switch (BlockID) { + case pch::PCH_BLOCK_ID: + if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { + fprintf(stderr, "error: malformed block record in PCH file\n"); + return std::string(); + } + break; + + default: + if (Stream.SkipBlock()) { + fprintf(stderr, "error: malformed block record in PCH file\n"); + return std::string(); + } + break; + } + continue; + } + + if (Code == llvm::bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) { + fprintf(stderr, "error: error at end of module block in PCH file\n"); + return std::string(); + } + continue; + } + + if (Code == llvm::bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + Record.clear(); + const char *BlobStart = 0; + unsigned BlobLen = 0; + if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) + == pch::ORIGINAL_FILE_NAME) + return std::string(BlobStart, BlobLen); + } + + return std::string(); +} + /// \brief Parse the record that corresponds to a LangOptions data /// structure. /// diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index fc6aa4709e..dbe0e536e5 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -33,6 +33,7 @@ #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/System/Path.h" #include <cstdio> using namespace clang; @@ -442,16 +443,44 @@ void PCHWriter::WriteBlockInfoBlock() { /// \brief Write the PCH metadata (e.g., i686-apple-darwin9). -void PCHWriter::WriteMetadata(const TargetInfo &Target) { +void PCHWriter::WriteMetadata(ASTContext &Context) { using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::METADATA)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple - unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); + + // Original file name + SourceManager &SM = Context.getSourceManager(); + if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { + BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); + FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME)); + FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name + unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); + + llvm::sys::Path MainFilePath(MainFile->getName()); + std::string MainFileName; + + if (!MainFilePath.isAbsolute()) { + llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); + P.appendComponent(MainFilePath.toString()); + MainFileName = P.toString(); + } else { + MainFileName = MainFilePath.toString(); + } + + RecordData Record; + Record.push_back(pch::ORIGINAL_FILE_NAME); + Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileName.c_str(), + MainFileName.size()); + } + + // Metadata + const TargetInfo &Target = Context.Target; + BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); + MetaAbbrev->Add(BitCodeAbbrevOp(pch::METADATA)); + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple + unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); RecordData Record; Record.push_back(pch::METADATA); @@ -460,7 +489,7 @@ void PCHWriter::WriteMetadata(const TargetInfo &Target) { Record.push_back(CLANG_VERSION_MAJOR); Record.push_back(CLANG_VERSION_MINOR); const char *Triple = Target.getTargetTriple(); - Stream.EmitRecordWithBlob(AbbrevCode, Record, Triple, strlen(Triple)); + Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple)); } /// \brief Write the LangOptions structure. @@ -1672,7 +1701,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { // Write the remaining PCH contents. RecordData Record; Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4); - WriteMetadata(Context.Target); + WriteMetadata(Context); WriteLanguageOptions(Context.getLangOptions()); if (StatCalls) WriteStatCache(*StatCalls); |