annotate clang/lib/Serialization/GlobalModuleIndex.cpp @ 266:00f31e85ec16 default tip

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