aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Serialization/GlobalModuleIndex.h
blob: 7e205106c4ee8a812f141a50b454d8bd4ef2881b (plain) (blame)
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
//===--- GlobalModuleIndex.h - Global Module Index --------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the GlobalModuleIndex class, which manages a global index
// containing all of the identifiers known to the various modules within a given
// subdirectory of the module cache. It is used to improve the performance of
// queries such as "do any modules know about this identifier?"
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SERIALIZATION_GLOBALMODULEINDEX_H
#define LLVM_CLANG_SERIALIZATION_GLOBALMODULEINDEX_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include <memory>
#include <utility>

namespace llvm {
class BitstreamCursor;
class MemoryBuffer;
}

namespace clang {

class DirectoryEntry;
class FileEntry;
class FileManager;
class IdentifierIterator;
class PCHContainerOperations;

namespace serialization {
  class ModuleFile;
}

using llvm::SmallVector;
using llvm::SmallVectorImpl;
using llvm::StringRef;
using serialization::ModuleFile;

/// \brief A global index for a set of module files, providing information about
/// the identifiers within those module files.
///
/// The global index is an aid for name lookup into modules, offering a central
/// place where one can look for identifiers determine which
/// module files contain any information about that identifier. This
/// allows the client to restrict the search to only those module files known
/// to have a information about that identifier, improving performance. Moreover,
/// the global module index may know about module files that have not been
/// imported, and can be queried to determine which modules the current
/// translation could or should load to fix a problem.
class GlobalModuleIndex {
  /// \brief Buffer containing the index file, which is lazily accessed so long
  /// as the global module index is live.
  std::unique_ptr<llvm::MemoryBuffer> Buffer;

  /// \brief The hash table.
  ///
  /// This pointer actually points to a IdentifierIndexTable object,
  /// but that type is only accessible within the implementation of
  /// GlobalModuleIndex.
  void *IdentifierIndex;

  /// \brief Information about a given module file.
  struct ModuleInfo {
    ModuleInfo() : File(), Size(), ModTime() { }

    /// \brief The module file, once it has been resolved.
    ModuleFile *File;

    /// \brief The module file name.
    std::string FileName;

    /// \brief Size of the module file at the time the global index was built.
    off_t Size;

    /// \brief Modification time of the module file at the time the global
    /// index was built.
    time_t ModTime;

    /// \brief The module IDs on which this module directly depends.
    /// FIXME: We don't really need a vector here.
    llvm::SmallVector<unsigned, 4> Dependencies;
  };

  /// \brief A mapping from module IDs to information about each module.
  ///
  /// This vector may have gaps, if module files have been removed or have
  /// been updated since the index was built. A gap is indicated by an empty
  /// file name.
  llvm::SmallVector<ModuleInfo, 16> Modules;

  /// \brief Lazily-populated mapping from module files to their
  /// corresponding index into the \c Modules vector.
  llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile;

  /// \brief The set of modules that have not yet been resolved.
  ///
  /// The string is just the name of the module itself, which maps to the
  /// module ID.
  llvm::StringMap<unsigned> UnresolvedModules;

  /// \brief The number of identifier lookups we performed.
  unsigned NumIdentifierLookups;

  /// \brief The number of identifier lookup hits, where we recognize the
  /// identifier.
  unsigned NumIdentifierLookupHits;
  
  /// \brief Internal constructor. Use \c readIndex() to read an index.
  explicit GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer,
                             llvm::BitstreamCursor Cursor);

  GlobalModuleIndex(const GlobalModuleIndex &) = delete;
  GlobalModuleIndex &operator=(const GlobalModuleIndex &) = delete;

public:
  ~GlobalModuleIndex();

  /// \brief An error code returned when trying to read an index.
  enum ErrorCode {
    /// \brief No error occurred.
    EC_None,
    /// \brief No index was found.
    EC_NotFound,
    /// \brief Some other process is currently building the index; it is not
    /// available yet.
    EC_Building,
    /// \brief There was an unspecified I/O error reading or writing the index.
    EC_IOError
  };

  /// \brief Read a global index file for the given directory.
  ///
  /// \param Path The path to the specific module cache where the module files
  /// for the intended configuration reside.
  ///
  /// \returns A pair containing the global module index (if it exists) and
  /// the error code.
  static std::pair<GlobalModuleIndex *, ErrorCode>
  readIndex(StringRef Path);

  /// \brief Returns an iterator for identifiers stored in the index table.
  ///
  /// The caller accepts ownership of the returned object.
  IdentifierIterator *createIdentifierIterator() const;

  /// \brief Retrieve the set of modules that have up-to-date indexes.
  ///
  /// \param ModuleFiles Will be populated with the set of module files that
  /// have been indexed.
  void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles);

  /// \brief Retrieve the set of module files on which the given module file
  /// directly depends.
  void getModuleDependencies(ModuleFile *File,
                             SmallVectorImpl<ModuleFile *> &Dependencies);

  /// \brief A set of module files in which we found a result.
  typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet;
  
  /// \brief Look for all of the module files with information about the given
  /// identifier, e.g., a global function, variable, or type with that name.
  ///
  /// \param Name The identifier to look for.
  ///
  /// \param Hits Will be populated with the set of module files that have
  /// information about this name.
  ///
  /// \returns true if the identifier is known to the index, false otherwise.
  bool lookupIdentifier(StringRef Name, HitSet &Hits);

  /// \brief Note that the given module file has been loaded.
  ///
  /// \returns false if the global module index has information about this
  /// module file, and true otherwise.
  bool loadedModuleFile(ModuleFile *File);

  /// \brief Print statistics to standard error.
  void printStats();

  /// \brief Print debugging view to standard error.
  void dump();

  /// \brief Write a global index into the given
  ///
  /// \param FileMgr The file manager to use to load module files.
  /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
  /// creating modules.
  /// \param Path The path to the directory containing module files, into
  /// which the global index will be written.
  static ErrorCode writeIndex(FileManager &FileMgr,
                              const PCHContainerOperations &PCHContainerOps,
                              StringRef Path);
};

}

#endif