Coverage Report

Created: 2019-07-24 05:18

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