Home | History | Annotate | Download | only in Basic
      1 //===--- FileManager.cpp - File System Probing and Caching ----------------===//
      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 implements the FileManager interface.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 //
     14 // TODO: This should index all interesting directories with dirent calls.
     15 //  getdirentries ?
     16 //  opendir/readdir_r/closedir ?
     17 //
     18 //===----------------------------------------------------------------------===//
     19 
     20 #include "clang/Basic/FileManager.h"
     21 #include "clang/Basic/FileSystemStatCache.h"
     22 #include "llvm/ADT/SmallString.h"
     23 #include "llvm/Support/FileSystem.h"
     24 #include "llvm/Support/MemoryBuffer.h"
     25 #include "llvm/Support/raw_ostream.h"
     26 #include "llvm/Support/Path.h"
     27 #include "llvm/Support/system_error.h"
     28 #include "llvm/Config/llvm-config.h"
     29 #include <map>
     30 #include <set>
     31 #include <string>
     32 
     33 // FIXME: This is terrible, we need this for ::close.
     34 #if !defined(_MSC_VER) && !defined(__MINGW32__)
     35 #include <unistd.h>
     36 #include <sys/uio.h>
     37 #else
     38 #include <io.h>
     39 #endif
     40 using namespace clang;
     41 
     42 // FIXME: Enhance libsystem to support inode and other fields.
     43 #include <sys/stat.h>
     44 
     45 /// NON_EXISTENT_DIR - A special value distinct from null that is used to
     46 /// represent a dir name that doesn't exist on the disk.
     47 #define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
     48 
     49 /// NON_EXISTENT_FILE - A special value distinct from null that is used to
     50 /// represent a filename that doesn't exist on the disk.
     51 #define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
     52 
     53 
     54 FileEntry::~FileEntry() {
     55   // If this FileEntry owns an open file descriptor that never got used, close
     56   // it.
     57   if (FD != -1) ::close(FD);
     58 }
     59 
     60 //===----------------------------------------------------------------------===//
     61 // Windows.
     62 //===----------------------------------------------------------------------===//
     63 
     64 #ifdef LLVM_ON_WIN32
     65 
     66 namespace {
     67   static std::string GetFullPath(const char *relPath) {
     68     char *absPathStrPtr = _fullpath(NULL, relPath, 0);
     69     assert(absPathStrPtr && "_fullpath() returned NULL!");
     70 
     71     std::string absPath(absPathStrPtr);
     72 
     73     free(absPathStrPtr);
     74     return absPath;
     75   }
     76 }
     77 
     78 class FileManager::UniqueDirContainer {
     79   /// UniqueDirs - Cache from full path to existing directories/files.
     80   ///
     81   llvm::StringMap<DirectoryEntry> UniqueDirs;
     82 
     83 public:
     84   /// getDirectory - Return an existing DirectoryEntry with the given
     85   /// name if there is already one; otherwise create and return a
     86   /// default-constructed DirectoryEntry.
     87   DirectoryEntry &getDirectory(const char *Name,
     88                                const struct stat & /*StatBuf*/) {
     89     std::string FullPath(GetFullPath(Name));
     90     return UniqueDirs.GetOrCreateValue(FullPath).getValue();
     91   }
     92 
     93   size_t size() const { return UniqueDirs.size(); }
     94 };
     95 
     96 class FileManager::UniqueFileContainer {
     97   /// UniqueFiles - Cache from full path to existing directories/files.
     98   ///
     99   llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles;
    100 
    101 public:
    102   /// getFile - Return an existing FileEntry with the given name if
    103   /// there is already one; otherwise create and return a
    104   /// default-constructed FileEntry.
    105   FileEntry &getFile(const char *Name, const struct stat & /*StatBuf*/) {
    106     std::string FullPath(GetFullPath(Name));
    107 
    108     // Lowercase string because Windows filesystem is case insensitive.
    109     FullPath = StringRef(FullPath).lower();
    110     return UniqueFiles.GetOrCreateValue(FullPath).getValue();
    111   }
    112 
    113   size_t size() const { return UniqueFiles.size(); }
    114 };
    115 
    116 //===----------------------------------------------------------------------===//
    117 // Unix-like Systems.
    118 //===----------------------------------------------------------------------===//
    119 
    120 #else
    121 
    122 class FileManager::UniqueDirContainer {
    123   /// UniqueDirs - Cache from ID's to existing directories/files.
    124   std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
    125 
    126 public:
    127   /// getDirectory - Return an existing DirectoryEntry with the given
    128   /// ID's if there is already one; otherwise create and return a
    129   /// default-constructed DirectoryEntry.
    130   DirectoryEntry &getDirectory(const char * /*Name*/,
    131                                const struct stat &StatBuf) {
    132     return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
    133   }
    134 
    135   size_t size() const { return UniqueDirs.size(); }
    136 };
    137 
    138 class FileManager::UniqueFileContainer {
    139   /// UniqueFiles - Cache from ID's to existing directories/files.
    140   std::set<FileEntry> UniqueFiles;
    141 
    142 public:
    143   /// getFile - Return an existing FileEntry with the given ID's if
    144   /// there is already one; otherwise create and return a
    145   /// default-constructed FileEntry.
    146   FileEntry &getFile(const char * /*Name*/, const struct stat &StatBuf) {
    147     return
    148       const_cast<FileEntry&>(
    149                     *UniqueFiles.insert(FileEntry(StatBuf.st_dev,
    150                                                   StatBuf.st_ino,
    151                                                   StatBuf.st_mode)).first);
    152   }
    153 
    154   size_t size() const { return UniqueFiles.size(); }
    155 };
    156 
    157 #endif
    158 
    159 //===----------------------------------------------------------------------===//
    160 // Common logic.
    161 //===----------------------------------------------------------------------===//
    162 
    163 FileManager::FileManager(const FileSystemOptions &FSO)
    164   : FileSystemOpts(FSO),
    165     UniqueRealDirs(*new UniqueDirContainer()),
    166     UniqueRealFiles(*new UniqueFileContainer()),
    167     SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) {
    168   NumDirLookups = NumFileLookups = 0;
    169   NumDirCacheMisses = NumFileCacheMisses = 0;
    170 }
    171 
    172 FileManager::~FileManager() {
    173   delete &UniqueRealDirs;
    174   delete &UniqueRealFiles;
    175   for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i)
    176     delete VirtualFileEntries[i];
    177   for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i)
    178     delete VirtualDirectoryEntries[i];
    179 }
    180 
    181 void FileManager::addStatCache(FileSystemStatCache *statCache,
    182                                bool AtBeginning) {
    183   assert(statCache && "No stat cache provided?");
    184   if (AtBeginning || StatCache.get() == 0) {
    185     statCache->setNextStatCache(StatCache.take());
    186     StatCache.reset(statCache);
    187     return;
    188   }
    189 
    190   FileSystemStatCache *LastCache = StatCache.get();
    191   while (LastCache->getNextStatCache())
    192     LastCache = LastCache->getNextStatCache();
    193 
    194   LastCache->setNextStatCache(statCache);
    195 }
    196 
    197 void FileManager::removeStatCache(FileSystemStatCache *statCache) {
    198   if (!statCache)
    199     return;
    200 
    201   if (StatCache.get() == statCache) {
    202     // This is the first stat cache.
    203     StatCache.reset(StatCache->takeNextStatCache());
    204     return;
    205   }
    206 
    207   // Find the stat cache in the list.
    208   FileSystemStatCache *PrevCache = StatCache.get();
    209   while (PrevCache && PrevCache->getNextStatCache() != statCache)
    210     PrevCache = PrevCache->getNextStatCache();
    211 
    212   assert(PrevCache && "Stat cache not found for removal");
    213   PrevCache->setNextStatCache(statCache->getNextStatCache());
    214 }
    215 
    216 /// \brief Retrieve the directory that the given file name resides in.
    217 /// Filename can point to either a real file or a virtual file.
    218 static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
    219                                                   StringRef Filename,
    220                                                   bool CacheFailure) {
    221   if (Filename.empty())
    222     return NULL;
    223 
    224   if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
    225     return NULL;  // If Filename is a directory.
    226 
    227   StringRef DirName = llvm::sys::path::parent_path(Filename);
    228   // Use the current directory if file has no path component.
    229   if (DirName.empty())
    230     DirName = ".";
    231 
    232   return FileMgr.getDirectory(DirName, CacheFailure);
    233 }
    234 
    235 /// Add all ancestors of the given path (pointing to either a file or
    236 /// a directory) as virtual directories.
    237 void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
    238   StringRef DirName = llvm::sys::path::parent_path(Path);
    239   if (DirName.empty())
    240     return;
    241 
    242   llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
    243     SeenDirEntries.GetOrCreateValue(DirName);
    244 
    245   // When caching a virtual directory, we always cache its ancestors
    246   // at the same time.  Therefore, if DirName is already in the cache,
    247   // we don't need to recurse as its ancestors must also already be in
    248   // the cache.
    249   if (NamedDirEnt.getValue())
    250     return;
    251 
    252   // Add the virtual directory to the cache.
    253   DirectoryEntry *UDE = new DirectoryEntry;
    254   UDE->Name = NamedDirEnt.getKeyData();
    255   NamedDirEnt.setValue(UDE);
    256   VirtualDirectoryEntries.push_back(UDE);
    257 
    258   // Recursively add the other ancestors.
    259   addAncestorsAsVirtualDirs(DirName);
    260 }
    261 
    262 /// getDirectory - Lookup, cache, and verify the specified directory
    263 /// (real or virtual).  This returns NULL if the directory doesn't
    264 /// exist.
    265 ///
    266 const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
    267                                                 bool CacheFailure) {
    268   // stat doesn't like trailing separators.
    269   // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'.
    270   // (though it can strip '\\')
    271   if (DirName.size() > 1 && llvm::sys::path::is_separator(DirName.back()))
    272     DirName = DirName.substr(0, DirName.size()-1);
    273 
    274   ++NumDirLookups;
    275   llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
    276     SeenDirEntries.GetOrCreateValue(DirName);
    277 
    278   // See if there was already an entry in the map.  Note that the map
    279   // contains both virtual and real directories.
    280   if (NamedDirEnt.getValue())
    281     return NamedDirEnt.getValue() == NON_EXISTENT_DIR
    282               ? 0 : NamedDirEnt.getValue();
    283 
    284   ++NumDirCacheMisses;
    285 
    286   // By default, initialize it to invalid.
    287   NamedDirEnt.setValue(NON_EXISTENT_DIR);
    288 
    289   // Get the null-terminated directory name as stored as the key of the
    290   // SeenDirEntries map.
    291   const char *InterndDirName = NamedDirEnt.getKeyData();
    292 
    293   // Check to see if the directory exists.
    294   struct stat StatBuf;
    295   if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) {
    296     // There's no real directory at the given path.
    297     if (!CacheFailure)
    298       SeenDirEntries.erase(DirName);
    299     return 0;
    300   }
    301 
    302   // It exists.  See if we have already opened a directory with the
    303   // same inode (this occurs on Unix-like systems when one dir is
    304   // symlinked to another, for example) or the same path (on
    305   // Windows).
    306   DirectoryEntry &UDE = UniqueRealDirs.getDirectory(InterndDirName, StatBuf);
    307 
    308   NamedDirEnt.setValue(&UDE);
    309   if (!UDE.getName()) {
    310     // We don't have this directory yet, add it.  We use the string
    311     // key from the SeenDirEntries map as the string.
    312     UDE.Name  = InterndDirName;
    313   }
    314 
    315   return &UDE;
    316 }
    317 
    318 /// getFile - Lookup, cache, and verify the specified file (real or
    319 /// virtual).  This returns NULL if the file doesn't exist.
    320 ///
    321 const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
    322                                       bool CacheFailure) {
    323   ++NumFileLookups;
    324 
    325   // See if there is already an entry in the map.
    326   llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
    327     SeenFileEntries.GetOrCreateValue(Filename);
    328 
    329   // See if there is already an entry in the map.
    330   if (NamedFileEnt.getValue())
    331     return NamedFileEnt.getValue() == NON_EXISTENT_FILE
    332                  ? 0 : NamedFileEnt.getValue();
    333 
    334   ++NumFileCacheMisses;
    335 
    336   // By default, initialize it to invalid.
    337   NamedFileEnt.setValue(NON_EXISTENT_FILE);
    338 
    339   // Get the null-terminated file name as stored as the key of the
    340   // SeenFileEntries map.
    341   const char *InterndFileName = NamedFileEnt.getKeyData();
    342 
    343   // Look up the directory for the file.  When looking up something like
    344   // sys/foo.h we'll discover all of the search directories that have a 'sys'
    345   // subdirectory.  This will let us avoid having to waste time on known-to-fail
    346   // searches when we go to find sys/bar.h, because all the search directories
    347   // without a 'sys' subdir will get a cached failure result.
    348   const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
    349                                                        CacheFailure);
    350   if (DirInfo == 0) {  // Directory doesn't exist, file can't exist.
    351     if (!CacheFailure)
    352       SeenFileEntries.erase(Filename);
    353 
    354     return 0;
    355   }
    356 
    357   // FIXME: Use the directory info to prune this, before doing the stat syscall.
    358   // FIXME: This will reduce the # syscalls.
    359 
    360   // Nope, there isn't.  Check to see if the file exists.
    361   int FileDescriptor = -1;
    362   struct stat StatBuf;
    363   if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) {
    364     // There's no real file at the given path.
    365     if (!CacheFailure)
    366       SeenFileEntries.erase(Filename);
    367 
    368     return 0;
    369   }
    370 
    371   if (FileDescriptor != -1 && !openFile) {
    372     close(FileDescriptor);
    373     FileDescriptor = -1;
    374   }
    375 
    376   // It exists.  See if we have already opened a file with the same inode.
    377   // This occurs when one dir is symlinked to another, for example.
    378   FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf);
    379 
    380   NamedFileEnt.setValue(&UFE);
    381   if (UFE.getName()) { // Already have an entry with this inode, return it.
    382     // If the stat process opened the file, close it to avoid a FD leak.
    383     if (FileDescriptor != -1)
    384       close(FileDescriptor);
    385 
    386     return &UFE;
    387   }
    388 
    389   // Otherwise, we don't have this directory yet, add it.
    390   // FIXME: Change the name to be a char* that points back to the
    391   // 'SeenFileEntries' key.
    392   UFE.Name    = InterndFileName;
    393   UFE.Size    = StatBuf.st_size;
    394   UFE.ModTime = StatBuf.st_mtime;
    395   UFE.Dir     = DirInfo;
    396   UFE.UID     = NextFileUID++;
    397   UFE.FD      = FileDescriptor;
    398   return &UFE;
    399 }
    400 
    401 const FileEntry *
    402 FileManager::getVirtualFile(StringRef Filename, off_t Size,
    403                             time_t ModificationTime) {
    404   ++NumFileLookups;
    405 
    406   // See if there is already an entry in the map.
    407   llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
    408     SeenFileEntries.GetOrCreateValue(Filename);
    409 
    410   // See if there is already an entry in the map.
    411   if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE)
    412     return NamedFileEnt.getValue();
    413 
    414   ++NumFileCacheMisses;
    415 
    416   // By default, initialize it to invalid.
    417   NamedFileEnt.setValue(NON_EXISTENT_FILE);
    418 
    419   addAncestorsAsVirtualDirs(Filename);
    420   FileEntry *UFE = 0;
    421 
    422   // Now that all ancestors of Filename are in the cache, the
    423   // following call is guaranteed to find the DirectoryEntry from the
    424   // cache.
    425   const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
    426                                                        /*CacheFailure=*/true);
    427   assert(DirInfo &&
    428          "The directory of a virtual file should already be in the cache.");
    429 
    430   // Check to see if the file exists. If so, drop the virtual file
    431   int FileDescriptor = -1;
    432   struct stat StatBuf;
    433   const char *InterndFileName = NamedFileEnt.getKeyData();
    434   if (getStatValue(InterndFileName, StatBuf, &FileDescriptor) == 0) {
    435     // If the stat process opened the file, close it to avoid a FD leak.
    436     if (FileDescriptor != -1)
    437       close(FileDescriptor);
    438 
    439     StatBuf.st_size = Size;
    440     StatBuf.st_mtime = ModificationTime;
    441     UFE = &UniqueRealFiles.getFile(InterndFileName, StatBuf);
    442 
    443     NamedFileEnt.setValue(UFE);
    444 
    445     // If we had already opened this file, close it now so we don't
    446     // leak the descriptor. We're not going to use the file
    447     // descriptor anyway, since this is a virtual file.
    448     if (UFE->FD != -1) {
    449       close(UFE->FD);
    450       UFE->FD = -1;
    451     }
    452 
    453     // If we already have an entry with this inode, return it.
    454     if (UFE->getName())
    455       return UFE;
    456   }
    457 
    458   if (!UFE) {
    459     UFE = new FileEntry();
    460     VirtualFileEntries.push_back(UFE);
    461     NamedFileEnt.setValue(UFE);
    462   }
    463 
    464   UFE->Name    = InterndFileName;
    465   UFE->Size    = Size;
    466   UFE->ModTime = ModificationTime;
    467   UFE->Dir     = DirInfo;
    468   UFE->UID     = NextFileUID++;
    469   UFE->FD      = -1;
    470   return UFE;
    471 }
    472 
    473 void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
    474   StringRef pathRef(path.data(), path.size());
    475 
    476   if (FileSystemOpts.WorkingDir.empty()
    477       || llvm::sys::path::is_absolute(pathRef))
    478     return;
    479 
    480   SmallString<128> NewPath(FileSystemOpts.WorkingDir);
    481   llvm::sys::path::append(NewPath, pathRef);
    482   path = NewPath;
    483 }
    484 
    485 llvm::MemoryBuffer *FileManager::
    486 getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) {
    487   OwningPtr<llvm::MemoryBuffer> Result;
    488   llvm::error_code ec;
    489 
    490   const char *Filename = Entry->getName();
    491   // If the file is already open, use the open file descriptor.
    492   if (Entry->FD != -1) {
    493     ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result,
    494                                          Entry->getSize());
    495     if (ErrorStr)
    496       *ErrorStr = ec.message();
    497 
    498     close(Entry->FD);
    499     Entry->FD = -1;
    500     return Result.take();
    501   }
    502 
    503   // Otherwise, open the file.
    504 
    505   if (FileSystemOpts.WorkingDir.empty()) {
    506     ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize());
    507     if (ec && ErrorStr)
    508       *ErrorStr = ec.message();
    509     return Result.take();
    510   }
    511 
    512   SmallString<128> FilePath(Entry->getName());
    513   FixupRelativePath(FilePath);
    514   ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, Entry->getSize());
    515   if (ec && ErrorStr)
    516     *ErrorStr = ec.message();
    517   return Result.take();
    518 }
    519 
    520 llvm::MemoryBuffer *FileManager::
    521 getBufferForFile(StringRef Filename, std::string *ErrorStr) {
    522   OwningPtr<llvm::MemoryBuffer> Result;
    523   llvm::error_code ec;
    524   if (FileSystemOpts.WorkingDir.empty()) {
    525     ec = llvm::MemoryBuffer::getFile(Filename, Result);
    526     if (ec && ErrorStr)
    527       *ErrorStr = ec.message();
    528     return Result.take();
    529   }
    530 
    531   SmallString<128> FilePath(Filename);
    532   FixupRelativePath(FilePath);
    533   ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result);
    534   if (ec && ErrorStr)
    535     *ErrorStr = ec.message();
    536   return Result.take();
    537 }
    538 
    539 /// getStatValue - Get the 'stat' information for the specified path,
    540 /// using the cache to accelerate it if possible.  This returns true
    541 /// if the path points to a virtual file or does not exist, or returns
    542 /// false if it's an existent real file.  If FileDescriptor is NULL,
    543 /// do directory look-up instead of file look-up.
    544 bool FileManager::getStatValue(const char *Path, struct stat &StatBuf,
    545                                int *FileDescriptor) {
    546   // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
    547   // absolute!
    548   if (FileSystemOpts.WorkingDir.empty())
    549     return FileSystemStatCache::get(Path, StatBuf, FileDescriptor,
    550                                     StatCache.get());
    551 
    552   SmallString<128> FilePath(Path);
    553   FixupRelativePath(FilePath);
    554 
    555   return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor,
    556                                   StatCache.get());
    557 }
    558 
    559 bool FileManager::getNoncachedStatValue(StringRef Path,
    560                                         struct stat &StatBuf) {
    561   SmallString<128> FilePath(Path);
    562   FixupRelativePath(FilePath);
    563 
    564   return ::stat(FilePath.c_str(), &StatBuf) != 0;
    565 }
    566 
    567 void FileManager::GetUniqueIDMapping(
    568                    SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
    569   UIDToFiles.clear();
    570   UIDToFiles.resize(NextFileUID);
    571 
    572   // Map file entries
    573   for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
    574          FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
    575        FE != FEEnd; ++FE)
    576     if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE)
    577       UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
    578 
    579   // Map virtual file entries
    580   for (SmallVector<FileEntry*, 4>::const_iterator
    581          VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end();
    582        VFE != VFEEnd; ++VFE)
    583     if (*VFE && *VFE != NON_EXISTENT_FILE)
    584       UIDToFiles[(*VFE)->getUID()] = *VFE;
    585 }
    586 
    587 
    588 void FileManager::PrintStats() const {
    589   llvm::errs() << "\n*** File Manager Stats:\n";
    590   llvm::errs() << UniqueRealFiles.size() << " real files found, "
    591                << UniqueRealDirs.size() << " real dirs found.\n";
    592   llvm::errs() << VirtualFileEntries.size() << " virtual files found, "
    593                << VirtualDirectoryEntries.size() << " virtual dirs found.\n";
    594   llvm::errs() << NumDirLookups << " dir lookups, "
    595                << NumDirCacheMisses << " dir cache misses.\n";
    596   llvm::errs() << NumFileLookups << " file lookups, "
    597                << NumFileCacheMisses << " file cache misses.\n";
    598 
    599   //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
    600 }
    601