On Fri Dec 05 2014 at 3:36:24 AM Richard Smith <[email protected]> wrote:
> Author: rsmith > Date: Thu Dec 4 20:33:27 2014 > New Revision: 223443 > > URL: http://llvm.org/viewvc/llvm-project?rev=223443&view=rev > Log: > [modules] Instead of storing absolute paths in a .pcm file, store the path > to > the root of the module and use paths relative to that directory wherever > possible. This is a step towards allowing explicit modules to be relocated > without being rebuilt, which is important for some kinds of distributed > builds, > for good paths in diagnostics, and for appropriate .d output. > > Modified: > cfe/trunk/include/clang/Serialization/ASTBitCodes.h > cfe/trunk/include/clang/Serialization/ASTReader.h > cfe/trunk/include/clang/Serialization/ASTWriter.h > cfe/trunk/include/clang/Serialization/Module.h > cfe/trunk/lib/Serialization/ASTReader.cpp > cfe/trunk/lib/Serialization/ASTReaderInternals.h > cfe/trunk/lib/Serialization/ASTWriter.cpp > > Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Serialization/ASTBitCodes.h?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) > +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Dec 4 > 20:33:27 2014 > @@ -291,7 +291,10 @@ namespace clang { > MODULE_MAP_FILE = 14, > > /// \brief Record code for the signature that identifiers this AST > file. > - SIGNATURE = 15 > + SIGNATURE = 15, > + > + /// \brief Record code for the module build directory. > + MODULE_DIRECTORY = 16, > }; > > /// \brief Record types that occur within the input-files block > > Modified: cfe/trunk/include/clang/Serialization/ASTReader.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Serialization/ASTReader.h?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Serialization/ASTReader.h (original) > +++ cfe/trunk/include/clang/Serialization/ASTReader.h Thu Dec 4 20:33:27 > 2014 > @@ -1113,12 +1113,11 @@ private: > serialization::InputFile getInputFile(ModuleFile &F, unsigned ID, > bool Complain = true); > > - /// \brief Get a FileEntry out of stored-in-PCH filename, making sure > we take > - /// into account all the necessary relocations. > - const FileEntry *getFileEntry(StringRef filename); > - > - void MaybeAddSystemRootToFilename(ModuleFile &M, std::string > &Filename); > +public: > + void ResolveImportedPath(ModuleFile &M, std::string &Filename); > + static void ResolveImportedPath(std::string &Filename, StringRef > Prefix); > > +private: > struct ImportedModule { > ModuleFile *Mod; > ModuleFile *ImportedBy; > @@ -1141,7 +1140,7 @@ private: > const ModuleFile *ImportedBy, > unsigned ClientLoadCapabilities); > ASTReadResult ReadASTBlock(ModuleFile &F, unsigned > ClientLoadCapabilities); > - bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record); > + bool ParseLineTable(ModuleFile &F, const RecordData &Record); > bool ReadSourceManagerBlock(ModuleFile &F); > llvm::BitstreamCursor &SLocCursorForID(int ID); > SourceLocation getImportLocation(ModuleFile *F); > @@ -2045,6 +2044,9 @@ public: > // \brief Read a string > static std::string ReadString(const RecordData &Record, unsigned &Idx); > > + // \brief Read a path > + std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned > &Idx); > + > /// \brief Read a version tuple. > static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned > &Idx); > > > Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Serialization/ASTWriter.h?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original) > +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Thu Dec 4 20:33:27 > 2014 > @@ -111,7 +111,10 @@ private: > > /// \brief The module we're currently writing, if any. > Module *WritingModule; > - > + > + /// \brief The base directory for any relative paths we emit. > + std::string BaseDirectory; > + > /// \brief Indicates when the AST writing is actively performing > /// serialization, rather than just queueing updates. > bool WritingAST; > @@ -457,13 +460,11 @@ private: > StringRef isysroot, const std::string > &OutputFile); > void WriteInputFiles(SourceManager &SourceMgr, > HeaderSearchOptions &HSOpts, > - StringRef isysroot, > bool Modules); > void WriteSourceManagerBlock(SourceManager &SourceMgr, > - const Preprocessor &PP, > - StringRef isysroot); > + const Preprocessor &PP); > void WritePreprocessor(const Preprocessor &PP, bool IsModule); > - void WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot); > + void WriteHeaderSearch(const HeaderSearch &HS); > void WritePreprocessorDetail(PreprocessingRecord &PPRec); > void WriteSubmodules(Module *WritingModule); > > @@ -539,7 +540,8 @@ public: > /// writing a precompiled header. > /// > /// \param isysroot if non-empty, write a relocatable file whose headers > - /// are relative to the given system root. > + /// are relative to the given system root. If we're writing a module, > its > + /// build directory will be used in preference to this if both are > available. > void WriteAST(Sema &SemaRef, > const std::string &OutputFile, > Module *WritingModule, StringRef isysroot, > @@ -686,6 +688,17 @@ public: > /// \brief Add a string to the given record. > void AddString(StringRef Str, RecordDataImpl &Record); > > + /// \brief Convert a path from this build process into one that is > appropriate > + /// for emission in the module file. > + bool PreparePathForOutput(SmallVectorImpl<char> &Path); > + > + /// \brief Add a path to the given record. > + void AddPath(StringRef Path, RecordDataImpl &Record); > + > + /// \brief Emit the current record with the given path as a blob. > + void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record, > + StringRef Path); > + > /// \brief Add a version tuple to the given record > void AddVersionTuple(const VersionTuple &Version, RecordDataImpl > &Record); > > > Modified: cfe/trunk/include/clang/Serialization/Module.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Serialization/Module.h?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Serialization/Module.h (original) > +++ cfe/trunk/include/clang/Serialization/Module.h Thu Dec 4 20:33:27 > 2014 > @@ -125,6 +125,9 @@ public: > /// \brief The name of the module. > std::string ModuleName; > > + /// \brief The base directory of the module. > + std::string BaseDirectory; > + > std::string getTimestampFilename() const { > return FileName + ".timestamp"; > } > > Modified: cfe/trunk/lib/Serialization/ASTReader.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ > Serialization/ASTReader.cpp?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Dec 4 20:33:27 2014 > @@ -1029,7 +1029,7 @@ void ASTReader::Error(unsigned DiagID, > /// \brief Read the line table in the source manager block. > /// \returns true if there was an error. > bool ASTReader::ParseLineTable(ModuleFile &F, > - SmallVectorImpl<uint64_t> &Record) { > + const RecordData &Record) { > unsigned Idx = 0; > LineTableInfo &LineTable = SourceMgr.getLineTable(); > > @@ -1037,10 +1037,7 @@ bool ASTReader::ParseLineTable(ModuleFil > std::map<int, int> FileIDs; > for (int 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; > - MaybeAddSystemRootToFilename(F, Filename); > + auto Filename = ReadPath(F, Record, Idx); > FileIDs[I] = LineTable.getLineTableFilenameID(Filename); > } > > @@ -1483,11 +1480,11 @@ ASTReader::getGlobalPreprocessedEntityID > unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) { > return llvm::hash_combine(ikey.Size, ikey.ModTime); > } > - > + > HeaderFileInfoTrait::internal_key_type > HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) { > internal_key_type ikey = { FE->getSize(), FE->getModificationTime(), > - FE->getName() }; > + FE->getName(), /*Imported*/false }; > return ikey; > } > > @@ -1495,14 +1492,24 @@ bool HeaderFileInfoTrait::EqualKey(inter > if (a.Size != b.Size || a.ModTime != b.ModTime) > return false; > > - if (strcmp(a.Filename, b.Filename) == 0) > + if (llvm::sys::path::is_absolute(a.Filename) && > + strcmp(a.Filename, b.Filename) == 0) > return true; > > // Determine whether the actual files are equivalent. > FileManager &FileMgr = Reader.getFileManager(); > - const FileEntry *FEA = FileMgr.getFile(a.Filename); > - const FileEntry *FEB = FileMgr.getFile(b.Filename); > - return (FEA && FEA == FEB); > + auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* { > + if (!Key.Imported) > + return FileMgr.getFile(Key.Filename); > + > + std::string Resolved = Key.Filename; > + Reader.ResolveImportedPath(M, Resolved); > + return FileMgr.getFile(Resolved); > + }; > + > + const FileEntry *FEA = GetFile(a); > + const FileEntry *FEB = GetFile(b); > + return FEA && FEA == FEB; > } > > std::pair<unsigned, unsigned> > @@ -1520,6 +1527,7 @@ HeaderFileInfoTrait::ReadKey(const unsig > ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d)); > ikey.ModTime = time_t(endian::readNext<uint64_t, little, > unaligned>(d)); > ikey.Filename = (const char *)d; > + ikey.Imported = true; > return ikey; > } > > @@ -1559,11 +1567,13 @@ HeaderFileInfoTrait::ReadData(internal_k > FileManager &FileMgr = Reader.getFileManager(); > ModuleMap &ModMap = > Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); > - // FIXME: This is wrong. We should track the filename as written; > this > - // information should be propagated through the SUBMODULE_HEADER etc > - // records rather than from here. > + // FIXME: This information should be propagated through the > + // SUBMODULE_HEADER etc records rather than from here. > // FIXME: We don't ever mark excluded headers. > - Module::Header H = { key.Filename, FileMgr.getFile(key.Filename) }; > + std::string Filename = key.Filename; > + if (key.Imported) > + Reader.ResolveImportedPath(M, Filename); > + Module::Header H = { key.Filename, FileMgr.getFile(Filename) }; > ModMap.addHeader(Mod, H, HFI.getHeaderRole()); > } > } > @@ -2084,14 +2094,14 @@ ASTReader::readInputFileInfo(ModuleFile > off_t StoredSize; > time_t StoredTime; > bool Overridden; > - > + > assert(Record[0] == ID && "Bogus stored ID or offset"); > StoredSize = static_cast<off_t>(Record[1]); > StoredTime = static_cast<time_t>(Record[2]); > Overridden = static_cast<bool>(Record[3]); > Filename = Blob; > - MaybeAddSystemRootToFilename(F, Filename); > - > + ResolveImportedPath(F, Filename); > + > InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, > Overridden }; > return R; > } > @@ -2229,46 +2239,24 @@ InputFile ASTReader::getInputFile(Module > return IF; > } > > -const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) { > - ModuleFile &M = ModuleMgr.getPrimaryModule(); > - std::string Filename = filenameStrRef; > - MaybeAddSystemRootToFilename(M, Filename); > - const FileEntry *File = FileMgr.getFile(Filename); > - if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() && > - M.OriginalDir != CurrentDir) { > - std::string resolved = resolveFileRelativeToOriginalDir(Filename, > - M.OriginalDir, > - CurrentDir); > - if (!resolved.empty()) > - File = FileMgr.getFile(resolved); > - } > - > - return File; > +/// \brief If we are loading a relocatable PCH or module file, and the > filename > +/// is not an absolute path, add the system or module root to the > beginning of > +/// the file name. > +void ASTReader::ResolveImportedPath(ModuleFile &M, std::string > &Filename) { > + // Resolve relative to the base directory, if we have one. > + if (!M.BaseDirectory.empty()) > + return ResolveImportedPath(Filename, M.BaseDirectory); > } > > -/// \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) { > - // If this is not a relocatable PCH file, there's nothing to do. > - if (!M.RelocatablePCH) > - return; > - > +void ASTReader::ResolveImportedPath(std::string &Filename, StringRef > Prefix) { > if (Filename.empty() || llvm::sys::path::is_absolute(Filename)) > return; > > - if (isysroot.empty()) { > - // If no system root was given, default to '/' > - Filename.insert(Filename.begin(), '/'); > - return; > - } > - > - unsigned Length = isysroot.size(); > - if (isysroot[Length - 1] != '/') > + unsigned Length = Prefix.size(); > + if (Prefix[Length - 1] != '/') > Filename.insert(Filename.begin(), '/'); > > - Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end()); > + Filename.insert(Filename.begin(), Prefix.begin(), Prefix.end()); Isn't that basically llvm::sys::path::append? > } > > ASTReader::ASTReadResult > @@ -2388,6 +2376,9 @@ ASTReader::ReadControlBlock(ModuleFile & > } > > F.RelocatablePCH = Record[4]; > + // Relative paths in a relocatable PCH are relative to our sysroot. > + if (F.RelocatablePCH) > + F.BaseDirectory = isysroot.empty() ? "/" : isysroot; > > const std::string &CurBranch = getClangFullRepositoryVersion(); > StringRef ASTBranch = Blob; > @@ -2418,10 +2409,7 @@ ASTReader::ReadControlBlock(ModuleFile & > off_t StoredSize = (off_t)Record[Idx++]; > time_t StoredModTime = (time_t)Record[Idx++]; > ASTFileSignature StoredSignature = Record[Idx++]; > - unsigned Length = Record[Idx++]; > - SmallString<128> ImportedFile(Record.begin() + Idx, > - Record.begin() + Idx + Length); > - Idx += Length; > + auto ImportedFile = ReadPath(F, Record, Idx); > > // Load the AST file. > switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, > Loaded, > @@ -2505,7 +2493,7 @@ ASTReader::ReadControlBlock(ModuleFile & > F.OriginalSourceFileID = FileID::get(Record[0]); > F.ActualOriginalSourceFileName = Blob; > F.OriginalSourceFileName = F.ActualOriginalSourceFileName; > - MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName); > + ResolveImportedPath(F, F.OriginalSourceFileName); > break; > > case ORIGINAL_FILE_ID: > @@ -2522,6 +2510,10 @@ ASTReader::ReadControlBlock(ModuleFile & > Listener->ReadModuleName(F.ModuleName); > break; > > + case MODULE_DIRECTORY: > + F.BaseDirectory = Blob; > + break; > + > case MODULE_MAP_FILE: > if (ASTReadResult Result = > ReadModuleMapFileBlock(Record, F, ImportedBy, > ClientLoadCapabilities)) > @@ -3342,7 +3334,7 @@ ASTReader::ReadModuleMapFileBlock(Record > const ModuleFile *ImportedBy, > unsigned ClientLoadCapabilities) { > unsigned Idx = 0; > - F.ModuleMapPath = ReadString(Record, Idx); > + F.ModuleMapPath = ReadPath(F, Record, Idx); > > if (F.Kind == MK_ExplicitModule) { > // For an explicitly-loaded module, we don't care whether the original > @@ -3389,7 +3381,7 @@ ASTReader::ReadModuleMapFileBlock(Record > llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps; > for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) { > // FIXME: we should use input files rather than storing names. > - std::string Filename = ReadString(Record, Idx); > + std::string Filename = ReadPath(F, Record, Idx); > const FileEntry *F = > FileMgr.getFile(Filename, false, false); > if (F == nullptr) { > @@ -4256,6 +4248,7 @@ bool ASTReader::readASTFileControlBlock( > > // Scan for ORIGINAL_FILE inside the control block. > RecordData Record; > + std::string ModuleDir; > while (1) { > llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); > if (Entry.Kind == llvm::BitstreamEntry::EndBlock) > @@ -4280,9 +4273,14 @@ bool ASTReader::readASTFileControlBlock( > case MODULE_NAME: > Listener.ReadModuleName(Blob); > break; > + case MODULE_DIRECTORY: > + ModuleDir = Blob; > + break; > case MODULE_MAP_FILE: { > unsigned Idx = 0; > - Listener.ReadModuleMapFile(ReadString(Record, Idx)); > + auto Path = ReadString(Record, Idx); > + ResolveImportedPath(Path, ModuleDir); > + Listener.ReadModuleMapFile(Path); > break; > } > case LANGUAGE_OPTIONS: > @@ -4344,7 +4342,10 @@ bool ASTReader::readASTFileControlBlock( > switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, > &Blob)) { > case INPUT_FILE: > bool Overridden = static_cast<bool>(Record[3]); > - shouldContinue = Listener.visitInputFile(Blob, isSystemFile, > Overridden); > + std::string Filename = Blob; > + ResolveImportedPath(Filename, ModuleDir); > + shouldContinue = > + Listener.visitInputFile(Filename, isSystemFile, > Overridden); > break; > } > if (!shouldContinue) > @@ -4361,11 +4362,9 @@ bool ASTReader::readASTFileControlBlock( > while (Idx < N) { > // Read information about the AST file. > Idx += 5; // ImportLoc, Size, ModTime, Signature > - unsigned Length = Record[Idx++]; > - SmallString<128> ImportedFile(Record.begin() + Idx, > - Record.begin() + Idx + Length); > - Idx += Length; > - Listener.visitImport(ImportedFile); > + std::string Filename = ReadString(Record, Idx); > + ResolveImportedPath(Filename, ModuleDir); > + Listener.visitImport(Filename); > } > break; > } > @@ -8050,6 +8049,13 @@ std::string ASTReader::ReadString(const > return Result; > } > > +std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record, > + unsigned &Idx) { > + std::string Filename = ReadString(Record, Idx); > + ResolveImportedPath(F, Filename); > + return Filename; > +} > + > VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, > unsigned &Idx) { > unsigned Major = Record[Idx++]; > > Modified: cfe/trunk/lib/Serialization/ASTReaderInternals.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ > ASTReaderInternals.h?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Serialization/ASTReaderInternals.h (original) > +++ cfe/trunk/lib/Serialization/ASTReaderInternals.h Thu Dec 4 20:33:27 > 2014 > @@ -194,8 +194,8 @@ typedef llvm::OnDiskChainedHashTable<AST > /// > /// The on-disk hash table contains a mapping from each header path to > /// information about that header (how many times it has been included, > its > -/// controlling macro, etc.). Note that we actually hash based on the > -/// filename, and support "deep" comparisons of file names based on > current > +/// controlling macro, etc.). Note that we actually hash based on the size > +/// and mtime, and support "deep" comparisons of file names based on > current > /// inode numbers, so that the search can cope with non-normalized path > names > /// and symlinks. > class HeaderFileInfoTrait { > @@ -211,6 +211,7 @@ public: > off_t Size; > time_t ModTime; > const char *Filename; > + bool Imported; > }; > typedef const internal_key_type &internal_key_ref; > > > Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ > Serialization/ASTWriter.cpp?rev=223443&r1=223442&r2=223443&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Dec 4 20:33:27 2014 > @@ -1063,33 +1063,44 @@ void ASTWriter::WriteBlockInfoBlock() { > /// > /// \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. > +/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file > and > +/// the returned filename will be adjusted by this root directory. > /// > /// \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, StringRef > isysroot) { > +adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) > { > assert(Filename && "No file name to adjust?"); > > - if (isysroot.empty()) > + if (BaseDir.empty()) > return Filename; > > // Verify that the filename and the system root have the same prefix. > unsigned Pos = 0; > - for (; Filename[Pos] && Pos < isysroot.size(); ++Pos) > - if (Filename[Pos] != isysroot[Pos]) > + for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos) > + if (Filename[Pos] != BaseDir[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] == '/') > + // If there's not a path separator at the end of the base directory nor > + // immediately after it, then this isn't within the base directory. > + if (!llvm::sys::path::is_separator(Filename[Pos])) { > + if (!llvm::sys::path::is_separator(BaseDir.back())) > + return Filename; > + } else { > + // If the file name has a '/' at the current position, skip over the > '/'. > + // We distinguish relative paths from absolute paths by the > + // absence of '/' at the beginning of relative paths. > + // > + // FIXME: This is wrong. We distinguish them by asking if the path is > + // absolute, which isn't the same thing. And there might be multiple > '/'s > + // in a row. Use a better mechanism to indicate whether we have > emitted an > + // absolute or relative path. > ++Pos; > + } > > return Filename + Pos; > } > @@ -1126,6 +1137,8 @@ void ASTWriter::WriteControlBlock(Prepro > Record.push_back(VERSION_MINOR); > Record.push_back(CLANG_VERSION_MAJOR); > Record.push_back(CLANG_VERSION_MINOR); > + assert((!WritingModule || isysroot.empty()) && > + "writing module as a relocatable PCH?"); > Record.push_back(!isysroot.empty()); > Record.push_back(ASTHasCompilerErrors); > Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, > @@ -1136,8 +1149,8 @@ void ASTWriter::WriteControlBlock(Prepro > Record.push_back(getSignature()); > Stream.EmitRecord(SIGNATURE, Record); > > - // Module name > if (WritingModule) { > + // Module name > BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); > Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); > Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name > @@ -1147,25 +1160,42 @@ void ASTWriter::WriteControlBlock(Prepro > Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name); > } > > + if (WritingModule && WritingModule->Directory) { > + // Module directory. > + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); > + Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); > + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory > + unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); > + RecordData Record; > + Record.push_back(MODULE_DIRECTORY); > + > + SmallString<128> BaseDir(WritingModule->Directory->getName()); > + Context.getSourceManager().getFileManager(). > FixupRelativePath(BaseDir); > + llvm::sys::fs::make_absolute(BaseDir); > + Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir); > + > + // Write out all other paths relative to the base directory if > possible. > + BaseDirectory.assign(BaseDir.begin(), BaseDir.end()); > + } else if (!isysroot.empty()) { > + // Write out paths relative to the sysroot if possible. > + BaseDirectory = isysroot; > + } > + > // Module map file > if (WritingModule) { > Record.clear(); > - auto addModMap = [&](const FileEntry *F) { > - SmallString<128> ModuleMap(F->getName()); > - llvm::sys::fs::make_absolute(ModuleMap); > - AddString(ModuleMap.str(), Record); > - }; > > auto &Map = PP.getHeaderSearchInfo().getModuleMap(); > > // Primary module map file. > - addModMap(Map.getModuleMapFileForUniquing(WritingModule)); > + AddPath(Map.getModuleMapFileForUniquing(WritingModule)->getName(), > Record); > > // Additional module map files. > - if (auto *AdditionalModMaps = > Map.getAdditionalModuleMapFiles(WritingModule)) > { > + if (auto *AdditionalModMaps = > + Map.getAdditionalModuleMapFiles(WritingModule)) { > Record.push_back(AdditionalModMaps->size()); > for (const FileEntry *F : *AdditionalModMaps) > - addModMap(F); > + AddPath(F->getName(), Record); > } else { > Record.push_back(0); > } > @@ -1189,9 +1219,7 @@ void ASTWriter::WriteControlBlock(Prepro > Record.push_back((*M)->File->getSize()); > Record.push_back((*M)->File->getModificationTime()); > Record.push_back((*M)->Signature); > - const std::string &FileName = (*M)->FileName; > - Record.push_back(FileName.size()); > - Record.append(FileName.begin(), FileName.end()); > + AddPath((*M)->FileName, Record); > } > Stream.EmitRecord(IMPORTS, Record); > } > @@ -1339,17 +1367,10 @@ void ASTWriter::WriteControlBlock(Prepro > FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name > unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); > > - SmallString<128> MainFilePath(MainFile->getName()); > - > - llvm::sys::fs::make_absolute(MainFilePath); > - > - const char *MainFileNameStr = MainFilePath.c_str(); > - MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, > - isysroot); > Record.clear(); > Record.push_back(ORIGINAL_FILE); > Record.push_back(SM.getMainFileID().getOpaqueValue()); > - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); > + EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName()); > } > > Record.clear(); > @@ -1375,7 +1396,6 @@ void ASTWriter::WriteControlBlock(Prepro > > WriteInputFiles(Context.SourceMgr, > PP.getHeaderSearchInfo().getHeaderSearchOpts(), > - isysroot, > PP.getLangOpts().Modules); > Stream.ExitBlock(); > } > @@ -1391,7 +1411,6 @@ namespace { > > void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, > HeaderSearchOptions &HSOpts, > - StringRef isysroot, > bool Modules) { > using namespace llvm; > Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); > @@ -1462,23 +1481,8 @@ void ASTWriter::WriteInputFiles(SourceMa > // Whether this file was overridden. > Record.push_back(Entry.BufferOverridden); > > - // Turn the file name into an absolute path, if it isn't already. > - const char *Filename = Entry.File->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); > - } > + EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); > + } > > Stream.ExitBlock(); > > @@ -1588,6 +1592,9 @@ namespace { > // The hash is based only on size/time of the file, so that the > reader can > // match even when symlinking or excess path elements ("foo/../", > "../") > // change the form of the name. However, complete path is still the > key. > + // > + // FIXME: Using the mtime here will cause problems for explicit > module > + // imports. > return llvm::hash_combine(key.FE->getSize(), > key.FE->getModificationTime()); > } > @@ -1668,7 +1675,7 @@ namespace { > /// \brief Write the header search block for the list of files that > /// > /// \param HS The header search structure to save. > -void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef > isysroot) { > +void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { > SmallVector<const FileEntry *, 16> FilesByUID; > HS.getFileMgr().GetUniqueIDMapping(FilesByUID); > > @@ -1692,17 +1699,16 @@ void ASTWriter::WriteHeaderSearch(const > (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)) > continue; > > - // Turn the file name into an absolute path, if it isn't already. > + // Massage the file path into an appropriate form. > const char *Filename = File->getName(); > - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); > - > - // If we performed any translation on the file name at all, we need to > - // save this string, since the generator will refer to it later. > - if (Filename != File->getName()) { > - Filename = strdup(Filename); > + SmallString<128> FilenameTmp(Filename); > + if (PreparePathForOutput(FilenameTmp)) { > + // If we performed any translation on the file name at all, we need > to > + // save this string, since the generator will refer to it later. > + Filename = strdup(FilenameTmp.c_str()); > SavedStrings.push_back(Filename); > } > - > + > HeaderFileInfoTrait::key_type key = { File, Filename }; > Generator.insert(key, HFI, GeneratorTrait); > ++NumHeaderSearchEntries; > @@ -1752,8 +1758,7 @@ void ASTWriter::WriteHeaderSearch(const > /// errors), we probably won't have to create file entries for any of > /// the files in the AST. > void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, > - const Preprocessor &PP, > - StringRef isysroot) { > + const Preprocessor &PP) { > RecordData Record; > > // Enter the source manager block. > @@ -1902,17 +1907,10 @@ void ASTWriter::WriteSourceManagerBlock( > LineTableInfo &LineTable = SourceMgr.getLineTable(); > > Record.clear(); > - // Emit the file names > + // 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); > - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); > - unsigned FilenameLen = Filename? strlen(Filename) : 0; > - Record.push_back(FilenameLen); > - if (FilenameLen) > - Record.insert(Record.end(), Filename, Filename + FilenameLen); > - } > + for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) > + AddPath(LineTable.getFilename(I), Record); > > // Emit the line entries > for (LineTableInfo::iterator L = LineTable.begin(), LEnd = > LineTable.end(); > @@ -2543,7 +2541,7 @@ void ASTWriter::WriteSubmodules(Module * > Record.clear(); > for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) { > unsigned ImportedID = getSubmoduleID(Mod->Imports[I]); > - assert(ImportedID && "Unknown submodule!"); > + assert(ImportedID && "Unknown submodule!"); > Record.push_back(ImportedID); > } > Stream.EmitRecord(SUBMODULE_IMPORTS, Record); > @@ -4077,6 +4075,47 @@ void ASTWriter::AddString(StringRef Str, > Record.insert(Record.end(), Str.begin(), Str.end()); > } > > +bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) { > + bool Changed = false; > + > + if (!llvm::sys::path::is_absolute(StringRef(Path.data(), > Path.size()))) { > + // Ask the file manager to fixup the relative path for us. This will > + // honor the working directory. > + if (Context) > + Context->getSourceManager().getFileManager(). > FixupRelativePath(Path); > + > + // We want an absolute path even if we weren't given a spelling for > the > + // current working directory. > + llvm::sys::fs::make_absolute(Path); > + > + Changed = true; > + } > + > + // Remove a prefix to make the path relative, if relevant. > + const char *PathBegin = Path.data(); > + const char *PathPtr = > + adjustFilenameForRelocatableAST(PathBegin, BaseDirectory); > + if (PathPtr != PathBegin) { > + Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin)); > + Changed = true; > + } > + > + return Changed; > +} > + > +void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) { > + SmallString<128> FilePath(Path); > + PreparePathForOutput(FilePath); > + AddString(FilePath, Record); > +} > + > +void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataImpl > &Record, > + StringRef Path) { > + SmallString<128> FilePath(Path); > + PreparePathForOutput(FilePath); > + Stream.EmitRecordWithBlob(Abbrev, Record, FilePath); > +} > + > void ASTWriter::AddVersionTuple(const VersionTuple &Version, > RecordDataImpl &Record) { > Record.push_back(Version.getMajor()); > @@ -4161,6 +4200,7 @@ void ASTWriter::WriteAST(Sema &SemaRef, > Context = nullptr; > PP = nullptr; > this->WritingModule = nullptr; > + this->BaseDirectory.clear(); > > WritingAST = false; > } > @@ -4551,11 +4591,11 @@ void ASTWriter::WriteASTCore(Sema &SemaR > Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); > WriteCXXBaseSpecifiersOffsets(); > WriteFileDeclIDsMap(); > - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); > + WriteSourceManagerBlock(Context.getSourceManager(), PP); > > WriteComments(); > WritePreprocessor(PP, isModule); > - WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot); > + WriteHeaderSearch(PP.getHeaderSearchInfo()); > WriteSelectors(SemaRef); > WriteReferencedSelectorsPool(SemaRef); > WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
