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