clang API Documentation
00001 //===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the ModuleManager class, which manages a set of loaded 00011 // modules for the ASTReader. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 #include "clang/Serialization/ModuleManager.h" 00015 #include "llvm/Support/MemoryBuffer.h" 00016 #include "llvm/Support/raw_ostream.h" 00017 #include "llvm/Support/system_error.h" 00018 00019 #ifndef NDEBUG 00020 #include "llvm/Support/GraphWriter.h" 00021 #endif 00022 00023 using namespace clang; 00024 using namespace serialization; 00025 00026 ModuleFile *ModuleManager::lookup(StringRef Name) { 00027 const FileEntry *Entry = FileMgr.getFile(Name); 00028 return Modules[Entry]; 00029 } 00030 00031 llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { 00032 const FileEntry *Entry = FileMgr.getFile(Name); 00033 return InMemoryBuffers[Entry]; 00034 } 00035 00036 std::pair<ModuleFile *, bool> 00037 ModuleManager::addModule(StringRef FileName, ModuleKind Type, 00038 ModuleFile *ImportedBy, unsigned Generation, 00039 std::string &ErrorStr) { 00040 const FileEntry *Entry = FileMgr.getFile(FileName); 00041 if (!Entry && FileName != "-") { 00042 ErrorStr = "file not found"; 00043 return std::make_pair(static_cast<ModuleFile*>(0), false); 00044 } 00045 00046 // Check whether we already loaded this module, before 00047 ModuleFile *&ModuleEntry = Modules[Entry]; 00048 bool NewModule = false; 00049 if (!ModuleEntry) { 00050 // Allocate a new module. 00051 ModuleFile *New = new ModuleFile(Type, Generation); 00052 New->FileName = FileName.str(); 00053 Chain.push_back(New); 00054 NewModule = true; 00055 ModuleEntry = New; 00056 00057 // Load the contents of the module 00058 if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { 00059 // The buffer was already provided for us. 00060 assert(Buffer && "Passed null buffer"); 00061 New->Buffer.reset(Buffer); 00062 } else { 00063 // Open the AST file. 00064 llvm::error_code ec; 00065 if (FileName == "-") { 00066 ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); 00067 if (ec) 00068 ErrorStr = ec.message(); 00069 } else 00070 New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); 00071 00072 if (!New->Buffer) 00073 return std::make_pair(static_cast<ModuleFile*>(0), false); 00074 } 00075 00076 // Initialize the stream 00077 New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), 00078 (const unsigned char *)New->Buffer->getBufferEnd()); } 00079 00080 if (ImportedBy) { 00081 ModuleEntry->ImportedBy.insert(ImportedBy); 00082 ImportedBy->Imports.insert(ModuleEntry); 00083 } else { 00084 ModuleEntry->DirectlyImported = true; 00085 } 00086 00087 return std::make_pair(ModuleEntry, NewModule); 00088 } 00089 00090 void ModuleManager::addInMemoryBuffer(StringRef FileName, 00091 llvm::MemoryBuffer *Buffer) { 00092 00093 const FileEntry *Entry = FileMgr.getVirtualFile(FileName, 00094 Buffer->getBufferSize(), 0); 00095 InMemoryBuffers[Entry] = Buffer; 00096 } 00097 00098 ModuleManager::ModuleManager(const FileSystemOptions &FSO) : FileMgr(FSO) { } 00099 00100 ModuleManager::~ModuleManager() { 00101 for (unsigned i = 0, e = Chain.size(); i != e; ++i) 00102 delete Chain[e - i - 1]; 00103 } 00104 00105 void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), 00106 void *UserData) { 00107 unsigned N = size(); 00108 00109 // Record the number of incoming edges for each module. When we 00110 // encounter a module with no incoming edges, push it into the queue 00111 // to seed the queue. 00112 SmallVector<ModuleFile *, 4> Queue; 00113 Queue.reserve(N); 00114 llvm::DenseMap<ModuleFile *, unsigned> UnusedIncomingEdges; 00115 for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { 00116 if (unsigned Size = (*M)->ImportedBy.size()) 00117 UnusedIncomingEdges[*M] = Size; 00118 else 00119 Queue.push_back(*M); 00120 } 00121 00122 llvm::SmallPtrSet<ModuleFile *, 4> Skipped; 00123 unsigned QueueStart = 0; 00124 while (QueueStart < Queue.size()) { 00125 ModuleFile *CurrentModule = Queue[QueueStart++]; 00126 00127 // Check whether this module should be skipped. 00128 if (Skipped.count(CurrentModule)) 00129 continue; 00130 00131 if (Visitor(*CurrentModule, UserData)) { 00132 // The visitor has requested that cut off visitation of any 00133 // module that the current module depends on. To indicate this 00134 // behavior, we mark all of the reachable modules as having N 00135 // incoming edges (which is impossible otherwise). 00136 SmallVector<ModuleFile *, 4> Stack; 00137 Stack.push_back(CurrentModule); 00138 Skipped.insert(CurrentModule); 00139 while (!Stack.empty()) { 00140 ModuleFile *NextModule = Stack.back(); 00141 Stack.pop_back(); 00142 00143 // For any module that this module depends on, push it on the 00144 // stack (if it hasn't already been marked as visited). 00145 for (llvm::SetVector<ModuleFile *>::iterator 00146 M = NextModule->Imports.begin(), 00147 MEnd = NextModule->Imports.end(); 00148 M != MEnd; ++M) { 00149 if (Skipped.insert(*M)) 00150 Stack.push_back(*M); 00151 } 00152 } 00153 continue; 00154 } 00155 00156 // For any module that this module depends on, push it on the 00157 // stack (if it hasn't already been marked as visited). 00158 for (llvm::SetVector<ModuleFile *>::iterator M = CurrentModule->Imports.begin(), 00159 MEnd = CurrentModule->Imports.end(); 00160 M != MEnd; ++M) { 00161 00162 // Remove our current module as an impediment to visiting the 00163 // module we depend on. If we were the last unvisited module 00164 // that depends on this particular module, push it into the 00165 // queue to be visited. 00166 unsigned &NumUnusedEdges = UnusedIncomingEdges[*M]; 00167 if (NumUnusedEdges && (--NumUnusedEdges == 0)) 00168 Queue.push_back(*M); 00169 } 00170 } 00171 } 00172 00173 /// \brief Perform a depth-first visit of the current module. 00174 static bool visitDepthFirst(ModuleFile &M, 00175 bool (*Visitor)(ModuleFile &M, bool Preorder, 00176 void *UserData), 00177 void *UserData, 00178 llvm::SmallPtrSet<ModuleFile *, 4> &Visited) { 00179 // Preorder visitation 00180 if (Visitor(M, /*Preorder=*/true, UserData)) 00181 return true; 00182 00183 // Visit children 00184 for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(), 00185 IMEnd = M.Imports.end(); 00186 IM != IMEnd; ++IM) { 00187 if (!Visited.insert(*IM)) 00188 continue; 00189 00190 if (visitDepthFirst(**IM, Visitor, UserData, Visited)) 00191 return true; 00192 } 00193 00194 // Postorder visitation 00195 return Visitor(M, /*Preorder=*/false, UserData); 00196 } 00197 00198 void ModuleManager::visitDepthFirst(bool (*Visitor)(ModuleFile &M, bool Preorder, 00199 void *UserData), 00200 void *UserData) { 00201 llvm::SmallPtrSet<ModuleFile *, 4> Visited; 00202 for (unsigned I = 0, N = Chain.size(); I != N; ++I) { 00203 if (!Visited.insert(Chain[I])) 00204 continue; 00205 00206 if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited)) 00207 return; 00208 } 00209 } 00210 00211 #ifndef NDEBUG 00212 namespace llvm { 00213 template<> 00214 struct GraphTraits<ModuleManager> { 00215 typedef ModuleFile NodeType; 00216 typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType; 00217 typedef ModuleManager::ModuleConstIterator nodes_iterator; 00218 00219 static ChildIteratorType child_begin(NodeType *Node) { 00220 return Node->Imports.begin(); 00221 } 00222 00223 static ChildIteratorType child_end(NodeType *Node) { 00224 return Node->Imports.end(); 00225 } 00226 00227 static nodes_iterator nodes_begin(const ModuleManager &Manager) { 00228 return Manager.begin(); 00229 } 00230 00231 static nodes_iterator nodes_end(const ModuleManager &Manager) { 00232 return Manager.end(); 00233 } 00234 }; 00235 00236 template<> 00237 struct DOTGraphTraits<ModuleManager> : public DefaultDOTGraphTraits { 00238 explicit DOTGraphTraits(bool IsSimple = false) 00239 : DefaultDOTGraphTraits(IsSimple) { } 00240 00241 static bool renderGraphFromBottomUp() { 00242 return true; 00243 } 00244 00245 std::string getNodeLabel(ModuleFile *M, const ModuleManager&) { 00246 return llvm::sys::path::stem(M->FileName); 00247 } 00248 }; 00249 } 00250 00251 void ModuleManager::viewGraph() { 00252 llvm::ViewGraph(*this, "Modules"); 00253 } 00254 #endif