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