blob: b9f4d888f30aca0225bf4453a1b835034a003f81 [file] [log] [blame]
Douglas Gregor98339b92011-08-25 20:47:51 +00001//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the ModuleManager class, which manages a set of loaded
11// modules for the ASTReader.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/Serialization/ModuleManager.h"
Douglas Gregor188bdcd2013-01-25 23:32:03 +000015#include "clang/Serialization/GlobalModuleIndex.h"
Douglas Gregor98339b92011-08-25 20:47:51 +000016#include "llvm/Support/MemoryBuffer.h"
17#include "llvm/Support/raw_ostream.h"
18#include "llvm/Support/system_error.h"
19
Douglas Gregor2492c892011-10-11 19:27:55 +000020#ifndef NDEBUG
21#include "llvm/Support/GraphWriter.h"
22#endif
23
Douglas Gregor98339b92011-08-25 20:47:51 +000024using namespace clang;
25using namespace serialization;
26
Douglas Gregor1a4761e2011-11-30 23:21:26 +000027ModuleFile *ModuleManager::lookup(StringRef Name) {
Douglas Gregorea14a872013-02-08 21:27:45 +000028 const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
29 /*cacheFailure=*/false);
Douglas Gregor98339b92011-08-25 20:47:51 +000030 return Modules[Entry];
31}
32
33llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
Douglas Gregorea14a872013-02-08 21:27:45 +000034 const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
35 /*cacheFailure=*/false);
Douglas Gregor98339b92011-08-25 20:47:51 +000036 return InMemoryBuffers[Entry];
37}
38
Douglas Gregor1a4761e2011-11-30 23:21:26 +000039std::pair<ModuleFile *, bool>
Douglas Gregor87e2cfc2012-11-30 19:28:05 +000040ModuleManager::addModule(StringRef FileName, ModuleKind Type,
41 SourceLocation ImportLoc, ModuleFile *ImportedBy,
42 unsigned Generation, std::string &ErrorStr) {
Douglas Gregorea14a872013-02-08 21:27:45 +000043 const FileEntry *Entry = FileMgr.getFile(FileName, /*openFile=*/false,
44 /*cacheFailure=*/false);
Douglas Gregor98339b92011-08-25 20:47:51 +000045 if (!Entry && FileName != "-") {
46 ErrorStr = "file not found";
Douglas Gregor1a4761e2011-11-30 23:21:26 +000047 return std::make_pair(static_cast<ModuleFile*>(0), false);
Douglas Gregor98339b92011-08-25 20:47:51 +000048 }
49
50 // Check whether we already loaded this module, before
Douglas Gregor1a4761e2011-11-30 23:21:26 +000051 ModuleFile *&ModuleEntry = Modules[Entry];
Douglas Gregor98339b92011-08-25 20:47:51 +000052 bool NewModule = false;
53 if (!ModuleEntry) {
54 // Allocate a new module.
Douglas Gregor057df202012-01-18 20:56:22 +000055 ModuleFile *New = new ModuleFile(Type, Generation);
Douglas Gregorcc71dbe2013-01-21 20:07:12 +000056 New->Index = Chain.size();
Douglas Gregor98339b92011-08-25 20:47:51 +000057 New->FileName = FileName.str();
Argyrios Kyrtzidisd64c26f2012-10-03 01:58:42 +000058 New->File = Entry;
Douglas Gregor87e2cfc2012-11-30 19:28:05 +000059 New->ImportLoc = ImportLoc;
Douglas Gregor98339b92011-08-25 20:47:51 +000060 Chain.push_back(New);
61 NewModule = true;
62 ModuleEntry = New;
Douglas Gregor87e2cfc2012-11-30 19:28:05 +000063
Douglas Gregor98339b92011-08-25 20:47:51 +000064 // Load the contents of the module
65 if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) {
66 // The buffer was already provided for us.
67 assert(Buffer && "Passed null buffer");
68 New->Buffer.reset(Buffer);
69 } else {
70 // Open the AST file.
71 llvm::error_code ec;
72 if (FileName == "-") {
73 ec = llvm::MemoryBuffer::getSTDIN(New->Buffer);
74 if (ec)
75 ErrorStr = ec.message();
76 } else
77 New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr));
78
79 if (!New->Buffer)
Douglas Gregor1a4761e2011-11-30 23:21:26 +000080 return std::make_pair(static_cast<ModuleFile*>(0), false);
Douglas Gregor98339b92011-08-25 20:47:51 +000081 }
82
83 // Initialize the stream
84 New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
85 (const unsigned char *)New->Buffer->getBufferEnd()); }
86
87 if (ImportedBy) {
88 ModuleEntry->ImportedBy.insert(ImportedBy);
89 ImportedBy->Imports.insert(ModuleEntry);
90 } else {
Douglas Gregor87e2cfc2012-11-30 19:28:05 +000091 if (!ModuleEntry->DirectlyImported)
92 ModuleEntry->ImportLoc = ImportLoc;
93
Douglas Gregor98339b92011-08-25 20:47:51 +000094 ModuleEntry->DirectlyImported = true;
95 }
96
97 return std::make_pair(ModuleEntry, NewModule);
98}
99
Douglas Gregor7cdd2812012-11-07 17:46:15 +0000100namespace {
101 /// \brief Predicate that checks whether a module file occurs within
102 /// the given set.
103 class IsInModuleFileSet : public std::unary_function<ModuleFile *, bool> {
104 llvm::SmallPtrSet<ModuleFile *, 4> &Removed;
105
106 public:
107 IsInModuleFileSet(llvm::SmallPtrSet<ModuleFile *, 4> &Removed)
108 : Removed(Removed) { }
109
110 bool operator()(ModuleFile *MF) const {
111 return Removed.count(MF);
112 }
113 };
114}
115
116void ModuleManager::removeModules(ModuleIterator first, ModuleIterator last) {
117 if (first == last)
118 return;
119
120 // Collect the set of module file pointers that we'll be removing.
121 llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
122
123 // Remove any references to the now-destroyed modules.
124 IsInModuleFileSet checkInSet(victimSet);
125 for (unsigned i = 0, n = Chain.size(); i != n; ++i) {
126 Chain[i]->ImportedBy.remove_if(checkInSet);
127 }
128
129 // Delete the modules and erase them from the various structures.
130 for (ModuleIterator victim = first; victim != last; ++victim) {
131 Modules.erase((*victim)->File);
132 delete *victim;
133 }
134
135 // Remove the modules from the chain.
136 Chain.erase(first, last);
137}
138
Douglas Gregor98339b92011-08-25 20:47:51 +0000139void ModuleManager::addInMemoryBuffer(StringRef FileName,
140 llvm::MemoryBuffer *Buffer) {
141
142 const FileEntry *Entry = FileMgr.getVirtualFile(FileName,
143 Buffer->getBufferSize(), 0);
144 InMemoryBuffers[Entry] = Buffer;
145}
146
Douglas Gregor188bdcd2013-01-25 23:32:03 +0000147void ModuleManager::updateModulesInCommonWithGlobalIndex() {
148 ModulesInCommonWithGlobalIndex.clear();
149
150 if (!GlobalIndex)
151 return;
152
153 // Collect the set of modules known to the global index.
154 SmallVector<const FileEntry *, 16> KnownModules;
155 GlobalIndex->getKnownModules(KnownModules);
156
157 // Map those modules to AST files known to the module manager.
158 for (unsigned I = 0, N = KnownModules.size(); I != N; ++I) {
159 llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
160 = Modules.find(KnownModules[I]);
161 if (Known == Modules.end())
162 continue;
163
164 ModulesInCommonWithGlobalIndex.push_back(Known->second);
165 }
166}
167
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000168ModuleManager::VisitState *ModuleManager::allocateVisitState() {
169 // Fast path: if we have a cached state, use it.
170 if (FirstVisitState) {
171 VisitState *Result = FirstVisitState;
172 FirstVisitState = FirstVisitState->NextState;
173 Result->NextState = 0;
174 return Result;
175 }
176
177 // Allocate and return a new state.
178 return new VisitState(size());
179}
180
181void ModuleManager::returnVisitState(VisitState *State) {
182 assert(State->NextState == 0 && "Visited state is in list?");
183 State->NextState = FirstVisitState;
184 FirstVisitState = State;
185}
186
Douglas Gregor188bdcd2013-01-25 23:32:03 +0000187void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
188 GlobalIndex = Index;
189 updateModulesInCommonWithGlobalIndex();
190}
191
192ModuleManager::ModuleManager(FileManager &FileMgr)
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000193 : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(0) { }
Douglas Gregor98339b92011-08-25 20:47:51 +0000194
195ModuleManager::~ModuleManager() {
196 for (unsigned i = 0, e = Chain.size(); i != e; ++i)
197 delete Chain[e - i - 1];
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000198 delete FirstVisitState;
Douglas Gregor98339b92011-08-25 20:47:51 +0000199}
200
Douglas Gregor188bdcd2013-01-25 23:32:03 +0000201void
202ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
203 void *UserData,
204 llvm::SmallPtrSet<const FileEntry *, 4> *ModuleFilesHit) {
205 // If the visitation order vector is the wrong size, recompute the order.
Douglas Gregord07865b2013-01-25 22:25:23 +0000206 if (VisitOrder.size() != Chain.size()) {
207 unsigned N = size();
208 VisitOrder.clear();
209 VisitOrder.reserve(N);
210
211 // Record the number of incoming edges for each module. When we
212 // encounter a module with no incoming edges, push it into the queue
213 // to seed the queue.
214 SmallVector<ModuleFile *, 4> Queue;
215 Queue.reserve(N);
216 llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
217 UnusedIncomingEdges.reserve(size());
218 for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) {
219 if (unsigned Size = (*M)->ImportedBy.size())
220 UnusedIncomingEdges.push_back(Size);
221 else {
222 UnusedIncomingEdges.push_back(0);
223 Queue.push_back(*M);
224 }
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000225 }
Douglas Gregord07865b2013-01-25 22:25:23 +0000226
227 // Traverse the graph, making sure to visit a module before visiting any
228 // of its dependencies.
229 unsigned QueueStart = 0;
230 while (QueueStart < Queue.size()) {
231 ModuleFile *CurrentModule = Queue[QueueStart++];
232 VisitOrder.push_back(CurrentModule);
233
234 // For any module that this module depends on, push it on the
235 // stack (if it hasn't already been marked as visited).
236 for (llvm::SetVector<ModuleFile *>::iterator
237 M = CurrentModule->Imports.begin(),
238 MEnd = CurrentModule->Imports.end();
239 M != MEnd; ++M) {
240 // Remove our current module as an impediment to visiting the
241 // module we depend on. If we were the last unvisited module
242 // that depends on this particular module, push it into the
243 // queue to be visited.
244 unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index];
245 if (NumUnusedEdges && (--NumUnusedEdges == 0))
246 Queue.push_back(*M);
247 }
248 }
249
250 assert(VisitOrder.size() == N && "Visitation order is wrong?");
Douglas Gregor188bdcd2013-01-25 23:32:03 +0000251
252 // We may need to update the set of modules we have in common with the
253 // global module index, since modules could have been added to the module
254 // manager since we loaded the global module index.
255 updateModulesInCommonWithGlobalIndex();
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000256
257 delete FirstVisitState;
258 FirstVisitState = 0;
Douglas Gregor98339b92011-08-25 20:47:51 +0000259 }
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000260
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000261 VisitState *State = allocateVisitState();
262 unsigned VisitNumber = State->NextVisitNumber++;
Douglas Gregord07865b2013-01-25 22:25:23 +0000263
Douglas Gregor188bdcd2013-01-25 23:32:03 +0000264 // If the caller has provided us with a hit-set that came from the global
265 // module index, mark every module file in common with the global module
266 // index that is *not* in that set as 'visited'.
267 if (ModuleFilesHit && !ModulesInCommonWithGlobalIndex.empty()) {
268 for (unsigned I = 0, N = ModulesInCommonWithGlobalIndex.size(); I != N; ++I)
269 {
270 ModuleFile *M = ModulesInCommonWithGlobalIndex[I];
271 if (!ModuleFilesHit->count(M->File))
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000272 State->VisitNumber[M->Index] = VisitNumber;
Douglas Gregor188bdcd2013-01-25 23:32:03 +0000273 }
274 }
275
Douglas Gregord07865b2013-01-25 22:25:23 +0000276 for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) {
277 ModuleFile *CurrentModule = VisitOrder[I];
278 // Should we skip this module file?
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000279 if (State->VisitNumber[CurrentModule->Index] == VisitNumber)
Douglas Gregor98339b92011-08-25 20:47:51 +0000280 continue;
Douglas Gregord07865b2013-01-25 22:25:23 +0000281
282 // Visit the module.
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000283 assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
284 State->VisitNumber[CurrentModule->Index] = VisitNumber;
Douglas Gregord07865b2013-01-25 22:25:23 +0000285 if (!Visitor(*CurrentModule, UserData))
286 continue;
287
288 // The visitor has requested that cut off visitation of any
289 // module that the current module depends on. To indicate this
290 // behavior, we mark all of the reachable modules as having been visited.
291 ModuleFile *NextModule = CurrentModule;
Douglas Gregord07865b2013-01-25 22:25:23 +0000292 do {
293 // For any module that this module depends on, push it on the
294 // stack (if it hasn't already been marked as visited).
295 for (llvm::SetVector<ModuleFile *>::iterator
296 M = NextModule->Imports.begin(),
297 MEnd = NextModule->Imports.end();
298 M != MEnd; ++M) {
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000299 if (State->VisitNumber[(*M)->Index] != VisitNumber) {
300 State->Stack.push_back(*M);
301 State->VisitNumber[(*M)->Index] = VisitNumber;
Douglas Gregor98339b92011-08-25 20:47:51 +0000302 }
303 }
Douglas Gregord07865b2013-01-25 22:25:23 +0000304
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000305 if (State->Stack.empty())
Douglas Gregord07865b2013-01-25 22:25:23 +0000306 break;
307
308 // Pop the next module off the stack.
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000309 NextModule = State->Stack.back();
310 State->Stack.pop_back();
Douglas Gregord07865b2013-01-25 22:25:23 +0000311 } while (true);
Douglas Gregor98339b92011-08-25 20:47:51 +0000312 }
Douglas Gregord3cf5fb2013-01-28 16:46:33 +0000313
314 returnVisitState(State);
Douglas Gregor98339b92011-08-25 20:47:51 +0000315}
316
317/// \brief Perform a depth-first visit of the current module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000318static bool visitDepthFirst(ModuleFile &M,
319 bool (*Visitor)(ModuleFile &M, bool Preorder,
Douglas Gregor98339b92011-08-25 20:47:51 +0000320 void *UserData),
321 void *UserData,
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000322 SmallVectorImpl<bool> &Visited) {
Douglas Gregor98339b92011-08-25 20:47:51 +0000323 // Preorder visitation
324 if (Visitor(M, /*Preorder=*/true, UserData))
325 return true;
326
327 // Visit children
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000328 for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000329 IMEnd = M.Imports.end();
Douglas Gregor98339b92011-08-25 20:47:51 +0000330 IM != IMEnd; ++IM) {
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000331 if (Visited[(*IM)->Index])
Douglas Gregor98339b92011-08-25 20:47:51 +0000332 continue;
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000333 Visited[(*IM)->Index] = true;
334
Douglas Gregor98339b92011-08-25 20:47:51 +0000335 if (visitDepthFirst(**IM, Visitor, UserData, Visited))
336 return true;
337 }
338
339 // Postorder visitation
340 return Visitor(M, /*Preorder=*/false, UserData);
341}
342
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000343void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder,
Douglas Gregor98339b92011-08-25 20:47:51 +0000344 void *UserData),
345 void *UserData) {
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000346 SmallVector<bool, 16> Visited(size(), false);
Douglas Gregor98339b92011-08-25 20:47:51 +0000347 for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000348 if (Visited[Chain[I]->Index])
Douglas Gregor98339b92011-08-25 20:47:51 +0000349 continue;
Douglas Gregorcc71dbe2013-01-21 20:07:12 +0000350 Visited[Chain[I]->Index] = true;
351
Douglas Gregor98339b92011-08-25 20:47:51 +0000352 if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
353 return;
354 }
355}
Douglas Gregor2492c892011-10-11 19:27:55 +0000356
357#ifndef NDEBUG
358namespace llvm {
359 template<>
360 struct GraphTraits<ModuleManager> {
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000361 typedef ModuleFile NodeType;
362 typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType;
Douglas Gregor2492c892011-10-11 19:27:55 +0000363 typedef ModuleManager::ModuleConstIterator nodes_iterator;
364
365 static ChildIteratorType child_begin(NodeType *Node) {
366 return Node->Imports.begin();
367 }
368
369 static ChildIteratorType child_end(NodeType *Node) {
370 return Node->Imports.end();
371 }
372
373 static nodes_iterator nodes_begin(const ModuleManager &Manager) {
374 return Manager.begin();
375 }
376
377 static nodes_iterator nodes_end(const ModuleManager &Manager) {
378 return Manager.end();
379 }
380 };
381
382 template<>
383 struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
384 explicit DOTGraphTraits(bool IsSimple = false)
385 : DefaultDOTGraphTraits(IsSimple) { }
386
387 static bool renderGraphFromBottomUp() {
388 return true;
389 }
390
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000391 std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
Douglas Gregor2492c892011-10-11 19:27:55 +0000392 return llvm::sys::path::stem(M->FileName);
393 }
394 };
395}
396
397void ModuleManager::viewGraph() {
398 llvm::ViewGraph(*this, "Modules");
399}
400#endif