diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/GeneratePCH.cpp | 22 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 59 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 129 |
3 files changed, 156 insertions, 54 deletions
diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp index 8be88ce381..3b7715ad28 100644 --- a/lib/Frontend/GeneratePCH.cpp +++ b/lib/Frontend/GeneratePCH.cpp @@ -32,19 +32,24 @@ using namespace llvm; namespace { class VISIBILITY_HIDDEN PCHGenerator : public SemaConsumer { const Preprocessor &PP; + const char *isysroot; llvm::raw_ostream *Out; Sema *SemaPtr; MemorizeStatCalls *StatCalls; // owned by the FileManager - + public: - explicit PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *Out); + explicit PCHGenerator(const Preprocessor &PP, + const char *isysroot, + llvm::raw_ostream *Out); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } virtual void HandleTranslationUnit(ASTContext &Ctx); }; } -PCHGenerator::PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS) - : PP(PP), Out(OS), SemaPtr(0), StatCalls(0) { +PCHGenerator::PCHGenerator(const Preprocessor &PP, + const char *isysroot, + llvm::raw_ostream *OS) + : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0) { // Install a stat() listener to keep track of all of the stat() // calls. @@ -56,14 +61,14 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { if (PP.getDiagnostics().hasErrorOccurred()) return; - // Write the PCH contents into a buffer + // Write the PCH contents into a buffer std::vector<unsigned char> Buffer; BitstreamWriter Stream(Buffer); PCHWriter Writer(Stream); // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WritePCH(*SemaPtr, StatCalls); + Writer.WritePCH(*SemaPtr, StatCalls, isysroot); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); @@ -73,6 +78,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { } ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP, - llvm::raw_ostream *OS) { - return new PCHGenerator(PP, OS); + llvm::raw_ostream *OS, + const char *isysroot) { + return new PCHGenerator(PP, isysroot, OS); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 067cce9b30..bc0e7208d3 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -336,7 +336,8 @@ void PCHValidator::ReadCounter(unsigned Value) { // PCH reader implementation //===----------------------------------------------------------------------===// -PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context) +PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, + const char *isysroot) : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), Consumer(0), @@ -344,25 +345,31 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context) IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), Comments(0), NumComments(0), + TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot), NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { } + NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), + CurrentlyLoadingTypeOrDecl(0) { + RelocatablePCH = false; +} PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags) + Diagnostic &Diags, const char *isysroot) : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0), + TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot), + NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), - CurrentlyLoadingTypeOrDecl(0) { } + CurrentlyLoadingTypeOrDecl(0) { + RelocatablePCH = false; +} PCHReader::~PCHReader() {} @@ -652,8 +659,7 @@ bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, /// \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) { +bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) { unsigned Idx = 0; LineTableInfo &LineTable = SourceMgr.getLineTable(); @@ -664,6 +670,7 @@ static bool ParseLineTable(SourceManager &SourceMgr, unsigned FilenameLen = Record[Idx++]; std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen); Idx += FilenameLen; + MaybeAddSystemRootToFilename(Filename); FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(), Filename.size()); } @@ -859,7 +866,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { break; case pch::SM_LINE_TABLE: - if (ParseLineTable(SourceMgr, Record)) + if (ParseLineTable(Record)) return Failure; break; @@ -912,10 +919,12 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { return Failure; case pch::SM_SLOC_FILE_ENTRY: { - const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen); + std::string Filename(BlobStart, BlobStart + BlobLen); + MaybeAddSystemRootToFilename(Filename); + const FileEntry *File = FileMgr.getFile(Filename); if (File == 0) { std::string ErrorStr = "could not find file '"; - ErrorStr.append(BlobStart, BlobLen); + ErrorStr += Filename; ErrorStr += "' referenced by PCH file"; Error(ErrorStr.c_str()); return Failure; @@ -1096,6 +1105,32 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { } } +/// \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 PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) { + // If this is not a relocatable PCH file, there's nothing to do. + if (!RelocatablePCH) + return; + + if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<') + return; + + std::string FIXME = Filename; + + if (isysroot == 0) { + // If no system root was given, default to '/' + Filename.insert(Filename.begin(), '/'); + return; + } + + unsigned Length = strlen(isysroot); + if (isysroot[Length - 1] != '/') + Filename.insert(Filename.begin(), '/'); + + Filename.insert(Filename.begin(), isysroot, isysroot + Length); +} + PCHReader::PCHReadResult PCHReader::ReadPCHBlock() { if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { @@ -1208,6 +1243,7 @@ PCHReader::ReadPCHBlock() { return IgnorePCH; } + RelocatablePCH = Record[4]; if (Listener) { std::string TargetTriple(BlobStart, BlobLen); if (Listener->ReadTargetTriple(TargetTriple)) @@ -1338,6 +1374,7 @@ PCHReader::ReadPCHBlock() { case pch::ORIGINAL_FILE_NAME: OriginalFileName.assign(BlobStart, BlobLen); + MaybeAddSystemRootToFilename(OriginalFileName); break; case pch::COMMENT_RANGES: diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index fee2137314..566df350f6 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -476,11 +476,68 @@ void PCHWriter::WriteBlockInfoBlock() { Stream.ExitBlock(); } +/// \brief Adjusts the given filename to only write out the portion of the +/// filename that is not part of the system root directory. +/// +/// \param Filename the file name to adjust. +/// +/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and +/// the returned filename will be adjusted by this system root. +/// +/// \returns either the original filename (if it needs no adjustment) or the +/// adjusted filename (which points into the @p Filename parameter). +static const char * +adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { + assert(Filename && "No file name to adjust?"); + + if (!isysroot) + return Filename; + + // Verify that the filename and the system root have the same prefix. + unsigned Pos = 0; + for (; Filename[Pos] && isysroot[Pos]; ++Pos) + if (Filename[Pos] != isysroot[Pos]) + return Filename; // Prefixes don't match. + + // We hit the end of the filename before we hit the end of the system root. + if (!Filename[Pos]) + return Filename; + + // If the file name has a '/' at the current position, skip over the '/'. + // We distinguish sysroot-based includes from absolute includes by the + // absence of '/' at the beginning of sysroot-based includes. + if (Filename[Pos] == '/') + ++Pos; + + return Filename + Pos; +} /// \brief Write the PCH metadata (e.g., i686-apple-darwin9). -void PCHWriter::WriteMetadata(ASTContext &Context) { +void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) { using namespace llvm; + // 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::Fixed, 1)); // Relocatable + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple + unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); + + RecordData Record; + Record.push_back(pch::METADATA); + Record.push_back(pch::VERSION_MAJOR); + Record.push_back(pch::VERSION_MINOR); + Record.push_back(CLANG_VERSION_MAJOR); + Record.push_back(CLANG_VERSION_MINOR); + Record.push_back(isysroot != 0); + const char *Triple = Target.getTargetTriple(); + Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple)); + // Original file name SourceManager &SM = Context.getSourceManager(); if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { @@ -500,31 +557,14 @@ void PCHWriter::WriteMetadata(ASTContext &Context) { MainFileName = MainFilePath.toString(); } + const char *MainFileNameStr = MainFileName.c_str(); + MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, + isysroot); RecordData Record; Record.push_back(pch::ORIGINAL_FILE_NAME); - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileName.c_str(), - MainFileName.size()); + Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr, + strlen(MainFileNameStr)); } - - // 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); - Record.push_back(pch::VERSION_MAJOR); - Record.push_back(pch::VERSION_MINOR); - Record.push_back(CLANG_VERSION_MAJOR); - Record.push_back(CLANG_VERSION_MINOR); - const char *Triple = Target.getTargetTriple(); - Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple)); } /// \brief Write the LangOptions structure. @@ -649,15 +689,19 @@ public: } // end anonymous namespace /// \brief Write the stat() system call cache to the PCH file. -void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { +void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls, + const char *isysroot) { // Build the on-disk hash table containing information about every // stat() call. OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator; unsigned NumStatEntries = 0; for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), StatEnd = StatCalls.end(); - Stat != StatEnd; ++Stat, ++NumStatEntries) - Generator.insert(Stat->first(), Stat->second); + Stat != StatEnd; ++Stat, ++NumStatEntries) { + const char *Filename = Stat->first(); + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); + Generator.insert(Filename, Stat->second); + } // Create the on-disk hash table in a buffer. llvm::SmallVector<char, 4096> StatCacheData; @@ -753,7 +797,8 @@ static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) { /// errors), we probably won't have to create file entries for any of /// the files in the AST. void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP) { + const Preprocessor &PP, + const char *isysroot) { RecordData Record; // Enter the source manager block. @@ -774,6 +819,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { // Emit the file name const char *Filename = LineTable.getFilename(I); + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); unsigned FilenameLen = Filename? strlen(Filename) : 0; Record.push_back(FilenameLen); if (FilenameLen) @@ -850,9 +896,21 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (Content->Entry) { // The source location entry is a file. The blob associated // with this entry is the file name. - Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, - Content->Entry->getName(), - strlen(Content->Entry->getName())); + + // Turn the file name into an absolute path, if it isn't already. + const char *Filename = Content->Entry->getName(); + llvm::sys::Path FilePath(Filename, strlen(Filename)); + std::string FilenameStr; + if (!FilePath.isAbsolute()) { + llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); + P.appendComponent(FilePath.toString()); + FilenameStr = P.toString(); + Filename = FilenameStr.c_str(); + } + + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); + Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename, + strlen(Filename)); // FIXME: For now, preload all file source locations, so that // we get the appropriate File entries in the reader. This is @@ -1716,7 +1774,8 @@ PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) { } -void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { +void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, + const char *isysroot) { using namespace llvm; ASTContext &Context = SemaRef.Context; @@ -1778,11 +1837,11 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { // Write the remaining PCH contents. RecordData Record; Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4); - WriteMetadata(Context); + WriteMetadata(Context, isysroot); WriteLanguageOptions(Context.getLangOptions()); - if (StatCalls) - WriteStatCache(*StatCalls); - WriteSourceManagerBlock(Context.getSourceManager(), PP); + if (StatCalls && !isysroot) + WriteStatCache(*StatCalls, isysroot); + WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); WritePreprocessor(PP); WriteComments(Context); |