FileManager.cpp revision 146d57fd5135a134bcdaaf402157c070cde9e4a1
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" 2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Config/llvm-config.h" 24fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer#include "llvm/Support/FileSystem.h" 25389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "llvm/Support/MemoryBuffer.h" 2603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 2755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 283a321e23f66128dbb986343927456ff6702af617Michael J. Spencer#include "llvm/Support/system_error.h" 29458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <map> 30458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <set> 31458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <string> 32291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner 33291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner// FIXME: This is terrible, we need this for ::close. 34291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#if !defined(_MSC_VER) && !defined(__MINGW32__) 35291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <unistd.h> 36291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <sys/uio.h> 37291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#else 38291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <io.h> 396a1f49423baf6fa0358f396f0d926a3263cb5ff9Daniel Dunbar#ifndef S_ISFIFO 406a1f49423baf6fa0358f396f0d926a3263cb5ff9Daniel Dunbar#define S_ISFIFO(x) (0) 416a1f49423baf6fa0358f396f0d926a3263cb5ff9Daniel Dunbar#endif 42291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#endif 43713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#if defined(LLVM_ON_UNIX) 44adeb7822cb7947194fef0e12d2d6583ccb8240b5Dmitri Gribenko#include <limits.h> 45713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#endif 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 513d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 533d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 55f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// NON_EXISTENT_FILE - A special value distinct from null that is used to 56f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// represent a filename that doesn't exist on the disk. 57f9f7766846a205bc900b578f944567e679b221aaChris Lattner#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 58f9f7766846a205bc900b578f944567e679b221aaChris Lattner 59f9f7766846a205bc900b578f944567e679b221aaChris Lattner 60f9f7766846a205bc900b578f944567e679b221aaChris LattnerFileEntry::~FileEntry() { 61f9f7766846a205bc900b578f944567e679b221aaChris Lattner // If this FileEntry owns an open file descriptor that never got used, close 62f9f7766846a205bc900b578f944567e679b221aaChris Lattner // it. 63f9f7766846a205bc900b578f944567e679b221aaChris Lattner if (FD != -1) ::close(FD); 64f9f7766846a205bc900b578f944567e679b221aaChris Lattner} 65f9f7766846a205bc900b578f944567e679b221aaChris Lattner 66ce36ecd5a509af8fc5924d21694df36e8bc94a95Daniel Dunbarbool FileEntry::isNamedPipe() const { 676a1f49423baf6fa0358f396f0d926a3263cb5ff9Daniel Dunbar return S_ISFIFO(FileMode); 68ce36ecd5a509af8fc5924d21694df36e8bc94a95Daniel Dunbar} 69ce36ecd5a509af8fc5924d21694df36e8bc94a95Daniel Dunbar 70cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 71cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 72cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 73cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace { 771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::string GetFullPath(const char *relPath) { 786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek char *absPathStrPtr = _fullpath(NULL, relPath, 0); 796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek assert(absPathStrPtr && "_fullpath() returned NULL!"); 806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string absPath(absPathStrPtr); 826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 836bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek free(absPathStrPtr); 846bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return absPath; 856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 876bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 886bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 896bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from full path to existing directories/files. 906bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::StringMap<DirectoryEntry> UniqueDirs; 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 949b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getDirectory - Return an existing DirectoryEntry with the given 959b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// name if there is already one; otherwise create and return a 969b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed DirectoryEntry. 979b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry &getDirectory(const char *Name, 989b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const struct stat & /*StatBuf*/) { 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 100f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueDirs.GetOrCreateValue(FullPath).getValue(); 1016bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 103f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 1046bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1056bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 1086bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 10975368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 1106bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1116bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1129b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getFile - Return an existing FileEntry with the given name if 1139b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// there is already one; otherwise create and return a 1149b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed FileEntry. 1159b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FileEntry &getFile(const char *Name, const struct stat & /*StatBuf*/) { 1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 1179b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 11890c7892b699c5405a81bcc339432ba2f4b50e0d6Benjamin Kramer // Lowercase string because Windows filesystem is case insensitive. 11990c7892b699c5405a81bcc339432ba2f4b50e0d6Benjamin Kramer FullPath = StringRef(FullPath).lower(); 120f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueFiles.GetOrCreateValue(FullPath).getValue(); 1216bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 123f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1243ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 125be779598aa70a71c56e5d576947ade53e249c602Axel Naumann void erase(const FileEntry *Entry) { 126be779598aa70a71c56e5d576947ade53e249c602Axel Naumann std::string FullPath(GetFullPath(Entry->getName())); 127be779598aa70a71c56e5d576947ade53e249c602Axel Naumann 128be779598aa70a71c56e5d576947ade53e249c602Axel Naumann // Lowercase string because Windows filesystem is case insensitive. 129be779598aa70a71c56e5d576947ade53e249c602Axel Naumann FullPath = StringRef(FullPath).lower(); 130be779598aa70a71c56e5d576947ade53e249c602Axel Naumann UniqueFiles.erase(FullPath); 131be779598aa70a71c56e5d576947ade53e249c602Axel Naumann } 1326bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 134cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 135cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 136cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 137cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 1396bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1406bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1416bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1436bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1446bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1459b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getDirectory - Return an existing DirectoryEntry with the given 1469b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// ID's if there is already one; otherwise create and return a 1479b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed DirectoryEntry. 1489b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry &getDirectory(const char * /*Name*/, 1499b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const struct stat &StatBuf) { 1506bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1516bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 153f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 1546bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1556bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1566bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1619b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getFile - Return an existing FileEntry with the given ID's if 1629b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// there is already one; otherwise create and return a 1639b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed FileEntry. 1649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FileEntry &getFile(const char * /*Name*/, const struct stat &StatBuf) { 1656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1666bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 16896438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_ino, 16996438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_mode)).first); 1706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 172f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1733ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 1745ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann void erase(const FileEntry *Entry) { UniqueFiles.erase(*Entry); } 1756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1776bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif 1786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 179cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 180cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 181cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 1826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1837ad97ffa631af6ad678c79b38341ac995f347ce9Chris LattnerFileManager::FileManager(const FileSystemOptions &FSO) 1847ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner : FileSystemOpts(FSO), 1859b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UniqueRealDirs(*new UniqueDirContainer()), 1869b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UniqueRealFiles(*new UniqueFileContainer()), 1879b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { 1886bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 1896bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 1906bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1916bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1926bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 1939b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete &UniqueRealDirs; 1949b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete &UniqueRealFiles; 195f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) 196f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner delete VirtualFileEntries[i]; 1979b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i) 1989b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete VirtualDirectoryEntries[i]; 1996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 2006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 20110e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::addStatCache(FileSystemStatCache *statCache, 20210e286aa8d39fb51a21412850265d9dae74613eeChris Lattner bool AtBeginning) { 20352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(statCache && "No stat cache provided?"); 20452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (AtBeginning || StatCache.get() == 0) { 20552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor statCache->setNextStatCache(StatCache.take()); 20652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(statCache); 20752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 20852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 20952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 21010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *LastCache = StatCache.get(); 21152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (LastCache->getNextStatCache()) 21252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache = LastCache->getNextStatCache(); 21352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 21452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache->setNextStatCache(statCache); 21552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 21652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 21710e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::removeStatCache(FileSystemStatCache *statCache) { 21852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (!statCache) 21952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 22052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 22152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (StatCache.get() == statCache) { 22252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // This is the first stat cache. 22352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(StatCache->takeNextStatCache()); 22452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 22552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 22652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 22752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // Find the stat cache in the list. 22810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *PrevCache = StatCache.get(); 22952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (PrevCache && PrevCache->getNextStatCache() != statCache) 23052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache = PrevCache->getNextStatCache(); 231f9f7766846a205bc900b578f944567e679b221aaChris Lattner 232f9f7766846a205bc900b578f944567e679b221aaChris Lattner assert(PrevCache && "Stat cache not found for removal"); 233f9f7766846a205bc900b578f944567e679b221aaChris Lattner PrevCache->setNextStatCache(statCache->getNextStatCache()); 23452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 23552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 23698be86038b1e891a05583061c55dfa974150eb2cManuel Klimekvoid FileManager::clearStatCaches() { 23798be86038b1e891a05583061c55dfa974150eb2cManuel Klimek StatCache.reset(0); 23898be86038b1e891a05583061c55dfa974150eb2cManuel Klimek} 23998be86038b1e891a05583061c55dfa974150eb2cManuel Klimek 240057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in. 2419b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// Filename can point to either a real file or a virtual file. 242057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 2436e975c4517958bcc11c834336d340797356058dbDouglas Gregor StringRef Filename, 2446e975c4517958bcc11c834336d340797356058dbDouglas Gregor bool CacheFailure) { 24521af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (Filename.empty()) 24621af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan return NULL; 2479b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 24821af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) 24921af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan return NULL; // If Filename is a directory. 250aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 2515f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef DirName = llvm::sys::path::parent_path(Filename); 252f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Use the current directory if file has no path component. 25321af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.empty()) 25421af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan DirName = "."; 255aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 2566e975c4517958bcc11c834336d340797356058dbDouglas Gregor return FileMgr.getDirectory(DirName, CacheFailure); 257057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 258057e567f1b375190779e5341f42861896cdee442Douglas Gregor 2599b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// Add all ancestors of the given path (pointing to either a file or 2609b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// a directory) as virtual directories. 2615f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid FileManager::addAncestorsAsVirtualDirs(StringRef Path) { 2625f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef DirName = llvm::sys::path::parent_path(Path); 26321af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.empty()) 2649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return; 2659b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2669b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 2679b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries.GetOrCreateValue(DirName); 2689b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2699b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // When caching a virtual directory, we always cache its ancestors 2709b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // at the same time. Therefore, if DirName is already in the cache, 2719b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // we don't need to recurse as its ancestors must also already be in 2729b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // the cache. 2739b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (NamedDirEnt.getValue()) 2749b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return; 2759b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2769b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Add the virtual directory to the cache. 2779b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry *UDE = new DirectoryEntry; 2789b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UDE->Name = NamedDirEnt.getKeyData(); 2799b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan NamedDirEnt.setValue(UDE); 2809b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan VirtualDirectoryEntries.push_back(UDE); 2819b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2829b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Recursively add the other ancestors. 2839b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan addAncestorsAsVirtualDirs(DirName); 2849b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan} 2859b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2866e975c4517958bcc11c834336d340797356058dbDouglas Gregorconst DirectoryEntry *FileManager::getDirectory(StringRef DirName, 2876e975c4517958bcc11c834336d340797356058dbDouglas Gregor bool CacheFailure) { 288759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi // stat doesn't like trailing separators except for root directory. 289678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'. 290678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi // (though it can strip '\\') 291759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi if (DirName.size() > 1 && 292759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi DirName != llvm::sys::path::root_path(DirName) && 293759a4b40cab9dd04683a548f998ebe2e443ca6b4NAKAMURA Takumi llvm::sys::path::is_separator(DirName.back())) 294678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi DirName = DirName.substr(0, DirName.size()-1); 295146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola#ifdef LLVM_ON_WIN32 296146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola // Fixing a problem with "clang C:test.c" on Windows. 297146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola // Stat("C:") does not recognize "C:" as a valid directory 298146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola std::string DirNameStr; 299146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola if (DirName.size() > 1 && DirName.back() == ':' && 300146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola DirName.equals_lower(llvm::sys::path::root_name(DirName))) { 301146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola DirNameStr = DirName.str() + '.'; 302146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola DirName = DirNameStr; 303146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola } 304146d57fd5135a134bcdaaf402157c070cde9e4a1Rafael Espindola#endif 305678a3ead409516d8e24831297b9a3bb98f6217c3NAKAMURA Takumi 3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 3089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries.GetOrCreateValue(DirName); 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3109b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // See if there was already an entry in the map. Note that the map 3119b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // contains both virtual and real directories. 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 3133d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 3193d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 3229b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // SeenDirEntries map. 3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 3241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 327e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis if (getStatValue(InterndDirName, StatBuf, false, 0/*directory lookup*/)) { 3289b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // There's no real directory at the given path. 3296e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (!CacheFailure) 3306e975c4517958bcc11c834336d340797356058dbDouglas Gregor SeenDirEntries.erase(DirName); 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3329b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 3336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 3349b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // It exists. See if we have already opened a directory with the 3359b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // same inode (this occurs on Unix-like systems when one dir is 3369b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // symlinked to another, for example) or the same path (on 3379b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Windows). 3389b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry &UDE = UniqueRealDirs.getDirectory(InterndDirName, StatBuf); 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 3419b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (!UDE.getName()) { 3429b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // We don't have this directory yet, add it. We use the string 3439b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // key from the SeenDirEntries map as the string. 3449b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UDE.Name = InterndDirName; 3459b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 3461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3506e975c4517958bcc11c834336d340797356058dbDouglas Gregorconst FileEntry *FileManager::getFile(StringRef Filename, bool openFile, 3516e975c4517958bcc11c834336d340797356058dbDouglas Gregor bool CacheFailure) { 3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 3555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 3569b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenFileEntries.GetOrCreateValue(Filename); 3575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 3595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 3603d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 3621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 3663d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 3675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 3699b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // SeenFileEntries map. 3705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 372f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // Look up the directory for the file. When looking up something like 373f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // sys/foo.h we'll discover all of the search directories that have a 'sys' 374f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // subdirectory. This will let us avoid having to waste time on known-to-fail 375f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // searches when we go to find sys/bar.h, because all the search directories 376f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // without a 'sys' subdir will get a cached failure result. 3776e975c4517958bcc11c834336d340797356058dbDouglas Gregor const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 3786e975c4517958bcc11c834336d340797356058dbDouglas Gregor CacheFailure); 3796e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (DirInfo == 0) { // Directory doesn't exist, file can't exist. 3806e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (!CacheFailure) 3816e975c4517958bcc11c834336d340797356058dbDouglas Gregor SeenFileEntries.erase(Filename); 3826e975c4517958bcc11c834336d340797356058dbDouglas Gregor 383057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 3846e975c4517958bcc11c834336d340797356058dbDouglas Gregor } 3856e975c4517958bcc11c834336d340797356058dbDouglas Gregor 3865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 390898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int FileDescriptor = -1; 3915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 392e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis if (getStatValue(InterndFileName, StatBuf, true, 393e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis openFile ? &FileDescriptor : 0)) { 3949b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // There's no real file at the given path. 3956e975c4517958bcc11c834336d340797356058dbDouglas Gregor if (!CacheFailure) 3966e975c4517958bcc11c834336d340797356058dbDouglas Gregor SeenFileEntries.erase(Filename); 3976e975c4517958bcc11c834336d340797356058dbDouglas Gregor 3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3999b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 4001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4013cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis if (FileDescriptor != -1 && !openFile) { 4023cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis close(FileDescriptor); 4033cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis FileDescriptor = -1; 4043cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis } 4053cd0128ce49abe658d1858c541e836e57959e04aArgyrios Kyrtzidis 406bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 4089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf); 4091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 411898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (UFE.getName()) { // Already have an entry with this inode, return it. 412898a061f69e1145bf89a987c08203132b9922a3cChris Lattner // If the stat process opened the file, close it to avoid a FD leak. 413898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (FileDescriptor != -1) 414898a061f69e1145bf89a987c08203132b9922a3cChris Lattner close(FileDescriptor); 4159b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 417898a061f69e1145bf89a987c08203132b9922a3cChris Lattner } 4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 4209b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // FIXME: Change the name to be a char* that points back to the 4219b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // 'SeenFileEntries' key. 4225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 4255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 4265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 427898a061f69e1145bf89a987c08203132b9922a3cChris Lattner UFE.FD = FileDescriptor; 4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 4295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 431057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry * 4325f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerFileManager::getVirtualFile(StringRef Filename, off_t Size, 43339b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner time_t ModificationTime) { 434057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileLookups; 435057e567f1b375190779e5341f42861896cdee442Douglas Gregor 436057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 437057e567f1b375190779e5341f42861896cdee442Douglas Gregor llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 4389b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenFileEntries.GetOrCreateValue(Filename); 439057e567f1b375190779e5341f42861896cdee442Douglas Gregor 440057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 44104331169f04198eb769925fa17696a21989c9d8bAxel Naumann if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE) 44204331169f04198eb769925fa17696a21989c9d8bAxel Naumann return NamedFileEnt.getValue(); 443057e567f1b375190779e5341f42861896cdee442Douglas Gregor 444057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileCacheMisses; 445057e567f1b375190779e5341f42861896cdee442Douglas Gregor 446057e567f1b375190779e5341f42861896cdee442Douglas Gregor // By default, initialize it to invalid. 447057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(NON_EXISTENT_FILE); 448057e567f1b375190779e5341f42861896cdee442Douglas Gregor 4499b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan addAncestorsAsVirtualDirs(Filename); 4508ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor FileEntry *UFE = 0; 4519b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4529b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Now that all ancestors of Filename are in the cache, the 4539b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // following call is guaranteed to find the DirectoryEntry from the 4549b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // cache. 4556e975c4517958bcc11c834336d340797356058dbDouglas Gregor const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename, 4566e975c4517958bcc11c834336d340797356058dbDouglas Gregor /*CacheFailure=*/true); 4579b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan assert(DirInfo && 4589b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan "The directory of a virtual file should already be in the cache."); 4599b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4609b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Check to see if the file exists. If so, drop the virtual file 4619b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan struct stat StatBuf; 4629b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const char *InterndFileName = NamedFileEnt.getKeyData(); 463e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis if (getStatValue(InterndFileName, StatBuf, true, 0) == 0) { 4649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan StatBuf.st_size = Size; 4659b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan StatBuf.st_mtime = ModificationTime; 4669b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UFE = &UniqueRealFiles.getFile(InterndFileName, StatBuf); 4679b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4689b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan NamedFileEnt.setValue(UFE); 4699b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4709b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If we had already opened this file, close it now so we don't 4719b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // leak the descriptor. We're not going to use the file 4729b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // descriptor anyway, since this is a virtual file. 4739b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (UFE->FD != -1) { 4749b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan close(UFE->FD); 4759b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UFE->FD = -1; 4768ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 4779b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4789b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If we already have an entry with this inode, return it. 4799b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (UFE->getName()) 4809b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return UFE; 4818ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 482057e567f1b375190779e5341f42861896cdee442Douglas Gregor 4838ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor if (!UFE) { 4848ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor UFE = new FileEntry(); 4858ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor VirtualFileEntries.push_back(UFE); 4868ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor NamedFileEnt.setValue(UFE); 4878ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 488057e567f1b375190779e5341f42861896cdee442Douglas Gregor 489f9f7766846a205bc900b578f944567e679b221aaChris Lattner UFE->Name = InterndFileName; 490057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Size = Size; 491057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->ModTime = ModificationTime; 492057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Dir = DirInfo; 493057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->UID = NextFileUID++; 4948ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor UFE->FD = -1; 495057e567f1b375190779e5341f42861896cdee442Douglas Gregor return UFE; 496057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 497057e567f1b375190779e5341f42861896cdee442Douglas Gregor 4985f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { 4995f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef pathRef(path.data(), path.size()); 500af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson 5012e2468e2d2ccbb9a38fe3b6b754009af7e5d39a9Anders Carlsson if (FileSystemOpts.WorkingDir.empty() 5022e2468e2d2ccbb9a38fe3b6b754009af7e5d39a9Anders Carlsson || llvm::sys::path::is_absolute(pathRef)) 503256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer return; 504256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer 505f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> NewPath(FileSystemOpts.WorkingDir); 506af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::sys::path::append(NewPath, pathRef); 50767452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner path = NewPath; 50867452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner} 50967452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 51075dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattnerllvm::MemoryBuffer *FileManager:: 511ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios KyrtzidisgetBufferForFile(const FileEntry *Entry, std::string *ErrorStr, 512ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis bool isVolatile) { 5136f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<llvm::MemoryBuffer> Result; 5143a321e23f66128dbb986343927456ff6702af617Michael J. Spencer llvm::error_code ec; 5155cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner 516ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis uint64_t FileSize = Entry->getSize(); 517ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis // If there's a high enough chance that the file have changed since we 518ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis // got its size, force a stat before opening it. 519ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis if (isVolatile) 520ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis FileSize = -1; 521ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis 522a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis const char *Filename = Entry->getName(); 523a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis // If the file is already open, use the open file descriptor. 524a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis if (Entry->FD != -1) { 525ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize); 526a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis if (ErrorStr) 527a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis *ErrorStr = ec.message(); 528a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis 529a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis close(Entry->FD); 530a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis Entry->FD = -1; 531a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis return Result.take(); 532a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis } 533a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis 534a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis // Otherwise, open the file. 535a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis 536a8d530e3ad52cca33a81185ccc9518eab23ddb11Argyrios Kyrtzidis if (FileSystemOpts.WorkingDir.empty()) { 537ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize); 5384eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 5393a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 5404eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 5415cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner } 542af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson 543f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Entry->getName()); 54403fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 545ff398965a5abfaf5bc47bc022876f56a28e5b9a7Argyrios Kyrtzidis ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize); 5464eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 5473a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 5484eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 54975dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner} 55067452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 551f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager:: 5525f9e272e632e951b1efe824cd16acb4d96077930Chris LattnergetBufferForFile(StringRef Filename, std::string *ErrorStr) { 5536f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<llvm::MemoryBuffer> Result; 5543a321e23f66128dbb986343927456ff6702af617Michael J. Spencer llvm::error_code ec; 5553a321e23f66128dbb986343927456ff6702af617Michael J. Spencer if (FileSystemOpts.WorkingDir.empty()) { 5564eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(Filename, Result); 5574eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 5583a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 5594eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 5603a321e23f66128dbb986343927456ff6702af617Michael J. Spencer } 5613a321e23f66128dbb986343927456ff6702af617Michael J. Spencer 562f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Filename); 56303fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 5644eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result); 5654eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 5663a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 5674eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 568389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 569389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 5709b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// getStatValue - Get the 'stat' information for the specified path, 5719b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// using the cache to accelerate it if possible. This returns true 5729b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// if the path points to a virtual file or does not exist, or returns 5739b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// false if it's an existent real file. If FileDescriptor is NULL, 5749b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// do directory look-up instead of file look-up. 575f9f7766846a205bc900b578f944567e679b221aaChris Lattnerbool FileManager::getStatValue(const char *Path, struct stat &StatBuf, 576e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis bool isFile, int *FileDescriptor) { 57710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 57810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // absolute! 57911aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner if (FileSystemOpts.WorkingDir.empty()) 580e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis return FileSystemStatCache::get(Path, StatBuf, isFile, FileDescriptor, 581898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 5829b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 583f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Path); 58403fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 58511aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner 586e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis return FileSystemStatCache::get(FilePath.c_str(), StatBuf, 587e5d30e3b403539b10aaa52f03875a2243bf88904Argyrios Kyrtzidis isFile, FileDescriptor, StatCache.get()); 588389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 589389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 5905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerbool FileManager::getNoncachedStatValue(StringRef Path, 5917dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson struct stat &StatBuf) { 592f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> FilePath(Path); 5937dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson FixupRelativePath(FilePath); 5947dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson 5957dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson return ::stat(FilePath.c_str(), &StatBuf) != 0; 5967dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson} 5977dbafb3ade491a41100c97597209455ee10c537dAnders Carlsson 5985ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumannvoid FileManager::invalidateCache(const FileEntry *Entry) { 5995ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann assert(Entry && "Cannot invalidate a NULL FileEntry"); 6003ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 6013ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann SeenFileEntries.erase(Entry->getName()); 6025ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann 6035ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann // FileEntry invalidation should not block future optimizations in the file 6045ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann // caches. Possible alternatives are cache truncation (invalidate last N) or 6055ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann // invalidation of the whole cache. 6065ba0559f2f0ddd62de16547af514dbaf93b79585Axel Naumann UniqueRealFiles.erase(Entry); 6073ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann} 6083ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 6093ce42c37b0ef6b10538f5040a33d19a6e6988d05Axel Naumann 610cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregorvoid FileManager::GetUniqueIDMapping( 6115f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<const FileEntry *> &UIDToFiles) const { 612cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles.clear(); 613cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles.resize(NextFileUID); 614cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 615cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // Map file entries 616cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator 6179b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); 618cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor FE != FEEnd; ++FE) 619cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE) 620cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); 621cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 622cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // Map virtual file entries 62309d19efaa147762f84aed55efa7930bb3616a4e5Craig Topper for (SmallVectorImpl<FileEntry *>::const_iterator 624cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end(); 625cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor VFE != VFEEnd; ++VFE) 626cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (*VFE && *VFE != NON_EXISTENT_FILE) 627cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles[(*VFE)->getUID()] = *VFE; 628cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor} 62910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 630d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidisvoid FileManager::modifyFileEntry(FileEntry *File, 631d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis off_t Size, time_t ModificationTime) { 632d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis File->Size = Size; 633d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis File->ModTime = ModificationTime; 634d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis} 635d54dff026b02303a35147224de72bb44cbb53c79Argyrios Kyrtzidis 636713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas GregorStringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { 637713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor // FIXME: use llvm::sys::fs::canonical() when it gets implemented 638713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#ifdef LLVM_ON_UNIX 639713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known 640713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor = CanonicalDirNames.find(Dir); 641713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor if (Known != CanonicalDirNames.end()) 642713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor return Known->second; 643713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor 644713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor StringRef CanonicalName(Dir->getName()); 645713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor char CanonicalNameBuf[PATH_MAX]; 646713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor if (realpath(Dir->getName(), CanonicalNameBuf)) { 647713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor unsigned Len = strlen(CanonicalNameBuf); 648713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor char *Mem = static_cast<char *>(CanonicalNameStorage.Allocate(Len, 1)); 649713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor memcpy(Mem, CanonicalNameBuf, Len); 650713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor CanonicalName = StringRef(Mem, Len); 651713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor } 652713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor 653713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName)); 654713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor return CanonicalName; 655713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#else 656713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor return StringRef(Dir->getName()); 657713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor#endif 658713b7c011869f177dc76e6df4f7f44b1bd073bb0Douglas Gregor} 65910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 6605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 6616cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "\n*** File Manager Stats:\n"; 6629b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::errs() << UniqueRealFiles.size() << " real files found, " 6639b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan << UniqueRealDirs.size() << " real dirs found.\n"; 6649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::errs() << VirtualFileEntries.size() << " virtual files found, " 6659b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan << VirtualDirectoryEntries.size() << " virtual dirs found.\n"; 6666cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumDirLookups << " dir lookups, " 6676cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumDirCacheMisses << " dir cache misses.\n"; 6686cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumFileLookups << " file lookups, " 6696cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumFileCacheMisses << " file cache misses.\n"; 6701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6716cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 6725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 673