reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
//===- ModuleManager.cpp - Module Manager -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ModuleManager class, which manages a set of loaded
//  modules for the ASTReader.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H
#define LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H

#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/Module.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include <cstdint>
#include <ctime>
#include <memory>
#include <string>
#include <utility>

namespace clang {

class FileEntry;
class FileManager;
class GlobalModuleIndex;
class HeaderSearch;
class InMemoryModuleCache;
class ModuleMap;
class PCHContainerReader;

namespace serialization {

/// Manages the set of modules loaded by an AST reader.
class ModuleManager {
  /// The chain of AST files, in the order in which we started to load
  /// them (this order isn't really useful for anything).
  SmallVector<std::unique_ptr<ModuleFile>, 2> Chain;

  /// The chain of non-module PCH files. The first entry is the one named
  /// by the user, the last one is the one that doesn't depend on anything
  /// further.
  SmallVector<ModuleFile *, 2> PCHChain;

  // The roots of the dependency DAG of AST files. This is used
  // to implement short-circuiting logic when running DFS over the dependencies.
  SmallVector<ModuleFile *, 2> Roots;

  /// All loaded modules, indexed by name.
  llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;

  /// FileManager that handles translating between filenames and
  /// FileEntry *.
  FileManager &FileMgr;

  /// Cache of PCM files.
  IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;

  /// Knows how to unwrap module containers.
  const PCHContainerReader &PCHContainerRdr;

  /// Preprocessor's HeaderSearchInfo containing the module map.
  const HeaderSearch &HeaderSearchInfo;

  /// A lookup of in-memory (virtual file) buffers
  llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
      InMemoryBuffers;

  /// The visitation order.
  SmallVector<ModuleFile *, 4> VisitOrder;

  /// The list of module files that both we and the global module index
  /// know about.
  ///
  /// Either the global index or the module manager may have modules that the
  /// other does not know about, because the global index can be out-of-date
  /// (in which case the module manager could have modules it does not) and
  /// this particular translation unit might not have loaded all of the modules
  /// known to the global index.
  SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex;

  /// The global module index, if one is attached.
  ///
  /// The global module index will actually be owned by the ASTReader; this is
  /// just an non-owning pointer.
  GlobalModuleIndex *GlobalIndex = nullptr;

  /// State used by the "visit" operation to avoid malloc traffic in
  /// calls to visit().
  struct VisitState {
    explicit VisitState(unsigned N) : VisitNumber(N, 0) {
      Stack.reserve(N);
    }

    ~VisitState() {
      delete NextState;
    }

    /// The stack used when marking the imports of a particular module
    /// as not-to-be-visited.
    SmallVector<ModuleFile *, 4> Stack;

    /// The visit number of each module file, which indicates when
    /// this module file was last visited.
    SmallVector<unsigned, 4> VisitNumber;

    /// The next visit number to use to mark visited module files.
    unsigned NextVisitNumber = 1;

    /// The next visit state.
    VisitState *NextState = nullptr;
  };

  /// The first visit() state in the chain.
  VisitState *FirstVisitState = nullptr;

  VisitState *allocateVisitState();
  void returnVisitState(VisitState *State);

public:
  using ModuleIterator = llvm::pointee_iterator<
      SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator>;
  using ModuleConstIterator = llvm::pointee_iterator<
      SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator>;
  using ModuleReverseIterator = llvm::pointee_iterator<
      SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>;
  using ModuleOffset = std::pair<uint32_t, StringRef>;

  explicit ModuleManager(FileManager &FileMgr, InMemoryModuleCache &ModuleCache,
                         const PCHContainerReader &PCHContainerRdr,
                         const HeaderSearch &HeaderSearchInfo);
  ~ModuleManager();

  /// Forward iterator to traverse all loaded modules.
  ModuleIterator begin() { return Chain.begin(); }

  /// Forward iterator end-point to traverse all loaded modules
  ModuleIterator end() { return Chain.end(); }

  /// Const forward iterator to traverse all loaded modules.
  ModuleConstIterator begin() const { return Chain.begin(); }

  /// Const forward iterator end-point to traverse all loaded modules
  ModuleConstIterator end() const { return Chain.end(); }

  /// Reverse iterator to traverse all loaded modules.
  ModuleReverseIterator rbegin() { return Chain.rbegin(); }

  /// Reverse iterator end-point to traverse all loaded modules.
  ModuleReverseIterator rend() { return Chain.rend(); }

  /// A range covering the PCH and preamble module files loaded.
  llvm::iterator_range<SmallVectorImpl<ModuleFile *>::const_iterator>
  pch_modules() const {
    return llvm::make_range(PCHChain.begin(), PCHChain.end());
  }

  /// Returns the primary module associated with the manager, that is,
  /// the first module loaded
  ModuleFile &getPrimaryModule() { return *Chain[0]; }

  /// Returns the primary module associated with the manager, that is,
  /// the first module loaded.
  ModuleFile &getPrimaryModule() const { return *Chain[0]; }

  /// Returns the module associated with the given index
  ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; }

  /// Returns the module associated with the given file name.
  ModuleFile *lookupByFileName(StringRef FileName) const;

  /// Returns the module associated with the given module name.
  ModuleFile *lookupByModuleName(StringRef ModName) const;

  /// Returns the module associated with the given module file.
  ModuleFile *lookup(const FileEntry *File) const;

  /// Returns the in-memory (virtual file) buffer with the given name
  std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name);

  /// Number of modules loaded
  unsigned size() const { return Chain.size(); }

  /// The result of attempting to add a new module.
  enum AddModuleResult {
    /// The module file had already been loaded.
    AlreadyLoaded,

    /// The module file was just loaded in response to this call.
    NewlyLoaded,

    /// The module file is missing.
    Missing,

    /// The module file is out-of-date.
    OutOfDate
  };

  using ASTFileSignatureReader = ASTFileSignature (*)(StringRef);

  /// Attempts to create a new module and add it to the list of known
  /// modules.
  ///
  /// \param FileName The file name of the module to be loaded.
  ///
  /// \param Type The kind of module being loaded.
  ///
  /// \param ImportLoc The location at which the module is imported.
  ///
  /// \param ImportedBy The module that is importing this module, or NULL if
  /// this module is imported directly by the user.
  ///
  /// \param Generation The generation in which this module was loaded.
  ///
  /// \param ExpectedSize The expected size of the module file, used for
  /// validation. This will be zero if unknown.
  ///
  /// \param ExpectedModTime The expected modification time of the module
  /// file, used for validation. This will be zero if unknown.
  ///
  /// \param ExpectedSignature The expected signature of the module file, used
  /// for validation. This will be zero if unknown.
  ///
  /// \param ReadSignature Reads the signature from an AST file without actually
  /// loading it.
  ///
  /// \param Module A pointer to the module file if the module was successfully
  /// loaded.
  ///
  /// \param ErrorStr Will be set to a non-empty string if any errors occurred
  /// while trying to load the module.
  ///
  /// \return A pointer to the module that corresponds to this file name,
  /// and a value indicating whether the module was loaded.
  AddModuleResult addModule(StringRef FileName, ModuleKind Type,
                            SourceLocation ImportLoc,
                            ModuleFile *ImportedBy, unsigned Generation,
                            off_t ExpectedSize, time_t ExpectedModTime,
                            ASTFileSignature ExpectedSignature,
                            ASTFileSignatureReader ReadSignature,
                            ModuleFile *&Module,
                            std::string &ErrorStr);

  /// Remove the modules starting from First (to the end).
  void removeModules(ModuleIterator First,
                     llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
                     ModuleMap *modMap);

  /// Add an in-memory buffer the list of known buffers
  void addInMemoryBuffer(StringRef FileName,
                         std::unique_ptr<llvm::MemoryBuffer> Buffer);

  /// Set the global module index.
  void setGlobalIndex(GlobalModuleIndex *Index);

  /// Notification from the AST reader that the given module file
  /// has been "accepted", and will not (can not) be unloaded.
  void moduleFileAccepted(ModuleFile *MF);

  /// Visit each of the modules.
  ///
  /// This routine visits each of the modules, starting with the
  /// "root" modules that no other loaded modules depend on, and
  /// proceeding to the leaf modules, visiting each module only once
  /// during the traversal.
  ///
  /// This traversal is intended to support various "lookup"
  /// operations that can find data in any of the loaded modules.
  ///
  /// \param Visitor A visitor function that will be invoked with each
  /// module. The return value must be convertible to bool; when false, the
  /// visitation continues to modules that the current module depends on. When
  /// true, the visitation skips any modules that the current module depends on.
  ///
  /// \param ModuleFilesHit If non-NULL, contains the set of module files
  /// that we know we need to visit because the global module index told us to.
  /// Any module that is known to both the global module index and the module
  /// manager that is *not* in this set can be skipped.
  void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
             llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr);

  /// Attempt to resolve the given module file name to a file entry.
  ///
  /// \param FileName The name of the module file.
  ///
  /// \param ExpectedSize The size that the module file is expected to have.
  /// If the actual size differs, the resolver should return \c true.
  ///
  /// \param ExpectedModTime The modification time that the module file is
  /// expected to have. If the actual modification time differs, the resolver
  /// should return \c true.
  ///
  /// \param File Will be set to the file if there is one, or null
  /// otherwise.
  ///
  /// \returns True if a file exists but does not meet the size/
  /// modification time criteria, false if the file is either available and
  /// suitable, or is missing.
  bool lookupModuleFile(StringRef FileName,
                        off_t ExpectedSize,
                        time_t ExpectedModTime,
                        const FileEntry *&File);

  /// View the graphviz representation of the module graph.
  void viewGraph();

  InMemoryModuleCache &getModuleCache() const { return *ModuleCache; }
};

} // namespace serialization

} // namespace clang

#endif // LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H