FileManager.cpp revision f69a1f319bd3c846c4a9ab84ea615e4e37dfd359
18fbc88e5faee291e2e5039ec4c1dac3cfd219704Ted Kremenek///===--- FileManager.cpp - File System Probing and Caching ----------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the FileManager interface. 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// TODO: This should index all interesting directories with dirent calls. 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// getdirentries ? 165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// opendir/readdir_r/closedir ? 175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/FileManager.h" 21389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "clang/Basic/FileSystemOptions.h" 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/SmallString.h" 23c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner#include "llvm/ADT/StringExtras.h" 24389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "llvm/Support/MemoryBuffer.h" 25d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner#include "llvm/Support/raw_ostream.h" 264fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor#include "llvm/System/Path.h" 276bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#include "llvm/Config/config.h" 28458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <map> 29458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <set> 30458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <string> 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 36a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#if defined(_MSC_VER) 373102c83f6eac0cbbd698471173672c3e47a6914cChris Lattner#define S_ISDIR(s) (_S_IFDIR & s) 38a8c11c6a7831df37f2f40b34072360b04f6d19a8Chris Lattner#endif 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 403d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 423d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 44cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 45cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 46cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 47cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 496bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 50f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner#define DIR_SEPARATOR_CHARS "/\\" 516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace { 531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::string GetFullPath(const char *relPath) { 546bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek char *absPathStrPtr = _fullpath(NULL, relPath, 0); 556bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek assert(absPathStrPtr && "_fullpath() returned NULL!"); 566bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string absPath(absPathStrPtr); 586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek free(absPathStrPtr); 606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return absPath; 616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 626bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from full path to existing directories/files. 666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::StringMap<DirectoryEntry> UniqueDirs; 686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 696bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs.GetOrCreateValue( 736bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str(), 746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str() + FullPath.size() 756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek ).getValue(); 766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueDirs.size(); } 796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 836bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 8475368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 876bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 886bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 89c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner 90c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner // LowercaseString because Windows filesystem is case insensitive. 91c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner FullPath = llvm::LowercaseString(FullPath); 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueFiles.GetOrCreateValue( 936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str(), 946bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FullPath.c_str() + FullPath.size() 956bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek ).getValue(); 966bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 976bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 986bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueFiles.size(); } 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 101cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 102cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 103cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 104cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 1056bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 107f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner#define DIR_SEPARATOR_CHARS "/" 1086bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1106bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1116bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 1121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1136bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1146bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1176bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueDirs.size(); } 1206bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1216bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 1256bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1276bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1286bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1296bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1306bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1316bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 13296438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_ino, 13396438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_mode)).first); 1346bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1356bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1366bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek size_t size() { return UniqueFiles.size(); } 1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1396bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif 1406bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 141cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 142cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 143cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 1446bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 14596438f319bb07d9a40564b5e01333f82c0c8a61eTed KremenekFileManager::FileManager() 146fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek : UniqueDirs(*new UniqueDirContainer), 147fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek UniqueFiles(*new UniqueFileContainer), 14896438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek DirEntries(64), FileEntries(64), NextFileUID(0) { 1496bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 1506bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 1516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1536bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 1546bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueDirs; 1556bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueFiles; 156057e567f1b375190779e5341f42861896cdee442Douglas Gregor for (llvm::SmallVectorImpl<FileEntry *>::iterator 157057e567f1b375190779e5341f42861896cdee442Douglas Gregor V = VirtualFileEntries.begin(), 158057e567f1b375190779e5341f42861896cdee442Douglas Gregor VEnd = VirtualFileEntries.end(); 159057e567f1b375190779e5341f42861896cdee442Douglas Gregor V != VEnd; 160057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++V) 161057e567f1b375190779e5341f42861896cdee442Douglas Gregor delete *V; 1626bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 16452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregorvoid FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) { 16552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(statCache && "No stat cache provided?"); 16652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (AtBeginning || StatCache.get() == 0) { 16752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor statCache->setNextStatCache(StatCache.take()); 16852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(statCache); 16952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 17052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 17152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 17252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatSysCallCache *LastCache = StatCache.get(); 17352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (LastCache->getNextStatCache()) 17452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache = LastCache->getNextStatCache(); 17552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 17652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache->setNextStatCache(statCache); 17752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 17852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 17952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregorvoid FileManager::removeStatCache(StatSysCallCache *statCache) { 18052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (!statCache) 18152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 18252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (StatCache.get() == statCache) { 18452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // This is the first stat cache. 18552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(StatCache->takeNextStatCache()); 18652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 18752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 18852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // Find the stat cache in the list. 19052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatSysCallCache *PrevCache = StatCache.get(); 19152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (PrevCache && PrevCache->getNextStatCache() != statCache) 19252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache = PrevCache->getNextStatCache(); 19352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (PrevCache) 19452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache->setNextStatCache(statCache->getNextStatCache()); 19552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor else 19652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(false && "Stat cache not found for removal"); 19752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 19852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 199057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in. 200057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 201f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner llvm::StringRef Filename, 202389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis const FileSystemOptions &FileSystemOpts) { 203057e567f1b375190779e5341f42861896cdee442Douglas Gregor // Figure out what directory it is in. If the string contains a / in it, 204057e567f1b375190779e5341f42861896cdee442Douglas Gregor // strip off everything after it. 205057e567f1b375190779e5341f42861896cdee442Douglas Gregor // FIXME: this logic should be in sys::Path. 206f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner size_t SlashPos = Filename.rfind(DIR_SEPARATOR_CHARS); 207f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner 208f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Use the current directory if file has no path component. 209f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner if (SlashPos == llvm::StringRef::npos) 210f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner return FileMgr.getDirectory(".", FileSystemOpts); 211057e567f1b375190779e5341f42861896cdee442Douglas Gregor 212f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner if (SlashPos == Filename.size()-1) 213057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; // If filename ends with a /, it's a directory. 214f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner 215f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Ignore repeated //'s. 216f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner while (SlashPos != 0 && 217f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner llvm::StringRef(DIR_SEPARATOR_CHARS).count(Filename[SlashPos-1])) 218f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner --SlashPos; 219f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner 220f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner return FileMgr.getDirectory(Filename.substr(0, SlashPos), FileSystemOpts); 221057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 222057e567f1b375190779e5341f42861896cdee442Douglas Gregor 2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDirectory - Lookup, cache, and verify the specified directory. This 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// returns null if the directory doesn't exist. 2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 226f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerconst DirectoryEntry *FileManager::getDirectory(llvm::StringRef Filename, 227389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis const FileSystemOptions &FileSystemOpts) { 2289a6ac540bab63380a4a78d8fad87f23c50878685John Thompson // stat doesn't like trailing separators (at least on Windows). 229f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner if (Filename.size() > 1 && 230f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner (Filename.back() == '/' || Filename.back() == '\\')) 231f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner Filename = Filename.substr(0, Filename.size()-1); 2329a6ac540bab63380a4a78d8fad87f23c50878685John Thompson 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 235f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner DirEntries.GetOrCreateValue(Filename); 2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 2393d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2453d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // DirEntries map. 2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 253389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis if (stat_cached(InterndDirName, &StatBuf, FileSystemOpts) || // Error stat'ing. 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer !S_ISDIR(StatBuf.st_mode)) // Not a directory? 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2566bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // It exists. See if we have already opened a directory with the same inode. 2581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // This occurs when one dir is symlinked to another, for example. 2596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf); 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UDE.getName()) // Already have an entry with this inode, return it. 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. We use the string 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key from the DirEntries map as the string. 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UDE.Name = InterndDirName; 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2713d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_FILE - A special value distinct from null that is used to 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a filename that doesn't exist on the disk. 2733d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFile - Lookup, cache, and verify the specified file. This returns null 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if the file doesn't exist. 2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 278f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerconst FileEntry *FileManager::getFile(llvm::StringRef Filename, 279389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis const FileSystemOptions &FileSystemOpts) { 2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 284f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner FileEntries.GetOrCreateValue(Filename); 2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 2883d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 2901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2943d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FileEntries map. 2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 3001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 301057e567f1b375190779e5341f42861896cdee442Douglas Gregor const DirectoryEntry *DirInfo 302f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner = getDirectoryFromFile(*this, Filename, FileSystemOpts); 303057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (DirInfo == 0) // Directory doesn't exist, file can't exist. 304057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 305057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 3116cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << "STATING: " << Filename; 312389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis if (stat_cached(InterndFileName, &StatBuf, FileSystemOpts) || // Error stat'ing. 313fc7052d4a241ee6fc70afea7c1c9560147f0a49cTed Kremenek S_ISDIR(StatBuf.st_mode)) { // A directory? 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this file doesn't exist, we leave a null in FileEntries for this path. 3156cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << ": Not existing\n"; 3165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3186cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << ": exists\n"; 3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 320bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 3226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf); 3231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UFE.getName()) // Already have an entry with this inode, return it. 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Change the name to be a char* that points back to the 'FileEntries' 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key. 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 339057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry * 340ec1b1cc006cef19e0a95d0ea6fbfd37d0d615066Benjamin KramerFileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, 341389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis time_t ModificationTime, 342389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis const FileSystemOptions &FileSystemOpts) { 343057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileLookups; 344057e567f1b375190779e5341f42861896cdee442Douglas Gregor 345057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 346057e567f1b375190779e5341f42861896cdee442Douglas Gregor llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 347f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner FileEntries.GetOrCreateValue(Filename); 348057e567f1b375190779e5341f42861896cdee442Douglas Gregor 349057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 350057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (NamedFileEnt.getValue()) 351057e567f1b375190779e5341f42861896cdee442Douglas Gregor return NamedFileEnt.getValue() == NON_EXISTENT_FILE 352057e567f1b375190779e5341f42861896cdee442Douglas Gregor ? 0 : NamedFileEnt.getValue(); 353057e567f1b375190779e5341f42861896cdee442Douglas Gregor 354057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileCacheMisses; 355057e567f1b375190779e5341f42861896cdee442Douglas Gregor 356057e567f1b375190779e5341f42861896cdee442Douglas Gregor // By default, initialize it to invalid. 357057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(NON_EXISTENT_FILE); 358057e567f1b375190779e5341f42861896cdee442Douglas Gregor 359057e567f1b375190779e5341f42861896cdee442Douglas Gregor const DirectoryEntry *DirInfo 360f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner = getDirectoryFromFile(*this, Filename, FileSystemOpts); 361057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (DirInfo == 0) // Directory doesn't exist, file can't exist. 362057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 363057e567f1b375190779e5341f42861896cdee442Douglas Gregor 364057e567f1b375190779e5341f42861896cdee442Douglas Gregor FileEntry *UFE = new FileEntry(); 365057e567f1b375190779e5341f42861896cdee442Douglas Gregor VirtualFileEntries.push_back(UFE); 366057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(UFE); 367057e567f1b375190779e5341f42861896cdee442Douglas Gregor 368057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Name = NamedFileEnt.getKeyData(); 369057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Size = Size; 370057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->ModTime = ModificationTime; 371057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Dir = DirInfo; 372057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->UID = NextFileUID++; 3733e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor 3743e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor // If this virtual file resolves to a file, also map that file to the 3753e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor // newly-created file entry. 3763e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor const char *InterndFileName = NamedFileEnt.getKeyData(); 3773e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor struct stat StatBuf; 378389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis if (!stat_cached(InterndFileName, &StatBuf, FileSystemOpts) && 3793e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor !S_ISDIR(StatBuf.st_mode)) { 3803e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor llvm::sys::Path FilePath(InterndFileName); 3813e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor FilePath.makeAbsolute(); 3823e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor FileEntries[FilePath.str()] = UFE; 3833e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor } 3843e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor 385057e567f1b375190779e5341f42861896cdee442Douglas Gregor return UFE; 386057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 387057e567f1b375190779e5341f42861896cdee442Douglas Gregor 388f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager:: 389f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris LattnergetBufferForFile(const char *FilenameStart, const char *FilenameEnd, 390f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner const FileSystemOptions &FileSystemOpts, 391f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner std::string *ErrorStr, 392f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner int64_t FileSize, 393f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner struct stat *FileInfo) { 394389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis llvm::sys::Path FilePath(llvm::StringRef(FilenameStart, 395389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FilenameEnd-FilenameStart)); 396389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FixupRelativePath(FilePath, FileSystemOpts); 397389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 398389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis return llvm::MemoryBuffer::getFile(FilePath.c_str(), ErrorStr, 399389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FileSize, FileInfo); 400389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 401389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 402389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidisint FileManager::stat_cached(const char* path, struct stat* buf, 403389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis const FileSystemOptions &FileSystemOpts) { 404389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis llvm::sys::Path FilePath(path); 405389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FixupRelativePath(FilePath, FileSystemOpts); 406389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 407389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis return StatCache.get() ? StatCache->stat(FilePath.c_str(), buf) 408389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis : stat(FilePath.c_str(), buf); 409389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 410389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 411389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidisvoid FileManager::FixupRelativePath(llvm::sys::Path &path, 412389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis const FileSystemOptions &FSOpts) { 413389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis if (!FSOpts.WorkingDir.empty() && !path.isAbsolute()) { 414389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis llvm::sys::Path NewPath(FSOpts.WorkingDir); 415389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis NewPath.appendComponent(path.str()); 416389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis path = NewPath; 417389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis } 418389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 419389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 4216cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "\n*** File Manager Stats:\n"; 4226cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << UniqueFiles.size() << " files found, " 4236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << UniqueDirs.size() << " dirs found.\n"; 4246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumDirLookups << " dir lookups, " 4256cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumDirCacheMisses << " dir cache misses.\n"; 4266cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumFileLookups << " file lookups, " 4276cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumFileCacheMisses << " file cache misses.\n"; 4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4296cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 4305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4314fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor 4324fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregorint MemorizeStatCalls::stat(const char *path, struct stat *buf) { 43352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor int result = StatSysCallCache::stat(path, buf); 43452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 435475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar // Do not cache failed stats, it is easy to construct common inconsistent 436475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar // situations if we do, and they are not important for PCH performance (which 437475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar // currently only needs the stats to construct the initial FileManager 438475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar // entries). 439475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar if (result != 0) 440475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar return result; 441475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar 442475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar // Cache file 'stat' results and directories with absolutely paths. 443475ddb4547ce35706ce1ff54b14bdcfdc51954c2Daniel Dunbar if (!S_ISDIR(buf->st_mode) || llvm::sys::Path(path).isAbsolute()) 4444fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor StatCalls[path] = StatResult(result, *buf); 4451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return result; 4474fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor} 448