Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Serialization/GlobalModuleIndex.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- GlobalModuleIndex.cpp - Global Module Index ------------*- C++ -*-===//
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 implements the GlobalModuleIndex class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/Serialization/GlobalModuleIndex.h"
14
#include "ASTReaderInternals.h"
15
#include "clang/Basic/FileManager.h"
16
#include "clang/Lex/HeaderSearch.h"
17
#include "clang/Serialization/ASTBitCodes.h"
18
#include "clang/Serialization/ModuleFile.h"
19
#include "clang/Serialization/PCHContainerOperations.h"
20
#include "llvm/ADT/DenseMap.h"
21
#include "llvm/ADT/MapVector.h"
22
#include "llvm/ADT/SmallString.h"
23
#include "llvm/ADT/StringRef.h"
24
#include "llvm/Bitstream/BitstreamReader.h"
25
#include "llvm/Bitstream/BitstreamWriter.h"
26
#include "llvm/Support/DJB.h"
27
#include "llvm/Support/FileSystem.h"
28
#include "llvm/Support/LockFileManager.h"
29
#include "llvm/Support/MemoryBuffer.h"
30
#include "llvm/Support/OnDiskHashTable.h"
31
#include "llvm/Support/Path.h"
32
#include "llvm/Support/TimeProfiler.h"
33
#include "llvm/Support/raw_ostream.h"
34
#include <cstdio>
35
using namespace clang;
36
using namespace serialization;
37
38
//----------------------------------------------------------------------------//
39
// Shared constants
40
//----------------------------------------------------------------------------//
41
namespace {
42
  enum {
43
    /// The block containing the index.
44
    GLOBAL_INDEX_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID
45
  };
46
47
  /// Describes the record types in the index.
48
  enum IndexRecordTypes {
49
    /// Contains version information and potentially other metadata,
50
    /// used to determine if we can read this global index file.
51
    INDEX_METADATA,
52
    /// Describes a module, including its file name and dependencies.
53
    MODULE,
54
    /// The index for identifiers.
55
    IDENTIFIER_INDEX
56
  };
57
}
58
59
/// The name of the global index file.
60
static const char * const IndexFileName = "modules.idx";
61
62
/// The global index file version.
63
static const unsigned CurrentVersion = 1;
64
65
//----------------------------------------------------------------------------//
66
// Global module index reader.
67
//----------------------------------------------------------------------------//
68
69
namespace {
70
71
/// Trait used to read the identifier index from the on-disk hash
72
/// table.
73
class IdentifierIndexReaderTrait {
74
public:
75
  typedef StringRef external_key_type;
76
  typedef StringRef internal_key_type;
77
  typedef SmallVector<unsigned, 2> data_type;
78
  typedef unsigned hash_value_type;
79
  typedef unsigned offset_type;
80
81
0
  static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
82
0
    return a == b;
83
0
  }
84
85
0
  static hash_value_type ComputeHash(const internal_key_type& a) {
86
0
    return llvm::djbHash(a);
87
0
  }
88
89
  static std::pair<unsigned, unsigned>
90
0
  ReadKeyDataLength(const unsigned char*& d) {
91
0
    using namespace llvm::support;
92
0
    unsigned KeyLen =
93
0
        endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
94
0
    unsigned DataLen =
95
0
        endian::readNext<uint16_t, llvm::endianness::little, unaligned>(d);
96
0
    return std::make_pair(KeyLen, DataLen);
97
0
  }
98
99
  static const internal_key_type&
100
0
  GetInternalKey(const external_key_type& x) { return x; }
101
102
  static const external_key_type&
103
0
  GetExternalKey(const internal_key_type& x) { return x; }
104
105
0
  static internal_key_type ReadKey(const unsigned char* d, unsigned n) {
106
0
    return StringRef((const char *)d, n);
107
0
  }
108
109
  static data_type ReadData(const internal_key_type& k,
110
                            const unsigned char* d,
111
0
                            unsigned DataLen) {
112
0
    using namespace llvm::support;
113
114
0
    data_type Result;
115
0
    while (DataLen > 0) {
116
0
      unsigned ID =
117
0
          endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
118
0
      Result.push_back(ID);
119
0
      DataLen -= 4;
120
0
    }
121
122
0
    return Result;
123
0
  }
124
};
125
126
typedef llvm::OnDiskIterableChainedHashTable<IdentifierIndexReaderTrait>
127
    IdentifierIndexTable;
128
129
}
130
131
GlobalModuleIndex::GlobalModuleIndex(
132
    std::unique_ptr<llvm::MemoryBuffer> IndexBuffer,
133
    llvm::BitstreamCursor Cursor)
134
    : Buffer(std::move(IndexBuffer)), IdentifierIndex(), NumIdentifierLookups(),
135
0
      NumIdentifierLookupHits() {
136
0
  auto Fail = [&](llvm::Error &&Err) {
137
0
    report_fatal_error("Module index '" + Buffer->getBufferIdentifier() +
138
0
                       "' failed: " + toString(std::move(Err)));
139
0
  };
140
141
0
  llvm::TimeTraceScope TimeScope("Module LoadIndex");
142
  // Read the global index.
143
0
  bool InGlobalIndexBlock = false;
144
0
  bool Done = false;
145
0
  while (!Done) {
146
0
    llvm::BitstreamEntry Entry;
147
0
    if (Expected<llvm::BitstreamEntry> Res = Cursor.advance())
148
0
      Entry = Res.get();
149
0
    else
150
0
      Fail(Res.takeError());
151
152
0
    switch (Entry.Kind) {
153
0
    case llvm::BitstreamEntry::Error:
154
0
      return;
155
156
0
    case llvm::BitstreamEntry::EndBlock:
157
0
      if (InGlobalIndexBlock) {
158
0
        InGlobalIndexBlock = false;
159
0
        Done = true;
160
0
        continue;
161
0
      }
162
0
      return;
163
164
165
0
    case llvm::BitstreamEntry::Record:
166
      // Entries in the global index block are handled below.
167
0
      if (InGlobalIndexBlock)
168
0
        break;
169
170
0
      return;
171
172
0
    case llvm::BitstreamEntry::SubBlock:
173
0
      if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) {
174
0
        if (llvm::Error Err = Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
175
0
          Fail(std::move(Err));
176
0
        InGlobalIndexBlock = true;
177
0
      } else if (llvm::Error Err = Cursor.SkipBlock())
178
0
        Fail(std::move(Err));
179
0
      continue;
180
0
    }
181
182
0
    SmallVector<uint64_t, 64> Record;
183
0
    StringRef Blob;
184
0
    Expected<unsigned> MaybeIndexRecord =
185
0
        Cursor.readRecord(Entry.ID, Record, &Blob);
186
0
    if (!MaybeIndexRecord)
187
0
      Fail(MaybeIndexRecord.takeError());
188
0
    IndexRecordTypes IndexRecord =
189
0
        static_cast<IndexRecordTypes>(MaybeIndexRecord.get());
190
0
    switch (IndexRecord) {
191
0
    case INDEX_METADATA:
192
      // Make sure that the version matches.
193
0
      if (Record.size() < 1 || Record[0] != CurrentVersion)
194
0
        return;
195
0
      break;
196
197
0
    case MODULE: {
198
0
      unsigned Idx = 0;
199
0
      unsigned ID = Record[Idx++];
200
201
      // Make room for this module's information.
202
0
      if (ID == Modules.size())
203
0
        Modules.push_back(ModuleInfo());
204
0
      else
205
0
        Modules.resize(ID + 1);
206
207
      // Size/modification time for this module file at the time the
208
      // global index was built.
209
0
      Modules[ID].Size = Record[Idx++];
210
0
      Modules[ID].ModTime = Record[Idx++];
211
212
      // File name.
213
0
      unsigned NameLen = Record[Idx++];
214
0
      Modules[ID].FileName.assign(Record.begin() + Idx,
215
0
                                  Record.begin() + Idx + NameLen);
216
0
      Idx += NameLen;
217
218
      // Dependencies
219
0
      unsigned NumDeps = Record[Idx++];
220
0
      Modules[ID].Dependencies.insert(Modules[ID].Dependencies.end(),
221
0
                                      Record.begin() + Idx,
222
0
                                      Record.begin() + Idx + NumDeps);
223
0
      Idx += NumDeps;
224
225
      // Make sure we're at the end of the record.
226
0
      assert(Idx == Record.size() && "More module info?");
227
228
      // Record this module as an unresolved module.
229
      // FIXME: this doesn't work correctly for module names containing path
230
      // separators.
231
0
      StringRef ModuleName = llvm::sys::path::stem(Modules[ID].FileName);
232
      // Remove the -<hash of ModuleMapPath>
233
0
      ModuleName = ModuleName.rsplit('-').first;
234
0
      UnresolvedModules[ModuleName] = ID;
235
0
      break;
236
0
    }
237
238
0
    case IDENTIFIER_INDEX:
239
      // Wire up the identifier index.
240
0
      if (Record[0]) {
241
0
        IdentifierIndex = IdentifierIndexTable::Create(
242
0
            (const unsigned char *)Blob.data() + Record[0],
243
0
            (const unsigned char *)Blob.data() + sizeof(uint32_t),
244
0
            (const unsigned char *)Blob.data(), IdentifierIndexReaderTrait());
245
0
      }
246
0
      break;
247
0
    }
248
0
  }
249
0
}
250
251
0
GlobalModuleIndex::~GlobalModuleIndex() {
252
0
  delete static_cast<IdentifierIndexTable *>(IdentifierIndex);
253
0
}
254
255
std::pair<GlobalModuleIndex *, llvm::Error>
256
0
GlobalModuleIndex::readIndex(StringRef Path) {
257
  // Load the index file, if it's there.
258
0
  llvm::SmallString<128> IndexPath;
259
0
  IndexPath += Path;
260
0
  llvm::sys::path::append(IndexPath, IndexFileName);
261
262
0
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrErr =
263
0
      llvm::MemoryBuffer::getFile(IndexPath.c_str());
264
0
  if (!BufferOrErr)
265
0
    return std::make_pair(nullptr,
266
0
                          llvm::errorCodeToError(BufferOrErr.getError()));
267
0
  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
268
269
  /// The main bitstream cursor for the main block.
270
0
  llvm::BitstreamCursor Cursor(*Buffer);
271
272
  // Sniff for the signature.
273
0
  for (unsigned char C : {'B', 'C', 'G', 'I'}) {
274
0
    if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Cursor.Read(8)) {
275
0
      if (Res.get() != C)
276
0
        return std::make_pair(
277
0
            nullptr, llvm::createStringError(std::errc::illegal_byte_sequence,
278
0
                                             "expected signature BCGI"));
279
0
    } else
280
0
      return std::make_pair(nullptr, Res.takeError());
281
0
  }
282
283
0
  return std::make_pair(new GlobalModuleIndex(std::move(Buffer), std::move(Cursor)),
284
0
                        llvm::Error::success());
285
0
}
286
287
void GlobalModuleIndex::getModuleDependencies(
288
       ModuleFile *File,
289
0
       SmallVectorImpl<ModuleFile *> &Dependencies) {
290
  // Look for information about this module file.
291
0
  llvm::DenseMap<ModuleFile *, unsigned>::iterator Known
292
0
    = ModulesByFile.find(File);
293
0
  if (Known == ModulesByFile.end())
294
0
    return;
295
296
  // Record dependencies.
297
0
  Dependencies.clear();
298
0
  ArrayRef<unsigned> StoredDependencies = Modules[Known->second].Dependencies;
299
0
  for (unsigned I = 0, N = StoredDependencies.size(); I != N; ++I) {
300
0
    if (ModuleFile *MF = Modules[I].File)
301
0
      Dependencies.push_back(MF);
302
0
  }
303
0
}
304
305
0
bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) {
306
0
  Hits.clear();
307
308
  // If there's no identifier index, there is nothing we can do.
309
0
  if (!IdentifierIndex)
310
0
    return false;
311
312
  // Look into the identifier index.
313
0
  ++NumIdentifierLookups;
314
0
  IdentifierIndexTable &Table
315
0
    = *static_cast<IdentifierIndexTable *>(IdentifierIndex);
316
0
  IdentifierIndexTable::iterator Known = Table.find(Name);
317
0
  if (Known == Table.end()) {
318
0
    return false;
319
0
  }
320
321
0
  SmallVector<unsigned, 2> ModuleIDs = *Known;
322
0
  for (unsigned I = 0, N = ModuleIDs.size(); I != N; ++I) {
323
0
    if (ModuleFile *MF = Modules[ModuleIDs[I]].File)
324
0
      Hits.insert(MF);
325
0
  }
326
327
0
  ++NumIdentifierLookupHits;
328
0
  return true;
329
0
}
330
331
0
bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) {
332
  // Look for the module in the global module index based on the module name.
333
0
  StringRef Name = File->ModuleName;
334
0
  llvm::StringMap<unsigned>::iterator Known = UnresolvedModules.find(Name);
335
0
  if (Known == UnresolvedModules.end()) {
336
0
    return true;
337
0
  }
338
339
  // Rectify this module with the global module index.
340
0
  ModuleInfo &Info = Modules[Known->second];
341
342
  //  If the size and modification time match what we expected, record this
343
  // module file.
344
0
  bool Failed = true;
345
0
  if (File->File.getSize() == Info.Size &&
346
0
      File->File.getModificationTime() == Info.ModTime) {
347
0
    Info.File = File;
348
0
    ModulesByFile[File] = Known->second;
349
350
0
    Failed = false;
351
0
  }
352
353
  // One way or another, we have resolved this module file.
354
0
  UnresolvedModules.erase(Known);
355
0
  return Failed;
356
0
}
357
358
0
void GlobalModuleIndex::printStats() {
359
0
  std::fprintf(stderr, "*** Global Module Index Statistics:\n");
360
0
  if (NumIdentifierLookups) {
361
0
    fprintf(stderr, "  %u / %u identifier lookups succeeded (%f%%)\n",
362
0
            NumIdentifierLookupHits, NumIdentifierLookups,
363
0
            (double)NumIdentifierLookupHits*100.0/NumIdentifierLookups);
364
0
  }
365
0
  std::fprintf(stderr, "\n");
366
0
}
367
368
0
LLVM_DUMP_METHOD void GlobalModuleIndex::dump() {
369
0
  llvm::errs() << "*** Global Module Index Dump:\n";
370
0
  llvm::errs() << "Module files:\n";
371
0
  for (auto &MI : Modules) {
372
0
    llvm::errs() << "** " << MI.FileName << "\n";
373
0
    if (MI.File)
374
0
      MI.File->dump();
375
0
    else
376
0
      llvm::errs() << "\n";
377
0
  }
378
0
  llvm::errs() << "\n";
379
0
}
380
381
//----------------------------------------------------------------------------//
382
// Global module index writer.
383
//----------------------------------------------------------------------------//
384
385
namespace {
386
  /// Provides information about a specific module file.
387
  struct ModuleFileInfo {
388
    /// The numberic ID for this module file.
389
    unsigned ID;
390
391
    /// The set of modules on which this module depends. Each entry is
392
    /// a module ID.
393
    SmallVector<unsigned, 4> Dependencies;
394
    ASTFileSignature Signature;
395
  };
396
397
  struct ImportedModuleFileInfo {
398
    off_t StoredSize;
399
    time_t StoredModTime;
400
    ASTFileSignature StoredSignature;
401
    ImportedModuleFileInfo(off_t Size, time_t ModTime, ASTFileSignature Sig)
402
0
        : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {}
403
  };
404
405
  /// Builder that generates the global module index file.
406
  class GlobalModuleIndexBuilder {
407
    FileManager &FileMgr;
408
    const PCHContainerReader &PCHContainerRdr;
409
410
    /// Mapping from files to module file information.
411
    using ModuleFilesMap = llvm::MapVector<FileEntryRef, ModuleFileInfo>;
412
413
    /// Information about each of the known module files.
414
    ModuleFilesMap ModuleFiles;
415
416
    /// Mapping from the imported module file to the imported
417
    /// information.
418
    using ImportedModuleFilesMap =
419
        std::multimap<FileEntryRef, ImportedModuleFileInfo>;
420
421
    /// Information about each importing of a module file.
422
    ImportedModuleFilesMap ImportedModuleFiles;
423
424
    /// Mapping from identifiers to the list of module file IDs that
425
    /// consider this identifier to be interesting.
426
    typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap;
427
428
    /// A mapping from all interesting identifiers to the set of module
429
    /// files in which those identifiers are considered interesting.
430
    InterestingIdentifierMap InterestingIdentifiers;
431
432
    /// Write the block-info block for the global module index file.
433
    void emitBlockInfoBlock(llvm::BitstreamWriter &Stream);
434
435
    /// Retrieve the module file information for the given file.
436
0
    ModuleFileInfo &getModuleFileInfo(FileEntryRef File) {
437
0
      auto Known = ModuleFiles.find(File);
438
0
      if (Known != ModuleFiles.end())
439
0
        return Known->second;
440
441
0
      unsigned NewID = ModuleFiles.size();
442
0
      ModuleFileInfo &Info = ModuleFiles[File];
443
0
      Info.ID = NewID;
444
0
      return Info;
445
0
    }
446
447
  public:
448
    explicit GlobalModuleIndexBuilder(
449
        FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr)
450
0
        : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {}
451
452
    /// Load the contents of the given module file into the builder.
453
    llvm::Error loadModuleFile(FileEntryRef File);
454
455
    /// Write the index to the given bitstream.
456
    /// \returns true if an error occurred, false otherwise.
457
    bool writeIndex(llvm::BitstreamWriter &Stream);
458
  };
459
}
460
461
static void emitBlockID(unsigned ID, const char *Name,
462
                        llvm::BitstreamWriter &Stream,
463
0
                        SmallVectorImpl<uint64_t> &Record) {
464
0
  Record.clear();
465
0
  Record.push_back(ID);
466
0
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
467
468
  // Emit the block name if present.
469
0
  if (!Name || Name[0] == 0) return;
470
0
  Record.clear();
471
0
  while (*Name)
472
0
    Record.push_back(*Name++);
473
0
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
474
0
}
475
476
static void emitRecordID(unsigned ID, const char *Name,
477
                         llvm::BitstreamWriter &Stream,
478
0
                         SmallVectorImpl<uint64_t> &Record) {
479
0
  Record.clear();
480
0
  Record.push_back(ID);
481
0
  while (*Name)
482
0
    Record.push_back(*Name++);
483
0
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
484
0
}
485
486
void
487
0
GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) {
488
0
  SmallVector<uint64_t, 64> Record;
489
0
  Stream.EnterBlockInfoBlock();
490
491
0
#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record)
492
0
#define RECORD(X) emitRecordID(X, #X, Stream, Record)
493
0
  BLOCK(GLOBAL_INDEX_BLOCK);
494
0
  RECORD(INDEX_METADATA);
495
0
  RECORD(MODULE);
496
0
  RECORD(IDENTIFIER_INDEX);
497
0
#undef RECORD
498
0
#undef BLOCK
499
500
0
  Stream.ExitBlock();
501
0
}
502
503
namespace {
504
  class InterestingASTIdentifierLookupTrait
505
    : public serialization::reader::ASTIdentifierLookupTraitBase {
506
507
  public:
508
    /// The identifier and whether it is "interesting".
509
    typedef std::pair<StringRef, bool> data_type;
510
511
    data_type ReadData(const internal_key_type& k,
512
                       const unsigned char* d,
513
0
                       unsigned DataLen) {
514
      // The first bit indicates whether this identifier is interesting.
515
      // That's all we care about.
516
0
      using namespace llvm::support;
517
0
      unsigned RawID =
518
0
          endian::readNext<uint32_t, llvm::endianness::little, unaligned>(d);
519
0
      bool IsInteresting = RawID & 0x01;
520
0
      return std::make_pair(k, IsInteresting);
521
0
    }
522
  };
523
}
524
525
0
llvm::Error GlobalModuleIndexBuilder::loadModuleFile(FileEntryRef File) {
526
  // Open the module file.
527
528
0
  auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true);
529
0
  if (!Buffer)
530
0
    return llvm::createStringError(Buffer.getError(),
531
0
                                   "failed getting buffer for module file");
532
533
  // Initialize the input stream
534
0
  llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer));
535
536
  // Sniff for the signature.
537
0
  for (unsigned char C : {'C', 'P', 'C', 'H'})
538
0
    if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = InStream.Read(8)) {
539
0
      if (Res.get() != C)
540
0
        return llvm::createStringError(std::errc::illegal_byte_sequence,
541
0
                                       "expected signature CPCH");
542
0
    } else
543
0
      return Res.takeError();
544
545
  // Record this module file and assign it a unique ID (if it doesn't have
546
  // one already).
547
0
  unsigned ID = getModuleFileInfo(File).ID;
548
549
  // Search for the blocks and records we care about.
550
0
  enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other;
551
0
  bool Done = false;
552
0
  while (!Done) {
553
0
    Expected<llvm::BitstreamEntry> MaybeEntry = InStream.advance();
554
0
    if (!MaybeEntry)
555
0
      return MaybeEntry.takeError();
556
0
    llvm::BitstreamEntry Entry = MaybeEntry.get();
557
558
0
    switch (Entry.Kind) {
559
0
    case llvm::BitstreamEntry::Error:
560
0
      Done = true;
561
0
      continue;
562
563
0
    case llvm::BitstreamEntry::Record:
564
      // In the 'other' state, just skip the record. We don't care.
565
0
      if (State == Other) {
566
0
        if (llvm::Expected<unsigned> Skipped = InStream.skipRecord(Entry.ID))
567
0
          continue;
568
0
        else
569
0
          return Skipped.takeError();
570
0
      }
571
572
      // Handle potentially-interesting records below.
573
0
      break;
574
575
0
    case llvm::BitstreamEntry::SubBlock:
576
0
      if (Entry.ID == CONTROL_BLOCK_ID) {
577
0
        if (llvm::Error Err = InStream.EnterSubBlock(CONTROL_BLOCK_ID))
578
0
          return Err;
579
580
        // Found the control block.
581
0
        State = ControlBlock;
582
0
        continue;
583
0
      }
584
585
0
      if (Entry.ID == AST_BLOCK_ID) {
586
0
        if (llvm::Error Err = InStream.EnterSubBlock(AST_BLOCK_ID))
587
0
          return Err;
588
589
        // Found the AST block.
590
0
        State = ASTBlock;
591
0
        continue;
592
0
      }
593
594
0
      if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) {
595
0
        if (llvm::Error Err = InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID))
596
0
          return Err;
597
598
        // Found the Diagnostic Options block.
599
0
        State = DiagnosticOptionsBlock;
600
0
        continue;
601
0
      }
602
603
0
      if (llvm::Error Err = InStream.SkipBlock())
604
0
        return Err;
605
606
0
      continue;
607
608
0
    case llvm::BitstreamEntry::EndBlock:
609
0
      State = Other;
610
0
      continue;
611
0
    }
612
613
    // Read the given record.
614
0
    SmallVector<uint64_t, 64> Record;
615
0
    StringRef Blob;
616
0
    Expected<unsigned> MaybeCode = InStream.readRecord(Entry.ID, Record, &Blob);
617
0
    if (!MaybeCode)
618
0
      return MaybeCode.takeError();
619
0
    unsigned Code = MaybeCode.get();
620
621
    // Handle module dependencies.
622
0
    if (State == ControlBlock && Code == IMPORTS) {
623
      // Load each of the imported PCH files.
624
0
      unsigned Idx = 0, N = Record.size();
625
0
      while (Idx < N) {
626
        // Read information about the AST file.
627
628
        // Skip the imported kind
629
0
        ++Idx;
630
631
        // Skip if it is standard C++ module
632
0
        ++Idx;
633
634
        // Skip the import location
635
0
        ++Idx;
636
637
        // Load stored size/modification time.
638
0
        off_t StoredSize = (off_t)Record[Idx++];
639
0
        time_t StoredModTime = (time_t)Record[Idx++];
640
641
        // Skip the stored signature.
642
        // FIXME: we could read the signature out of the import and validate it.
643
0
        auto FirstSignatureByte = Record.begin() + Idx;
644
0
        ASTFileSignature StoredSignature = ASTFileSignature::create(
645
0
            FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size);
646
0
        Idx += ASTFileSignature::size;
647
648
        // Skip the module name (currently this is only used for prebuilt
649
        // modules while here we are only dealing with cached).
650
0
        Idx += Record[Idx] + 1;
651
652
        // Retrieve the imported file name.
653
0
        unsigned Length = Record[Idx++];
654
0
        SmallString<128> ImportedFile(Record.begin() + Idx,
655
0
                                      Record.begin() + Idx + Length);
656
0
        Idx += Length;
657
658
        // Find the imported module file.
659
0
        auto DependsOnFile =
660
0
            FileMgr.getOptionalFileRef(ImportedFile, /*OpenFile=*/false,
661
0
                                       /*CacheFailure=*/false);
662
663
0
        if (!DependsOnFile)
664
0
          return llvm::createStringError(std::errc::bad_file_descriptor,
665
0
                                         "imported file \"%s\" not found",
666
0
                                         ImportedFile.c_str());
667
668
        // Save the information in ImportedModuleFileInfo so we can verify after
669
        // loading all pcms.
670
0
        ImportedModuleFiles.insert(std::make_pair(
671
0
            *DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime,
672
0
                                                   StoredSignature)));
673
674
        // Record the dependency.
675
0
        unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID;
676
0
        getModuleFileInfo(File).Dependencies.push_back(DependsOnID);
677
0
      }
678
679
0
      continue;
680
0
    }
681
682
    // Handle the identifier table
683
0
    if (State == ASTBlock && Code == IDENTIFIER_TABLE && Record[0] > 0) {
684
0
      typedef llvm::OnDiskIterableChainedHashTable<
685
0
          InterestingASTIdentifierLookupTrait> InterestingIdentifierTable;
686
0
      std::unique_ptr<InterestingIdentifierTable> Table(
687
0
          InterestingIdentifierTable::Create(
688
0
              (const unsigned char *)Blob.data() + Record[0],
689
0
              (const unsigned char *)Blob.data() + sizeof(uint32_t),
690
0
              (const unsigned char *)Blob.data()));
691
0
      for (InterestingIdentifierTable::data_iterator D = Table->data_begin(),
692
0
                                                     DEnd = Table->data_end();
693
0
           D != DEnd; ++D) {
694
0
        std::pair<StringRef, bool> Ident = *D;
695
0
        if (Ident.second)
696
0
          InterestingIdentifiers[Ident.first].push_back(ID);
697
0
        else
698
0
          (void)InterestingIdentifiers[Ident.first];
699
0
      }
700
0
    }
701
702
    // Get Signature.
703
0
    if (State == DiagnosticOptionsBlock && Code == SIGNATURE) {
704
0
      auto Signature = ASTFileSignature::create(Blob.begin(), Blob.end());
705
0
      assert(Signature != ASTFileSignature::createDummy() &&
706
0
             "Dummy AST file signature not backpatched in ASTWriter.");
707
0
      getModuleFileInfo(File).Signature = Signature;
708
0
    }
709
710
    // We don't care about this record.
711
0
  }
712
713
0
  return llvm::Error::success();
714
0
}
715
716
namespace {
717
718
/// Trait used to generate the identifier index as an on-disk hash
719
/// table.
720
class IdentifierIndexWriterTrait {
721
public:
722
  typedef StringRef key_type;
723
  typedef StringRef key_type_ref;
724
  typedef SmallVector<unsigned, 2> data_type;
725
  typedef const SmallVector<unsigned, 2> &data_type_ref;
726
  typedef unsigned hash_value_type;
727
  typedef unsigned offset_type;
728
729
0
  static hash_value_type ComputeHash(key_type_ref Key) {
730
0
    return llvm::djbHash(Key);
731
0
  }
732
733
  std::pair<unsigned,unsigned>
734
0
  EmitKeyDataLength(raw_ostream& Out, key_type_ref Key, data_type_ref Data) {
735
0
    using namespace llvm::support;
736
0
    endian::Writer LE(Out, llvm::endianness::little);
737
0
    unsigned KeyLen = Key.size();
738
0
    unsigned DataLen = Data.size() * 4;
739
0
    LE.write<uint16_t>(KeyLen);
740
0
    LE.write<uint16_t>(DataLen);
741
0
    return std::make_pair(KeyLen, DataLen);
742
0
  }
743
744
0
  void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
745
0
    Out.write(Key.data(), KeyLen);
746
0
  }
747
748
  void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
749
0
                unsigned DataLen) {
750
0
    using namespace llvm::support;
751
0
    for (unsigned I = 0, N = Data.size(); I != N; ++I)
752
0
      endian::write<uint32_t>(Out, Data[I], llvm::endianness::little);
753
0
  }
754
};
755
756
}
757
758
0
bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
759
0
  for (auto MapEntry : ImportedModuleFiles) {
760
0
    auto File = MapEntry.first;
761
0
    ImportedModuleFileInfo &Info = MapEntry.second;
762
0
    if (getModuleFileInfo(File).Signature) {
763
0
      if (getModuleFileInfo(File).Signature != Info.StoredSignature)
764
        // Verify Signature.
765
0
        return true;
766
0
    } else if (Info.StoredSize != File.getSize() ||
767
0
               Info.StoredModTime != File.getModificationTime())
768
      // Verify Size and ModTime.
769
0
      return true;
770
0
  }
771
772
0
  using namespace llvm;
773
0
  llvm::TimeTraceScope TimeScope("Module WriteIndex");
774
775
  // Emit the file header.
776
0
  Stream.Emit((unsigned)'B', 8);
777
0
  Stream.Emit((unsigned)'C', 8);
778
0
  Stream.Emit((unsigned)'G', 8);
779
0
  Stream.Emit((unsigned)'I', 8);
780
781
  // Write the block-info block, which describes the records in this bitcode
782
  // file.
783
0
  emitBlockInfoBlock(Stream);
784
785
0
  Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3);
786
787
  // Write the metadata.
788
0
  SmallVector<uint64_t, 2> Record;
789
0
  Record.push_back(CurrentVersion);
790
0
  Stream.EmitRecord(INDEX_METADATA, Record);
791
792
  // Write the set of known module files.
793
0
  for (ModuleFilesMap::iterator M = ModuleFiles.begin(),
794
0
                                MEnd = ModuleFiles.end();
795
0
       M != MEnd; ++M) {
796
0
    Record.clear();
797
0
    Record.push_back(M->second.ID);
798
0
    Record.push_back(M->first.getSize());
799
0
    Record.push_back(M->first.getModificationTime());
800
801
    // File name
802
0
    StringRef Name(M->first.getName());
803
0
    Record.push_back(Name.size());
804
0
    Record.append(Name.begin(), Name.end());
805
806
    // Dependencies
807
0
    Record.push_back(M->second.Dependencies.size());
808
0
    Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end());
809
0
    Stream.EmitRecord(MODULE, Record);
810
0
  }
811
812
  // Write the identifier -> module file mapping.
813
0
  {
814
0
    llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator;
815
0
    IdentifierIndexWriterTrait Trait;
816
817
    // Populate the hash table.
818
0
    for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(),
819
0
                                            IEnd = InterestingIdentifiers.end();
820
0
         I != IEnd; ++I) {
821
0
      Generator.insert(I->first(), I->second, Trait);
822
0
    }
823
824
    // Create the on-disk hash table in a buffer.
825
0
    SmallString<4096> IdentifierTable;
826
0
    uint32_t BucketOffset;
827
0
    {
828
0
      using namespace llvm::support;
829
0
      llvm::raw_svector_ostream Out(IdentifierTable);
830
      // Make sure that no bucket is at offset 0
831
0
      endian::write<uint32_t>(Out, 0, llvm::endianness::little);
832
0
      BucketOffset = Generator.Emit(Out, Trait);
833
0
    }
834
835
    // Create a blob abbreviation
836
0
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
837
0
    Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX));
838
0
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
839
0
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
840
0
    unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
841
842
    // Write the identifier table
843
0
    uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset};
844
0
    Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);
845
0
  }
846
847
0
  Stream.ExitBlock();
848
0
  return false;
849
0
}
850
851
llvm::Error
852
GlobalModuleIndex::writeIndex(FileManager &FileMgr,
853
                              const PCHContainerReader &PCHContainerRdr,
854
0
                              StringRef Path) {
855
0
  llvm::SmallString<128> IndexPath;
856
0
  IndexPath += Path;
857
0
  llvm::sys::path::append(IndexPath, IndexFileName);
858
859
  // Coordinate building the global index file with other processes that might
860
  // try to do the same.
861
0
  llvm::LockFileManager Locked(IndexPath);
862
0
  switch (Locked) {
863
0
  case llvm::LockFileManager::LFS_Error:
864
0
    return llvm::createStringError(std::errc::io_error, "LFS error");
865
866
0
  case llvm::LockFileManager::LFS_Owned:
867
    // We're responsible for building the index ourselves. Do so below.
868
0
    break;
869
870
0
  case llvm::LockFileManager::LFS_Shared:
871
    // Someone else is responsible for building the index. We don't care
872
    // when they finish, so we're done.
873
0
    return llvm::createStringError(std::errc::device_or_resource_busy,
874
0
                                   "someone else is building the index");
875
0
  }
876
877
  // The module index builder.
878
0
  GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerRdr);
879
880
  // Load each of the module files.
881
0
  std::error_code EC;
882
0
  for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd;
883
0
       D != DEnd && !EC;
884
0
       D.increment(EC)) {
885
    // If this isn't a module file, we don't care.
886
0
    if (llvm::sys::path::extension(D->path()) != ".pcm") {
887
      // ... unless it's a .pcm.lock file, which indicates that someone is
888
      // in the process of rebuilding a module. They'll rebuild the index
889
      // at the end of that translation unit, so we don't have to.
890
0
      if (llvm::sys::path::extension(D->path()) == ".pcm.lock")
891
0
        return llvm::createStringError(std::errc::device_or_resource_busy,
892
0
                                       "someone else is building the index");
893
894
0
      continue;
895
0
    }
896
897
    // If we can't find the module file, skip it.
898
0
    auto ModuleFile = FileMgr.getOptionalFileRef(D->path());
899
0
    if (!ModuleFile)
900
0
      continue;
901
902
    // Load this module file.
903
0
    if (llvm::Error Err = Builder.loadModuleFile(*ModuleFile))
904
0
      return Err;
905
0
  }
906
907
  // The output buffer, into which the global index will be written.
908
0
  SmallString<16> OutputBuffer;
909
0
  {
910
0
    llvm::BitstreamWriter OutputStream(OutputBuffer);
911
0
    if (Builder.writeIndex(OutputStream))
912
0
      return llvm::createStringError(std::errc::io_error,
913
0
                                     "failed writing index");
914
0
  }
915
916
0
  return llvm::writeToOutput(IndexPath, [&OutputBuffer](llvm::raw_ostream &OS) {
917
0
    OS << OutputBuffer;
918
0
    return llvm::Error::success();
919
0
  });
920
0
}
921
922
namespace {
923
  class GlobalIndexIdentifierIterator : public IdentifierIterator {
924
    /// The current position within the identifier lookup table.
925
    IdentifierIndexTable::key_iterator Current;
926
927
    /// The end position within the identifier lookup table.
928
    IdentifierIndexTable::key_iterator End;
929
930
  public:
931
0
    explicit GlobalIndexIdentifierIterator(IdentifierIndexTable &Idx) {
932
0
      Current = Idx.key_begin();
933
0
      End = Idx.key_end();
934
0
    }
935
936
0
    StringRef Next() override {
937
0
      if (Current == End)
938
0
        return StringRef();
939
940
0
      StringRef Result = *Current;
941
0
      ++Current;
942
0
      return Result;
943
0
    }
944
  };
945
}
946
947
0
IdentifierIterator *GlobalModuleIndex::createIdentifierIterator() const {
948
0
  IdentifierIndexTable &Table =
949
0
    *static_cast<IdentifierIndexTable *>(IdentifierIndex);
950
0
  return new GlobalIndexIdentifierIterator(Table);
951
0
}