Clang Project

clang_source_code/lib/Serialization/ModuleManager.cpp
1//===- ModuleManager.cpp - Module Manager ---------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file defines the ModuleManager class, which manages a set of loaded
10//  modules for the ASTReader.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Serialization/ModuleManager.h"
15#include "clang/Basic/FileManager.h"
16#include "clang/Basic/LLVM.h"
17#include "clang/Lex/HeaderSearch.h"
18#include "clang/Lex/ModuleMap.h"
19#include "clang/Serialization/GlobalModuleIndex.h"
20#include "clang/Serialization/InMemoryModuleCache.h"
21#include "clang/Serialization/Module.h"
22#include "clang/Serialization/PCHContainerOperations.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SetVector.h"
25#include "llvm/ADT/SmallPtrSet.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/ADT/iterator.h"
29#include "llvm/Support/Chrono.h"
30#include "llvm/Support/DOTGraphTraits.h"
31#include "llvm/Support/ErrorOr.h"
32#include "llvm/Support/GraphWriter.h"
33#include "llvm/Support/MemoryBuffer.h"
34#include "llvm/Support/VirtualFileSystem.h"
35#include <algorithm>
36#include <cassert>
37#include <memory>
38#include <string>
39#include <system_error>
40
41using namespace clang;
42using namespace serialization;
43
44ModuleFile *ModuleManager::lookupByFileName(StringRef Nameconst {
45  const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
46                                           /*cacheFailure=*/false);
47  if (Entry)
48    return lookup(Entry);
49
50  return nullptr;
51}
52
53ModuleFile *ModuleManager::lookupByModuleName(StringRef Nameconst {
54  if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name))
55    if (const FileEntry *File = Mod->getASTFile())
56      return lookup(File);
57
58  return nullptr;
59}
60
61ModuleFile *ModuleManager::lookup(const FileEntry *Fileconst {
62  auto Known = Modules.find(File);
63  if (Known == Modules.end())
64    return nullptr;
65
66  return Known->second;
67}
68
69std::unique_ptr<llvm::MemoryBuffer>
70ModuleManager::lookupBuffer(StringRef Name) {
71  const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
72                                           /*cacheFailure=*/false);
73  return std::move(InMemoryBuffers[Entry]);
74}
75
76static bool checkSignature(ASTFileSignature Signature,
77                           ASTFileSignature ExpectedSignature,
78                           std::string &ErrorStr) {
79  if (!ExpectedSignature || Signature == ExpectedSignature)
80    return false;
81
82  ErrorStr =
83      Signature ? "signature mismatch" : "could not read module signature";
84  return true;
85}
86
87static void updateModuleImports(ModuleFile &MFModuleFile *ImportedBy,
88                                SourceLocation ImportLoc) {
89  if (ImportedBy) {
90    MF.ImportedBy.insert(ImportedBy);
91    ImportedBy->Imports.insert(&MF);
92  } else {
93    if (!MF.DirectlyImported)
94      MF.ImportLoc = ImportLoc;
95
96    MF.DirectlyImported = true;
97  }
98}
99
100ModuleManager::AddModuleResult
101ModuleManager::addModule(StringRef FileNameModuleKind Type,
102                         SourceLocation ImportLocModuleFile *ImportedBy,
103                         unsigned Generation,
104                         off_t ExpectedSizetime_t ExpectedModTime,
105                         ASTFileSignature ExpectedSignature,
106                         ASTFileSignatureReader ReadSignature,
107                         ModuleFile *&Module,
108                         std::string &ErrorStr) {
109  Module = nullptr;
110
111  // Look for the file entry. This only fails if the expected size or
112  // modification time differ.
113  const FileEntry *Entry;
114  if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) {
115    // If we're not expecting to pull this file out of the module cache, it
116    // might have a different mtime due to being moved across filesystems in
117    // a distributed build. The size must still match, though. (As must the
118    // contents, but we can't check that.)
119    ExpectedModTime = 0;
120  }
121  // Note: ExpectedSize and ExpectedModTime will be 0 for MK_ImplicitModule
122  // when using an ASTFileSignature.
123  if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) {
124    ErrorStr = "module file out of date";
125    return OutOfDate;
126  }
127
128  if (!Entry && FileName != "-") {
129    ErrorStr = "module file not found";
130    return Missing;
131  }
132
133  // Check whether we already loaded this module, before
134  if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) {
135    // Check the stored signature.
136    if (checkSignature(ModuleEntry->SignatureExpectedSignatureErrorStr))
137      return OutOfDate;
138
139    Module = ModuleEntry;
140    updateModuleImports(*ModuleEntryImportedByImportLoc);
141    return AlreadyLoaded;
142  }
143
144  // Allocate a new module.
145  auto NewModule = llvm::make_unique<ModuleFile>(Type, Generation);
146  NewModule->Index = Chain.size();
147  NewModule->FileName = FileName.str();
148  NewModule->File = Entry;
149  NewModule->ImportLoc = ImportLoc;
150  NewModule->InputFilesValidationTimestamp = 0;
151
152  if (NewModule->Kind == MK_ImplicitModule) {
153    std::string TimestampFilename = NewModule->getTimestampFilename();
154    llvm::vfs::Status Status;
155    // A cached stat value would be fine as well.
156    if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
157      NewModule->InputFilesValidationTimestamp =
158          llvm::sys::toTimeT(Status.getLastModificationTime());
159  }
160
161  // Load the contents of the module
162  if (std::unique_ptr<llvm::MemoryBufferBuffer = lookupBuffer(FileName)) {
163    // The buffer was already provided for us.
164    NewModule->Buffer = &ModuleCache->addBuiltPCM(FileName, std::move(Buffer));
165    // Since the cached buffer is reused, it is safe to close the file
166    // descriptor that was opened while stat()ing the PCM in
167    // lookupModuleFile() above, it won't be needed any longer.
168    Entry->closeFile();
169  } else if (llvm::MemoryBuffer *Buffer =
170                 getModuleCache().lookupPCM(FileName)) {
171    NewModule->Buffer = Buffer;
172    // As above, the file descriptor is no longer needed.
173    Entry->closeFile();
174  } else if (getModuleCache().shouldBuildPCM(FileName)) {
175    // Report that the module is out of date, since we tried (and failed) to
176    // import it earlier.
177    Entry->closeFile();
178    return OutOfDate;
179  } else {
180    // Open the AST file.
181    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf((std::error_code()));
182    if (FileName == "-") {
183      Buf = llvm::MemoryBuffer::getSTDIN();
184    } else {
185      // Get a buffer of the file and close the file descriptor when done.
186      Buf = FileMgr.getBufferForFile(NewModule->File,
187                                     /*IsVolatile=*/false,
188                                     /*ShouldClose=*/true);
189    }
190
191    if (!Buf) {
192      ErrorStr = Buf.getError().message();
193      return Missing;
194    }
195
196    NewModule->Buffer = &getModuleCache().addPCM(FileName, std::move(*Buf));
197  }
198
199  // Initialize the stream.
200  NewModule->Data = PCHContainerRdr.ExtractPCH(*NewModule->Buffer);
201
202  // Read the signature eagerly now so that we can check it.  Avoid calling
203  // ReadSignature unless there's something to check though.
204  if (ExpectedSignature && checkSignature(ReadSignature(NewModule->Data),
205                                          ExpectedSignature, ErrorStr)) {
206    // Try to remove the buffer.  If it can't be removed, then it was already
207    // validated by this process.
208    if (!getModuleCache().tryToDropPCM(NewModule->FileName))
209      FileMgr.invalidateCache(NewModule->File);
210    return OutOfDate;
211  }
212
213  // We're keeping this module.  Store it everywhere.
214  Module = Modules[Entry] = NewModule.get();
215
216  updateModuleImports(*NewModule, ImportedBy, ImportLoc);
217
218  if (!NewModule->isModule())
219    PCHChain.push_back(NewModule.get());
220  if (!ImportedBy)
221    Roots.push_back(NewModule.get());
222
223  Chain.push_back(std::move(NewModule));
224  return NewlyLoaded;
225}
226
227void ModuleManager::removeModules(
228    ModuleIterator First,
229    llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
230    ModuleMap *modMap) {
231  auto Last = end();
232  if (First == Last)
233    return;
234
235  // Explicitly clear VisitOrder since we might not notice it is stale.
236  VisitOrder.clear();
237
238  // Collect the set of module file pointers that we'll be removing.
239  llvm::SmallPtrSet<ModuleFile *, 4> victimSet(
240      (llvm::pointer_iterator<ModuleIterator>(First)),
241      (llvm::pointer_iterator<ModuleIterator>(Last)));
242
243  auto IsVictim = [&](ModuleFile *MF) {
244    return victimSet.count(MF);
245  };
246  // Remove any references to the now-destroyed modules.
247  for (auto I = begin(); I != First; ++I) {
248    I->Imports.remove_if(IsVictim);
249    I->ImportedBy.remove_if(IsVictim);
250  }
251  Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
252              Roots.end());
253
254  // Remove the modules from the PCH chain.
255  for (auto I = First; I != Last; ++I) {
256    if (!I->isModule()) {
257      PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), &*I),
258                     PCHChain.end());
259      break;
260    }
261  }
262
263  // Delete the modules and erase them from the various structures.
264  for (ModuleIterator victim = First; victim != Last; ++victim) {
265    Modules.erase(victim->File);
266
267    if (modMap) {
268      StringRef ModuleName = victim->ModuleName;
269      if (Module *mod = modMap->findModule(ModuleName)) {
270        mod->setASTFile(nullptr);
271      }
272    }
273  }
274
275  // Delete the modules.
276  Chain.erase(Chain.begin() + (First - begin()), Chain.end());
277}
278
279void
280ModuleManager::addInMemoryBuffer(StringRef FileName,
281                                 std::unique_ptr<llvm::MemoryBufferBuffer) {
282  const FileEntry *Entry =
283      FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
284  InMemoryBuffers[Entry] = std::move(Buffer);
285}
286
287ModuleManager::VisitState *ModuleManager::allocateVisitState() {
288  // Fast path: if we have a cached state, use it.
289  if (FirstVisitState) {
290    VisitState *Result = FirstVisitState;
291    FirstVisitState = FirstVisitState->NextState;
292    Result->NextState = nullptr;
293    return Result;
294  }
295
296  // Allocate and return a new state.
297  return new VisitState(size());
298}
299
300void ModuleManager::returnVisitState(VisitState *State) {
301   (0) . __assert_fail ("State->NextState == nullptr && \"Visited state is in list?\"", "/home/seafit/code_projects/clang_source/clang/lib/Serialization/ModuleManager.cpp", 301, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(State->NextState == nullptr && "Visited state is in list?");
302  State->NextState = FirstVisitState;
303  FirstVisitState = State;
304}
305
306void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
307  GlobalIndex = Index;
308  if (!GlobalIndex) {
309    ModulesInCommonWithGlobalIndex.clear();
310    return;
311  }
312
313  // Notify the global module index about all of the modules we've already
314  // loaded.
315  for (ModuleFile &M : *this)
316    if (!GlobalIndex->loadedModuleFile(&M))
317      ModulesInCommonWithGlobalIndex.push_back(&M);
318}
319
320void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
321  if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
322    return;
323
324  ModulesInCommonWithGlobalIndex.push_back(MF);
325}
326
327ModuleManager::ModuleManager(FileManager &FileMgr,
328                             InMemoryModuleCache &ModuleCache,
329                             const PCHContainerReader &PCHContainerRdr,
330                             const HeaderSearch &HeaderSearchInfo)
331    : FileMgr(FileMgr), ModuleCache(&ModuleCache),
332      PCHContainerRdr(PCHContainerRdr), HeaderSearchInfo(HeaderSearchInfo) {}
333
334ModuleManager::~ModuleManager() { delete FirstVisitState; }
335
336void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
337                          llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
338  // If the visitation order vector is the wrong size, recompute the order.
339  if (VisitOrder.size() != Chain.size()) {
340    unsigned N = size();
341    VisitOrder.clear();
342    VisitOrder.reserve(N);
343
344    // Record the number of incoming edges for each module. When we
345    // encounter a module with no incoming edges, push it into the queue
346    // to seed the queue.
347    SmallVector<ModuleFile *, 4> Queue;
348    Queue.reserve(N);
349    llvm::SmallVector<unsigned4> UnusedIncomingEdges;
350    UnusedIncomingEdges.resize(size());
351    for (ModuleFile &M : llvm::reverse(*this)) {
352      unsigned Size = M.ImportedBy.size();
353      UnusedIncomingEdges[M.Index] = Size;
354      if (!Size)
355        Queue.push_back(&M);
356    }
357
358    // Traverse the graph, making sure to visit a module before visiting any
359    // of its dependencies.
360    while (!Queue.empty()) {
361      ModuleFile *CurrentModule = Queue.pop_back_val();
362      VisitOrder.push_back(CurrentModule);
363
364      // For any module that this module depends on, push it on the
365      // stack (if it hasn't already been marked as visited).
366      for (auto M = CurrentModule->Imports.rbegin(),
367                MEnd = CurrentModule->Imports.rend();
368           M != MEnd; ++M) {
369        // Remove our current module as an impediment to visiting the
370        // module we depend on. If we were the last unvisited module
371        // that depends on this particular module, push it into the
372        // queue to be visited.
373        unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
374        if (NumUnusedEdges && (--NumUnusedEdges == 0))
375          Queue.push_back(*M);
376      }
377    }
378
379     (0) . __assert_fail ("VisitOrder.size() == N && \"Visitation order is wrong?\"", "/home/seafit/code_projects/clang_source/clang/lib/Serialization/ModuleManager.cpp", 379, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VisitOrder.size() == N && "Visitation order is wrong?");
380
381    delete FirstVisitState;
382    FirstVisitState = nullptr;
383  }
384
385  VisitState *State = allocateVisitState();
386  unsigned VisitNumber = State->NextVisitNumber++;
387
388  // If the caller has provided us with a hit-set that came from the global
389  // module index, mark every module file in common with the global module
390  // index that is *not* in that set as 'visited'.
391  if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
392    for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
393    {
394      ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
395      if (!ModuleFilesHit->count(M))
396        State->VisitNumber[M->Index] = VisitNumber;
397    }
398  }
399
400  for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
401    ModuleFile *CurrentModule = VisitOrder[I];
402    // Should we skip this module file?
403    if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
404      continue;
405
406    // Visit the module.
407    VisitNumber[CurrentModule->Index] == VisitNumber - 1", "/home/seafit/code_projects/clang_source/clang/lib/Serialization/ModuleManager.cpp", 407, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
408    State->VisitNumber[CurrentModule->Index] = VisitNumber;
409    if (!Visitor(*CurrentModule))
410      continue;
411
412    // The visitor has requested that cut off visitation of any
413    // module that the current module depends on. To indicate this
414    // behavior, we mark all of the reachable modules as having been visited.
415    ModuleFile *NextModule = CurrentModule;
416    do {
417      // For any module that this module depends on, push it on the
418      // stack (if it hasn't already been marked as visited).
419      for (llvm::SetVector<ModuleFile *>::iterator
420             M = NextModule->Imports.begin(),
421             MEnd = NextModule->Imports.end();
422           M != MEnd; ++M) {
423        if (State->VisitNumber[(*M)->Index] != VisitNumber) {
424          State->Stack.push_back(*M);
425          State->VisitNumber[(*M)->Index] = VisitNumber;
426        }
427      }
428
429      if (State->Stack.empty())
430        break;
431
432      // Pop the next module off the stack.
433      NextModule = State->Stack.pop_back_val();
434    } while (true);
435  }
436
437  returnVisitState(State);
438}
439
440bool ModuleManager::lookupModuleFile(StringRef FileName,
441                                     off_t ExpectedSize,
442                                     time_t ExpectedModTime,
443                                     const FileEntry *&File) {
444  if (FileName == "-") {
445    File = nullptr;
446    return false;
447  }
448
449  // Open the file immediately to ensure there is no race between stat'ing and
450  // opening the file.
451  File = FileMgr.getFile(FileName, /*openFile=*/true/*cacheFailure=*/false);
452  if (!File)
453    return false;
454
455  if ((ExpectedSize && ExpectedSize != File->getSize()) ||
456      (ExpectedModTime && ExpectedModTime != File->getModificationTime()))
457    // Do not destroy File, as it may be referenced. If we need to rebuild it,
458    // it will be destroyed by removeModules.
459    return true;
460
461  return false;
462}
463
464#ifndef NDEBUG
465namespace llvm {
466
467  template<>
468  struct GraphTraits<ModuleManager> {
469    using NodeRef = ModuleFile *;
470    using ChildIteratorType = llvm::SetVector<ModuleFile *>::const_iterator;
471    using nodes_iterator = pointer_iterator<ModuleManager::ModuleConstIterator>;
472
473    static ChildIteratorType child_begin(NodeRef Node) {
474      return Node->Imports.begin();
475    }
476
477    static ChildIteratorType child_end(NodeRef Node) {
478      return Node->Imports.end();
479    }
480
481    static nodes_iterator nodes_begin(const ModuleManager &Manager) {
482      return nodes_iterator(Manager.begin());
483    }
484
485    static nodes_iterator nodes_end(const ModuleManager &Manager) {
486      return nodes_iterator(Manager.end());
487    }
488  };
489
490  template<>
491  struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
492    explicit DOTGraphTraits(bool IsSimple = false)
493        : DefaultDOTGraphTraits(IsSimple) {}
494
495    static bool renderGraphFromBottomUp() { return true; }
496
497    std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
498      return M->ModuleName;
499    }
500  };
501
502// namespace llvm
503
504void ModuleManager::viewGraph() {
505  llvm::ViewGraph(*this"Modules");
506}
507#endif
508
clang::serialization::ModuleManager::lookupByFileName
clang::serialization::ModuleManager::lookupByModuleName
clang::serialization::ModuleManager::lookup
clang::serialization::ModuleManager::lookupBuffer
clang::serialization::ModuleManager::addModule
clang::serialization::ModuleManager::removeModules
clang::serialization::ModuleManager::addInMemoryBuffer
clang::serialization::ModuleManager::allocateVisitState
clang::serialization::ModuleManager::returnVisitState
clang::serialization::ModuleManager::setGlobalIndex
clang::serialization::ModuleManager::moduleFileAccepted