r223443 - [modules] Instead of storing absolute paths in a .pcm file, store the path to

Manuel Klimek klimek at google.com
Fri Dec 5 03:30:22 PST 2014


On Fri Dec 05 2014 at 3:36:24 AM Richard Smith <richard-llvm at metafoo.co.uk>
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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141205/1465f429/attachment.html>


More information about the cfe-commits mailing list