ModuleManager.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. //===--- 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"
  15. #include "llvm/Support/MemoryBuffer.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. #include "llvm/Support/system_error.h"
  18. #ifndef NDEBUG
  19. #include "llvm/Support/GraphWriter.h"
  20. #endif
  21. using namespace clang;
  22. using namespace serialization;
  23. ModuleFile *ModuleManager::lookup(StringRef Name) {
  24. const FileEntry *Entry = FileMgr.getFile(Name);
  25. return Modules[Entry];
  26. }
  27. llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
  28. const FileEntry *Entry = FileMgr.getFile(Name);
  29. return InMemoryBuffers[Entry];
  30. }
  31. std::pair<ModuleFile *, bool>
  32. ModuleManager::addModule(StringRef FileName, ModuleKind Type,
  33. ModuleFile *ImportedBy, std::string &ErrorStr) {
  34. const FileEntry *Entry = FileMgr.getFile(FileName);
  35. if (!Entry && FileName != "-") {
  36. ErrorStr = "file not found";
  37. return std::make_pair(static_cast<ModuleFile*>(0), false);
  38. }
  39. // Check whether we already loaded this module, before
  40. ModuleFile *&ModuleEntry = Modules[Entry];
  41. bool NewModule = false;
  42. if (!ModuleEntry) {
  43. // Allocate a new module.
  44. ModuleFile *New = new ModuleFile(Type);
  45. New->FileName = FileName.str();
  46. Chain.push_back(New);
  47. NewModule = true;
  48. ModuleEntry = New;
  49. // Load the contents of the module
  50. if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) {
  51. // The buffer was already provided for us.
  52. assert(Buffer && "Passed null buffer");
  53. New->Buffer.reset(Buffer);
  54. } else {
  55. // Open the AST file.
  56. llvm::error_code ec;
  57. if (FileName == "-") {
  58. ec = llvm::MemoryBuffer::getSTDIN(New->Buffer);
  59. if (ec)
  60. ErrorStr = ec.message();
  61. } else
  62. New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr));
  63. if (!New->Buffer)
  64. return std::make_pair(static_cast<ModuleFile*>(0), false);
  65. }
  66. // Initialize the stream
  67. New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
  68. (const unsigned char *)New->Buffer->getBufferEnd()); }
  69. if (ImportedBy) {
  70. ModuleEntry->ImportedBy.insert(ImportedBy);
  71. ImportedBy->Imports.insert(ModuleEntry);
  72. } else {
  73. ModuleEntry->DirectlyImported = true;
  74. }
  75. return std::make_pair(ModuleEntry, NewModule);
  76. }
  77. void ModuleManager::addInMemoryBuffer(StringRef FileName,
  78. llvm::MemoryBuffer *Buffer) {
  79. const FileEntry *Entry = FileMgr.getVirtualFile(FileName,
  80. Buffer->getBufferSize(), 0);
  81. InMemoryBuffers[Entry] = Buffer;
  82. }
  83. ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { }
  84. ModuleManager::~ModuleManager() {
  85. for (unsigned i = 0, e = Chain.size(); i != e; ++i)
  86. delete Chain[e - i - 1];
  87. }
  88. void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
  89. void *UserData) {
  90. unsigned N = size();
  91. // Record the number of incoming edges for each module. When we
  92. // encounter a module with no incoming edges, push it into the queue
  93. // to seed the queue.
  94. SmallVector<ModuleFile *, 4> Queue;
  95. Queue.reserve(N);
  96. llvm::DenseMap<ModuleFile *, unsigned> UnusedIncomingEdges;
  97. for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) {
  98. if (unsigned Size = (*M)->ImportedBy.size())
  99. UnusedIncomingEdges[*M] = Size;
  100. else
  101. Queue.push_back(*M);
  102. }
  103. llvm::SmallPtrSet<ModuleFile *, 4> Skipped;
  104. unsigned QueueStart = 0;
  105. while (QueueStart < Queue.size()) {
  106. ModuleFile *CurrentModule = Queue[QueueStart++];
  107. // Check whether this module should be skipped.
  108. if (Skipped.count(CurrentModule))
  109. continue;
  110. if (Visitor(*CurrentModule, UserData)) {
  111. // The visitor has requested that cut off visitation of any
  112. // module that the current module depends on. To indicate this
  113. // behavior, we mark all of the reachable modules as having N
  114. // incoming edges (which is impossible otherwise).
  115. SmallVector<ModuleFile *, 4> Stack;
  116. Stack.push_back(CurrentModule);
  117. Skipped.insert(CurrentModule);
  118. while (!Stack.empty()) {
  119. ModuleFile *NextModule = Stack.back();
  120. Stack.pop_back();
  121. // For any module that this module depends on, push it on the
  122. // stack (if it hasn't already been marked as visited).
  123. for (llvm::SetVector<ModuleFile *>::iterator
  124. M = NextModule->Imports.begin(),
  125. MEnd = NextModule->Imports.end();
  126. M != MEnd; ++M) {
  127. if (Skipped.insert(*M))
  128. Stack.push_back(*M);
  129. }
  130. }
  131. continue;
  132. }
  133. // For any module that this module depends on, push it on the
  134. // stack (if it hasn't already been marked as visited).
  135. for (llvm::SetVector<ModuleFile *>::iterator M = CurrentModule->Imports.begin(),
  136. MEnd = CurrentModule->Imports.end();
  137. M != MEnd; ++M) {
  138. // Remove our current module as an impediment to visiting the
  139. // module we depend on. If we were the last unvisited module
  140. // that depends on this particular module, push it into the
  141. // queue to be visited.
  142. unsigned &NumUnusedEdges = UnusedIncomingEdges[*M];
  143. if (NumUnusedEdges && (--NumUnusedEdges == 0))
  144. Queue.push_back(*M);
  145. }
  146. }
  147. }
  148. /// \brief Perform a depth-first visit of the current module.
  149. static bool visitDepthFirst(ModuleFile &M,
  150. bool (*Visitor)(ModuleFile &M, bool Preorder,
  151. void *UserData),
  152. void *UserData,
  153. llvm::SmallPtrSet<ModuleFile *, 4> &Visited) {
  154. // Preorder visitation
  155. if (Visitor(M, /*Preorder=*/true, UserData))
  156. return true;
  157. // Visit children
  158. for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
  159. IMEnd = M.Imports.end();
  160. IM != IMEnd; ++IM) {
  161. if (!Visited.insert(*IM))
  162. continue;
  163. if (visitDepthFirst(**IM, Visitor, UserData, Visited))
  164. return true;
  165. }
  166. // Postorder visitation
  167. return Visitor(M, /*Preorder=*/false, UserData);
  168. }
  169. void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder,
  170. void *UserData),
  171. void *UserData) {
  172. llvm::SmallPtrSet<ModuleFile *, 4> Visited;
  173. for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
  174. if (!Visited.insert(Chain[I]))
  175. continue;
  176. if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
  177. return;
  178. }
  179. }
  180. #ifndef NDEBUG
  181. namespace llvm {
  182. template<>
  183. struct GraphTraits<ModuleManager> {
  184. typedef ModuleFile NodeType;
  185. typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType;
  186. typedef ModuleManager::ModuleConstIterator nodes_iterator;
  187. static ChildIteratorType child_begin(NodeType *Node) {
  188. return Node->Imports.begin();
  189. }
  190. static ChildIteratorType child_end(NodeType *Node) {
  191. return Node->Imports.end();
  192. }
  193. static nodes_iterator nodes_begin(const ModuleManager &Manager) {
  194. return Manager.begin();
  195. }
  196. static nodes_iterator nodes_end(const ModuleManager &Manager) {
  197. return Manager.end();
  198. }
  199. };
  200. template<>
  201. struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits {
  202. explicit DOTGraphTraits(bool IsSimple = false)
  203. : DefaultDOTGraphTraits(IsSimple) { }
  204. static bool renderGraphFromBottomUp() {
  205. return true;
  206. }
  207. std::string getNodeLabel(ModuleFile *M, const ModuleManager&) {
  208. return llvm::sys::path::stem(M->FileName);
  209. }
  210. };
  211. }
  212. void ModuleManager::viewGraph() {
  213. llvm::ViewGraph(*this, "Modules");
  214. }
  215. #endif