FileManager.cpp revision 291fcf02980be85cf13c8a63bb036a19012311df
110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner//===--- 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" 2110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/FileSystemStatCache.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> 31291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner 32291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner// FIXME: This is terrible, we need this for ::close. 33291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#if !defined(_MSC_VER) && !defined(__MINGW32__) 34291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <unistd.h> 35291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <sys/uio.h> 36291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#else 37291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <io.h> 38291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#endif 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 443d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 463d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 48f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// NON_EXISTENT_FILE - A special value distinct from null that is used to 49f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// represent a filename that doesn't exist on the disk. 50f9f7766846a205bc900b578f944567e679b221aaChris Lattner#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 51f9f7766846a205bc900b578f944567e679b221aaChris Lattner 52f9f7766846a205bc900b578f944567e679b221aaChris Lattner 53f9f7766846a205bc900b578f944567e679b221aaChris LattnerFileEntry::~FileEntry() { 54f9f7766846a205bc900b578f944567e679b221aaChris Lattner // If this FileEntry owns an open file descriptor that never got used, close 55f9f7766846a205bc900b578f944567e679b221aaChris Lattner // it. 56f9f7766846a205bc900b578f944567e679b221aaChris Lattner if (FD != -1) ::close(FD); 57f9f7766846a205bc900b578f944567e679b221aaChris Lattner} 58f9f7766846a205bc900b578f944567e679b221aaChris Lattner 59cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 60cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 61cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 62cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 65aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\') 666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace { 681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::string GetFullPath(const char *relPath) { 696bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek char *absPathStrPtr = _fullpath(NULL, relPath, 0); 706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek assert(absPathStrPtr && "_fullpath() returned NULL!"); 716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string absPath(absPathStrPtr); 736bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek free(absPathStrPtr); 756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return absPath; 766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 776bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from full path to existing directories/files. 816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::StringMap<DirectoryEntry> UniqueDirs; 836bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 846bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 87f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueDirs.GetOrCreateValue(FullPath).getValue(); 886bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 90f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 916bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 946bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 956bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 9675368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 976bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 986bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 101c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner 102c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner // LowercaseString because Windows filesystem is case insensitive. 103c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner FullPath = llvm::LowercaseString(FullPath); 104f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueFiles.GetOrCreateValue(FullPath).getValue(); 1056bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 107f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1086bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 110cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 111cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 112cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 113cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 1146bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 116aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/') 1176bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1216bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1256bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 127f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 1286bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1296bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1306bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1316bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1326bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1346bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1356bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1366bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 13996438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_ino, 14096438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_mode)).first); 1416bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1426bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 143f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1446bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1456bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1466bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif 1476bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 148cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 149cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 150cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 1516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1527ad97ffa631af6ad678c79b38341ac995f347ce9Chris LattnerFileManager::FileManager(const FileSystemOptions &FSO) 1537ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner : FileSystemOpts(FSO), 154f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner UniqueDirs(*new UniqueDirContainer()), 155f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner UniqueFiles(*new UniqueFileContainer()), 15696438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek DirEntries(64), FileEntries(64), NextFileUID(0) { 1576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 1586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 1596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1616bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 1626bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueDirs; 1636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueFiles; 164f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) 165f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner delete VirtualFileEntries[i]; 1666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 16810e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::addStatCache(FileSystemStatCache *statCache, 16910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner bool AtBeginning) { 17052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(statCache && "No stat cache provided?"); 17152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (AtBeginning || StatCache.get() == 0) { 17252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor statCache->setNextStatCache(StatCache.take()); 17352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(statCache); 17452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 17552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 17652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 17710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *LastCache = StatCache.get(); 17852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (LastCache->getNextStatCache()) 17952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache = LastCache->getNextStatCache(); 18052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache->setNextStatCache(statCache); 18252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 18352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18410e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::removeStatCache(FileSystemStatCache *statCache) { 18552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (!statCache) 18652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 18752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (StatCache.get() == statCache) { 18952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // This is the first stat cache. 19052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(StatCache->takeNextStatCache()); 19152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 19252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 19352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 19452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // Find the stat cache in the list. 19510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *PrevCache = StatCache.get(); 19652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (PrevCache && PrevCache->getNextStatCache() != statCache) 19752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache = PrevCache->getNextStatCache(); 198f9f7766846a205bc900b578f944567e679b221aaChris Lattner 199f9f7766846a205bc900b578f944567e679b221aaChris Lattner assert(PrevCache && "Stat cache not found for removal"); 200f9f7766846a205bc900b578f944567e679b221aaChris Lattner PrevCache->setNextStatCache(statCache->getNextStatCache()); 20152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 20252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 203057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in. 204057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 20539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner llvm::StringRef Filename) { 206057e567f1b375190779e5341f42861896cdee442Douglas Gregor // Figure out what directory it is in. If the string contains a / in it, 207057e567f1b375190779e5341f42861896cdee442Douglas Gregor // strip off everything after it. 208057e567f1b375190779e5341f42861896cdee442Douglas Gregor // FIXME: this logic should be in sys::Path. 209aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer size_t SlashPos = Filename.size(); 210aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer while (SlashPos != 0 && !IS_DIR_SEPARATOR_CHAR(Filename[SlashPos-1])) 211aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer --SlashPos; 212aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 213f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Use the current directory if file has no path component. 214aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer if (SlashPos == 0) 21539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return FileMgr.getDirectory("."); 216057e567f1b375190779e5341f42861896cdee442Douglas Gregor 217f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner if (SlashPos == Filename.size()-1) 218057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; // If filename ends with a /, it's a directory. 219aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 220f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Ignore repeated //'s. 221aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer while (SlashPos != 0 && IS_DIR_SEPARATOR_CHAR(Filename[SlashPos-1])) 222f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner --SlashPos; 223aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 22439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return FileMgr.getDirectory(Filename.substr(0, SlashPos)); 225057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 226057e567f1b375190779e5341f42861896cdee442Douglas Gregor 2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDirectory - Lookup, cache, and verify the specified directory. This 2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// returns null if the directory doesn't exist. 2291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 23039b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst DirectoryEntry *FileManager::getDirectory(llvm::StringRef Filename) { 2319a6ac540bab63380a4a78d8fad87f23c50878685John Thompson // stat doesn't like trailing separators (at least on Windows). 232aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer if (Filename.size() > 1 && IS_DIR_SEPARATOR_CHAR(Filename.back())) 233f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner Filename = Filename.substr(0, Filename.size()-1); 2349a6ac540bab63380a4a78d8fad87f23c50878685John Thompson 2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 237f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner DirEntries.GetOrCreateValue(Filename); 2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 2413d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 2451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2473d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 2481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // DirEntries map. 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 2521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 255898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) 2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // It exists. See if we have already opened a directory with the same inode. 2591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // This occurs when one dir is symlinked to another, for example. 2606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf); 2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UDE.getName()) // Already have an entry with this inode, return it. 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. We use the string 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key from the DirEntries map as the string. 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UDE.Name = InterndDirName; 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFile - Lookup, cache, and verify the specified file. This returns null 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if the file doesn't exist. 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 27539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst FileEntry *FileManager::getFile(llvm::StringRef Filename) { 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 280f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner FileEntries.GetOrCreateValue(Filename); 2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 2843d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2903d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FileEntries map. 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 297f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner 298f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // Look up the directory for the file. When looking up something like 299f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // sys/foo.h we'll discover all of the search directories that have a 'sys' 300f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // subdirectory. This will let us avoid having to waste time on known-to-fail 301f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // searches when we go to find sys/bar.h, because all the search directories 302f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // without a 'sys' subdir will get a cached failure result. 30339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); 304057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (DirInfo == 0) // Directory doesn't exist, file can't exist. 305057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 306057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 3085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 311898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int FileDescriptor = -1; 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 313898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 316bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 3186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf); 3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 321898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (UFE.getName()) { // Already have an entry with this inode, return it. 322898a061f69e1145bf89a987c08203132b9922a3cChris Lattner // If the stat process opened the file, close it to avoid a FD leak. 323898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (FileDescriptor != -1) 324898a061f69e1145bf89a987c08203132b9922a3cChris Lattner close(FileDescriptor); 325898a061f69e1145bf89a987c08203132b9922a3cChris Lattner 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 327898a061f69e1145bf89a987c08203132b9922a3cChris Lattner } 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Change the name to be a char* that points back to the 'FileEntries' 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key. 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 337898a061f69e1145bf89a987c08203132b9922a3cChris Lattner UFE.FD = FileDescriptor; 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 341057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry * 342ec1b1cc006cef19e0a95d0ea6fbfd37d0d615066Benjamin KramerFileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, 34339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner time_t ModificationTime) { 344057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileLookups; 345057e567f1b375190779e5341f42861896cdee442Douglas Gregor 346057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 347057e567f1b375190779e5341f42861896cdee442Douglas Gregor llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 348f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner FileEntries.GetOrCreateValue(Filename); 349057e567f1b375190779e5341f42861896cdee442Douglas Gregor 350057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 351057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (NamedFileEnt.getValue()) 352057e567f1b375190779e5341f42861896cdee442Douglas Gregor return NamedFileEnt.getValue() == NON_EXISTENT_FILE 353057e567f1b375190779e5341f42861896cdee442Douglas Gregor ? 0 : NamedFileEnt.getValue(); 354057e567f1b375190779e5341f42861896cdee442Douglas Gregor 355057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileCacheMisses; 356057e567f1b375190779e5341f42861896cdee442Douglas Gregor 357057e567f1b375190779e5341f42861896cdee442Douglas Gregor // By default, initialize it to invalid. 358057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(NON_EXISTENT_FILE); 359057e567f1b375190779e5341f42861896cdee442Douglas Gregor 36039b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); 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 368f9f7766846a205bc900b578f944567e679b221aaChris Lattner // Get the null-terminated file name as stored as the key of the 369f9f7766846a205bc900b578f944567e679b221aaChris Lattner // FileEntries map. 370f9f7766846a205bc900b578f944567e679b221aaChris Lattner const char *InterndFileName = NamedFileEnt.getKeyData(); 371f9f7766846a205bc900b578f944567e679b221aaChris Lattner 372f9f7766846a205bc900b578f944567e679b221aaChris Lattner UFE->Name = InterndFileName; 373057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Size = Size; 374057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->ModTime = ModificationTime; 375057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Dir = DirInfo; 376057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->UID = NextFileUID++; 3773e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor 3783e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor // If this virtual file resolves to a file, also map that file to the 3793e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor // newly-created file entry. 380898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int FileDescriptor = -1; 3813e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor struct stat StatBuf; 382898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) 383f9f7766846a205bc900b578f944567e679b221aaChris Lattner return UFE; 384898a061f69e1145bf89a987c08203132b9922a3cChris Lattner 385898a061f69e1145bf89a987c08203132b9922a3cChris Lattner UFE->FD = FileDescriptor; 386f9f7766846a205bc900b578f944567e679b221aaChris Lattner llvm::sys::Path FilePath(UFE->Name); 387f9f7766846a205bc900b578f944567e679b221aaChris Lattner FilePath.makeAbsolute(); 388f9f7766846a205bc900b578f944567e679b221aaChris Lattner FileEntries[FilePath.str()] = UFE; 389057e567f1b375190779e5341f42861896cdee442Douglas Gregor return UFE; 390057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 391057e567f1b375190779e5341f42861896cdee442Douglas Gregor 39267452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattnervoid FileManager::FixupRelativePath(llvm::sys::Path &path, 39367452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner const FileSystemOptions &FSOpts) { 39467452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner if (FSOpts.WorkingDir.empty() || path.isAbsolute()) return; 39567452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 39667452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner llvm::sys::Path NewPath(FSOpts.WorkingDir); 39767452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner NewPath.appendComponent(path.str()); 39867452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner path = NewPath; 39967452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner} 40067452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 40175dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattnerllvm::MemoryBuffer *FileManager:: 40275dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { 40375dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner llvm::StringRef Filename = Entry->getName(); 40475dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner if (FileSystemOpts.WorkingDir.empty()) 405f8f6129861f3972dab2c5a6cde29711ac780a7d0Chris Lattner return llvm::MemoryBuffer::getFile(Filename, ErrorStr, Entry->getSize()); 40675dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner 40775dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner llvm::sys::Path FilePath(Filename); 40875dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner FixupRelativePath(FilePath, FileSystemOpts); 409f8f6129861f3972dab2c5a6cde29711ac780a7d0Chris Lattner return llvm::MemoryBuffer::getFile(FilePath.c_str(), ErrorStr, 410f8f6129861f3972dab2c5a6cde29711ac780a7d0Chris Lattner Entry->getSize()); 41175dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner} 41267452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 413f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager:: 41475dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) { 415efc4be242b8c8f076ad4addd3598c4853ec50ac7Chris Lattner if (FileSystemOpts.WorkingDir.empty()) 41675dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner return llvm::MemoryBuffer::getFile(Filename, ErrorStr); 41767452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 41867452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner llvm::sys::Path FilePath(Filename); 419389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FixupRelativePath(FilePath, FileSystemOpts); 42075dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner return llvm::MemoryBuffer::getFile(FilePath.c_str(), ErrorStr); 421389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 422389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 42310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// getStatValue - Get the 'stat' information for the specified path, using the 42410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// cache to accellerate it if possible. This returns true if the path does not 42510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// exist or false if it exists. 426f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// 427f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// The isForDir member indicates whether this is a directory lookup or not. 428f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// This will return failure if the lookup isn't the expected kind. 429f9f7766846a205bc900b578f944567e679b221aaChris Lattnerbool FileManager::getStatValue(const char *Path, struct stat &StatBuf, 430898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int *FileDescriptor) { 43110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 43210e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // absolute! 43311aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner if (FileSystemOpts.WorkingDir.empty()) 434898a061f69e1145bf89a987c08203132b9922a3cChris Lattner return FileSystemStatCache::get(Path, StatBuf, FileDescriptor, 435898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 43610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 43710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner llvm::sys::Path FilePath(Path); 438389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FixupRelativePath(FilePath, FileSystemOpts); 43911aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner 440898a061f69e1145bf89a987c08203132b9922a3cChris Lattner return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor, 441898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 442389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 443389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 44410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 44510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 4465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 4476cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "\n*** File Manager Stats:\n"; 4486cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << UniqueFiles.size() << " files found, " 4496cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << UniqueDirs.size() << " dirs found.\n"; 4506cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumDirLookups << " dir lookups, " 4516cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumDirCacheMisses << " dir cache misses.\n"; 4526cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumFileLookups << " file lookups, " 4536cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumFileCacheMisses << " file cache misses.\n"; 4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4556cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 4565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4574fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor 458