FileManager.cpp revision 03fd362dbf6fcd077df566fe2ac3165be668323b
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" 24fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer#include "llvm/Support/FileSystem.h" 25389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "llvm/Support/MemoryBuffer.h" 26d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner#include "llvm/Support/raw_ostream.h" 2703013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 283a321e23f66128dbb986343927456ff6702af617Michael J. Spencer#include "llvm/Support/system_error.h" 296bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#include "llvm/Config/config.h" 30458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <map> 31458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <set> 32458fb10ef5ba2d7b375c6c64095c1458af0a5be3Benjamin Kramer#include <string> 33291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner 34291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner// FIXME: This is terrible, we need this for ::close. 35291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#if !defined(_MSC_VER) && !defined(__MINGW32__) 36291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <unistd.h> 37291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <sys/uio.h> 38291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#else 39291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#include <io.h> 40291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#endif 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 463d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 483d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 50f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// NON_EXISTENT_FILE - A special value distinct from null that is used to 51f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// represent a filename that doesn't exist on the disk. 52f9f7766846a205bc900b578f944567e679b221aaChris Lattner#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 53f9f7766846a205bc900b578f944567e679b221aaChris Lattner 54f9f7766846a205bc900b578f944567e679b221aaChris Lattner 55f9f7766846a205bc900b578f944567e679b221aaChris LattnerFileEntry::~FileEntry() { 56f9f7766846a205bc900b578f944567e679b221aaChris Lattner // If this FileEntry owns an open file descriptor that never got used, close 57f9f7766846a205bc900b578f944567e679b221aaChris Lattner // it. 58f9f7766846a205bc900b578f944567e679b221aaChris Lattner if (FD != -1) ::close(FD); 59f9f7766846a205bc900b578f944567e679b221aaChris Lattner} 60f9f7766846a205bc900b578f944567e679b221aaChris Lattner 61cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 62cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 63cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 64cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 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: 859b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getDirectory - Return an existing DirectoryEntry with the given 869b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// name if there is already one; otherwise create and return a 879b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed DirectoryEntry. 889b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry &getDirectory(const char *Name, 899b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const struct stat & /*StatBuf*/) { 906bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 91f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueDirs.GetOrCreateValue(FullPath).getValue(); 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 956bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 966bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 976bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 986bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 10075368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 1016bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1026bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1039b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getFile - Return an existing FileEntry with the given name if 1049b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// there is already one; otherwise create and return a 1059b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed FileEntry. 1069b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FileEntry &getFile(const char *Name, const struct stat & /*StatBuf*/) { 1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 1089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 109c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner // LowercaseString because Windows filesystem is case insensitive. 110c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner FullPath = llvm::LowercaseString(FullPath); 111f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueFiles.GetOrCreateValue(FullPath).getValue(); 1126bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1136bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 114f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 117cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 118cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 119cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 120cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 1216bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1276bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1289b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getDirectory - Return an existing DirectoryEntry with the given 1299b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// ID's if there is already one; otherwise create and return a 1309b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed DirectoryEntry. 1319b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry &getDirectory(const char * /*Name*/, 1329b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const struct stat &StatBuf) { 1336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1346bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1356bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 136f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1396bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1406bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1416bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1426bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1436bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1449b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// getFile - Return an existing FileEntry with the given ID's if 1459b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// there is already one; otherwise create and return a 1469b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan /// default-constructed FileEntry. 1479b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FileEntry &getFile(const char * /*Name*/, const struct stat &StatBuf) { 1486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1496bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1506bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 15196438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_ino, 15296438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_mode)).first); 1536bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1546bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 155f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1566bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1576bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif 1596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 160cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 161cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 162cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 1636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1647ad97ffa631af6ad678c79b38341ac995f347ce9Chris LattnerFileManager::FileManager(const FileSystemOptions &FSO) 1657ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner : FileSystemOpts(FSO), 1669b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UniqueRealDirs(*new UniqueDirContainer()), 1679b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UniqueRealFiles(*new UniqueFileContainer()), 1689b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) { 1696bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 1706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 1716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1736bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 1749b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete &UniqueRealDirs; 1759b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete &UniqueRealFiles; 176f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) 177f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner delete VirtualFileEntries[i]; 1789b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i) 1799b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan delete VirtualDirectoryEntries[i]; 1806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 18210e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::addStatCache(FileSystemStatCache *statCache, 18310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner bool AtBeginning) { 18452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(statCache && "No stat cache provided?"); 18552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (AtBeginning || StatCache.get() == 0) { 18652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor statCache->setNextStatCache(StatCache.take()); 18752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(statCache); 18852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 18952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 19052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 19110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *LastCache = StatCache.get(); 19252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (LastCache->getNextStatCache()) 19352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache = LastCache->getNextStatCache(); 19452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 19552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache->setNextStatCache(statCache); 19652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 19752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 19810e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::removeStatCache(FileSystemStatCache *statCache) { 19952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (!statCache) 20052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 20152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 20252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (StatCache.get() == statCache) { 20352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // This is the first stat cache. 20452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(StatCache->takeNextStatCache()); 20552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 20652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 20752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 20852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // Find the stat cache in the list. 20910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *PrevCache = StatCache.get(); 21052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (PrevCache && PrevCache->getNextStatCache() != statCache) 21152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache = PrevCache->getNextStatCache(); 212f9f7766846a205bc900b578f944567e679b221aaChris Lattner 213f9f7766846a205bc900b578f944567e679b221aaChris Lattner assert(PrevCache && "Stat cache not found for removal"); 214f9f7766846a205bc900b578f944567e679b221aaChris Lattner PrevCache->setNextStatCache(statCache->getNextStatCache()); 21552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 21652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 217057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in. 2189b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// Filename can point to either a real file or a virtual file. 219057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 22039b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner llvm::StringRef Filename) { 22121af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (Filename.empty()) 22221af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan return NULL; 2239b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 22421af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (llvm::sys::path::is_separator(Filename[Filename.size() - 1])) 22521af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan return NULL; // If Filename is a directory. 226aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 22721af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan llvm::StringRef DirName = llvm::sys::path::parent_path(Filename); 228f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Use the current directory if file has no path component. 22921af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.empty()) 23021af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan DirName = "."; 231aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 23221af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan return FileMgr.getDirectory(DirName); 233057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 234057e567f1b375190779e5341f42861896cdee442Douglas Gregor 2359b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// Add all ancestors of the given path (pointing to either a file or 2369b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// a directory) as virtual directories. 2379b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wanvoid FileManager::addAncestorsAsVirtualDirs(llvm::StringRef Path) { 23821af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan llvm::StringRef DirName = llvm::sys::path::parent_path(Path); 23921af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.empty()) 2409b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return; 2419b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2429b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 2439b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries.GetOrCreateValue(DirName); 2449b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2459b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // When caching a virtual directory, we always cache its ancestors 2469b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // at the same time. Therefore, if DirName is already in the cache, 2479b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // we don't need to recurse as its ancestors must also already be in 2489b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // the cache. 2499b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (NamedDirEnt.getValue()) 2509b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return; 2519b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2529b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Add the virtual directory to the cache. 2539b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry *UDE = new DirectoryEntry; 2549b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UDE->Name = NamedDirEnt.getKeyData(); 2559b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan NamedDirEnt.setValue(UDE); 2569b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan VirtualDirectoryEntries.push_back(UDE); 2579b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2589b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Recursively add the other ancestors. 2599b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan addAncestorsAsVirtualDirs(DirName); 2609b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan} 2619b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 2629b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// getDirectory - Lookup, cache, and verify the specified directory 2639b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// (real or virtual). This returns NULL if the directory doesn't 2649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// exist. 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 2669b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wanconst DirectoryEntry *FileManager::getDirectory(llvm::StringRef DirName) { 2679a6ac540bab63380a4a78d8fad87f23c50878685John Thompson // stat doesn't like trailing separators (at least on Windows). 26821af8878b96ab1f9b077407ca3c512e5dc5d0ad6Zhanyong Wan if (DirName.size() > 1 && llvm::sys::path::is_separator(DirName.back())) 2699b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirName = DirName.substr(0, DirName.size()-1); 2709a6ac540bab63380a4a78d8fad87f23c50878685John Thompson 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 2739b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenDirEntries.GetOrCreateValue(DirName); 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2759b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // See if there was already an entry in the map. Note that the map 2769b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // contains both virtual and real directories. 2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 2783d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 2801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2843d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 2879b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // SeenDirEntries map. 2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 2891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 2929b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) { 2939b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // There's no real directory at the given path. 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2959b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 2966bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 2979b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // It exists. See if we have already opened a directory with the 2989b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // same inode (this occurs on Unix-like systems when one dir is 2999b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // symlinked to another, for example) or the same path (on 3009b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Windows). 3019b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan DirectoryEntry &UDE = UniqueRealDirs.getDirectory(InterndDirName, StatBuf); 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 3049b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (!UDE.getName()) { 3059b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // We don't have this directory yet, add it. We use the string 3069b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // key from the SeenDirEntries map as the string. 3079b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UDE.Name = InterndDirName; 3089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3139b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// getFile - Lookup, cache, and verify the specified file (real or 3149b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// virtual). This returns NULL if the file doesn't exist. 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 31639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst FileEntry *FileManager::getFile(llvm::StringRef Filename) { 3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 3181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 3219b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenFileEntries.GetOrCreateValue(Filename); 3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 3253d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 3313d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 3349b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // SeenFileEntries map. 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 3361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 337f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // Look up the directory for the file. When looking up something like 338f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // sys/foo.h we'll discover all of the search directories that have a 'sys' 339f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // subdirectory. This will let us avoid having to waste time on known-to-fail 340f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // searches when we go to find sys/bar.h, because all the search directories 341f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // without a 'sys' subdir will get a cached failure result. 34239b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); 343057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (DirInfo == 0) // Directory doesn't exist, file can't exist. 344057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 345057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 350898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int FileDescriptor = -1; 3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 3529b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) { 3539b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // There's no real file at the given path. 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3559b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan } 3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 357bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 3585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 3599b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf); 3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 362898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (UFE.getName()) { // Already have an entry with this inode, return it. 363898a061f69e1145bf89a987c08203132b9922a3cChris Lattner // If the stat process opened the file, close it to avoid a FD leak. 364898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (FileDescriptor != -1) 365898a061f69e1145bf89a987c08203132b9922a3cChris Lattner close(FileDescriptor); 3669b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 3675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 368898a061f69e1145bf89a987c08203132b9922a3cChris Lattner } 3695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 3719b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // FIXME: Change the name to be a char* that points back to the 3729b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // 'SeenFileEntries' key. 3735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 3745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 3755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 3775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 378898a061f69e1145bf89a987c08203132b9922a3cChris Lattner UFE.FD = FileDescriptor; 3795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 382057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry * 383ec1b1cc006cef19e0a95d0ea6fbfd37d0d615066Benjamin KramerFileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, 38439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner time_t ModificationTime) { 385057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileLookups; 386057e567f1b375190779e5341f42861896cdee442Douglas Gregor 387057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 388057e567f1b375190779e5341f42861896cdee442Douglas Gregor llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 3899b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan SeenFileEntries.GetOrCreateValue(Filename); 390057e567f1b375190779e5341f42861896cdee442Douglas Gregor 391057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 39204331169f04198eb769925fa17696a21989c9d8bAxel Naumann if (NamedFileEnt.getValue() && NamedFileEnt.getValue() != NON_EXISTENT_FILE) 39304331169f04198eb769925fa17696a21989c9d8bAxel Naumann return NamedFileEnt.getValue(); 394057e567f1b375190779e5341f42861896cdee442Douglas Gregor 395057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileCacheMisses; 396057e567f1b375190779e5341f42861896cdee442Douglas Gregor 397057e567f1b375190779e5341f42861896cdee442Douglas Gregor // By default, initialize it to invalid. 398057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(NON_EXISTENT_FILE); 399057e567f1b375190779e5341f42861896cdee442Douglas Gregor 4009b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan addAncestorsAsVirtualDirs(Filename); 4018ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor FileEntry *UFE = 0; 4029b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4039b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Now that all ancestors of Filename are in the cache, the 4049b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // following call is guaranteed to find the DirectoryEntry from the 4059b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // cache. 40639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); 4079b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan assert(DirInfo && 4089b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan "The directory of a virtual file should already be in the cache."); 4099b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4109b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // Check to see if the file exists. If so, drop the virtual file 4119b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan int FileDescriptor = -1; 4129b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan struct stat StatBuf; 4139b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan const char *InterndFileName = NamedFileEnt.getKeyData(); 4149b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (getStatValue(InterndFileName, StatBuf, &FileDescriptor) == 0) { 4159b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If the stat process opened the file, close it to avoid a FD leak. 4169b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (FileDescriptor != -1) 4179b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan close(FileDescriptor); 4189b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4199b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan StatBuf.st_size = Size; 4209b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan StatBuf.st_mtime = ModificationTime; 4219b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UFE = &UniqueRealFiles.getFile(InterndFileName, StatBuf); 4229b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4239b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan NamedFileEnt.setValue(UFE); 4249b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4259b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If we had already opened this file, close it now so we don't 4269b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // leak the descriptor. We're not going to use the file 4279b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // descriptor anyway, since this is a virtual file. 4289b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (UFE->FD != -1) { 4299b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan close(UFE->FD); 4309b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan UFE->FD = -1; 4318ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 4329b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 4339b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan // If we already have an entry with this inode, return it. 4349b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan if (UFE->getName()) 4359b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan return UFE; 4368ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 437057e567f1b375190779e5341f42861896cdee442Douglas Gregor 4388ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor if (!UFE) { 4398ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor UFE = new FileEntry(); 4408ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor VirtualFileEntries.push_back(UFE); 4418ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor NamedFileEnt.setValue(UFE); 4428ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor } 443057e567f1b375190779e5341f42861896cdee442Douglas Gregor 444f9f7766846a205bc900b578f944567e679b221aaChris Lattner UFE->Name = InterndFileName; 445057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Size = Size; 446057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->ModTime = ModificationTime; 447057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Dir = DirInfo; 448057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->UID = NextFileUID++; 4498ef6c8cb6c5627240e2339fd7062c9873f821d7eDouglas Gregor UFE->FD = -1; 450057e567f1b375190779e5341f42861896cdee442Douglas Gregor return UFE; 451057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 452057e567f1b375190779e5341f42861896cdee442Douglas Gregor 453af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlssonvoid FileManager::FixupRelativePath(llvm::SmallVectorImpl<char> &path, 45467452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner const FileSystemOptions &FSOpts) { 455af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::StringRef pathRef(path.data(), path.size()); 456af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson 457af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson if (FSOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(pathRef)) 458256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer return; 459256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer 460256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer llvm::SmallString<128> NewPath(FSOpts.WorkingDir); 461af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::sys::path::append(NewPath, pathRef); 46267452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner path = NewPath; 46367452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner} 46467452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 46503fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlssonvoid FileManager::FixupRelativePath(llvm::SmallVectorImpl<char> &path) const { 46603fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(path, FileSystemOpts); 46703fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson} 46803fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson 46975dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattnerllvm::MemoryBuffer *FileManager:: 47075dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { 4714eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer llvm::OwningPtr<llvm::MemoryBuffer> Result; 4723a321e23f66128dbb986343927456ff6702af617Michael J. Spencer llvm::error_code ec; 4735cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner if (FileSystemOpts.WorkingDir.empty()) { 4745cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner const char *Filename = Entry->getName(); 4755cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner // If the file is already open, use the open file descriptor. 4765cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner if (Entry->FD != -1) { 4774eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, 4784eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer Entry->getSize()); 4794eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ErrorStr) 4803a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 481100f239df90c2576cfd6ce4fdcf3886033c00e26Rafael Espindola 482100f239df90c2576cfd6ce4fdcf3886033c00e26Rafael Espindola close(Entry->FD); 4835cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner Entry->FD = -1; 4844eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 4855cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner } 4865cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner 4875cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner // Otherwise, open the file. 4884eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize()); 4894eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4903a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4914eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 4925cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner } 493af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson 494af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::SmallString<128> FilePath(Entry->getName()); 49503fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 496af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, Entry->getSize()); 4974eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4983a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4994eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 50075dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner} 50167452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 502f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager:: 50375dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) { 5044eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer llvm::OwningPtr<llvm::MemoryBuffer> Result; 5053a321e23f66128dbb986343927456ff6702af617Michael J. Spencer llvm::error_code ec; 5063a321e23f66128dbb986343927456ff6702af617Michael J. Spencer if (FileSystemOpts.WorkingDir.empty()) { 5074eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(Filename, Result); 5084eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 5093a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 5104eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 5113a321e23f66128dbb986343927456ff6702af617Michael J. Spencer } 5123a321e23f66128dbb986343927456ff6702af617Michael J. Spencer 513af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::SmallString<128> FilePath(Filename); 51403fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 5154eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result); 5164eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 5173a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 5184eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 519389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 520389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 5219b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// getStatValue - Get the 'stat' information for the specified path, 5229b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// using the cache to accelerate it if possible. This returns true 5239b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// if the path points to a virtual file or does not exist, or returns 5249b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// false if it's an existent real file. If FileDescriptor is NULL, 5259b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan/// do directory look-up instead of file look-up. 526f9f7766846a205bc900b578f944567e679b221aaChris Lattnerbool FileManager::getStatValue(const char *Path, struct stat &StatBuf, 527898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int *FileDescriptor) { 52810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 52910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // absolute! 53011aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner if (FileSystemOpts.WorkingDir.empty()) 531898a061f69e1145bf89a987c08203132b9922a3cChris Lattner return FileSystemStatCache::get(Path, StatBuf, FileDescriptor, 532898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 5339b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan 534af036a6c25f540a9daf51e721485ae6d0e645bd8Anders Carlsson llvm::SmallString<128> FilePath(Path); 53503fd362dbf6fcd077df566fe2ac3165be668323bAnders Carlsson FixupRelativePath(FilePath); 53611aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner 537898a061f69e1145bf89a987c08203132b9922a3cChris Lattner return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor, 538898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 539389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 540389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 541cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregorvoid FileManager::GetUniqueIDMapping( 542cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor llvm::SmallVectorImpl<const FileEntry *> &UIDToFiles) const { 543cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles.clear(); 544cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles.resize(NextFileUID); 545cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 546cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // Map file entries 547cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator 5489b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end(); 549cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor FE != FEEnd; ++FE) 550cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE) 551cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles[FE->getValue()->getUID()] = FE->getValue(); 552cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor 553cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor // Map virtual file entries 554cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor for (llvm::SmallVector<FileEntry*, 4>::const_iterator 555cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end(); 556cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor VFE != VFEEnd; ++VFE) 557cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor if (*VFE && *VFE != NON_EXISTENT_FILE) 558cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor UIDToFiles[(*VFE)->getUID()] = *VFE; 559cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor} 56010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 56110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 5625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 5636cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "\n*** File Manager Stats:\n"; 5649b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::errs() << UniqueRealFiles.size() << " real files found, " 5659b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan << UniqueRealDirs.size() << " real dirs found.\n"; 5669b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan llvm::errs() << VirtualFileEntries.size() << " virtual files found, " 5679b555ea217565ac0f8bf7255b29496916cb03476Zhanyong Wan << VirtualDirectoryEntries.size() << " virtual dirs found.\n"; 5686cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumDirLookups << " dir lookups, " 5696cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumDirCacheMisses << " dir cache misses.\n"; 5706cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumFileLookups << " file lookups, " 5716cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumFileCacheMisses << " file cache misses.\n"; 5721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5736cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 5745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 575