FileManager.cpp revision 256053b31e697fdf0cc48f17d621c82fc3b8dff0
110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner//===--- FileManager.cpp - File System Probing and Caching ----------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the FileManager interface. 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// TODO: This should index all interesting directories with dirent calls. 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// getdirentries ? 165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// opendir/readdir_r/closedir ? 175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/FileManager.h" 2110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/FileSystemStatCache.h" 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/SmallString.h" 23c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner#include "llvm/ADT/StringExtras.h" 24389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis#include "llvm/Support/MemoryBuffer.h" 25d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner#include "llvm/Support/raw_ostream.h" 2603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 273a321e23f66128dbb986343927456ff6702af617Michael J. Spencer#include "llvm/Support/system_error.h" 286bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#include "llvm/Config/config.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> 39291fcf02980be85cf13c8a63bb036a19012311dfChris Lattner#endif 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// FIXME: Enhance libsystem to support inode and other fields. 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/stat.h> 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 453d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek/// NON_EXISTENT_DIR - A special value distinct from null that is used to 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// represent a dir name that doesn't exist on the disk. 473d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1) 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 49f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// NON_EXISTENT_FILE - A special value distinct from null that is used to 50f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// represent a filename that doesn't exist on the disk. 51f9f7766846a205bc900b578f944567e679b221aaChris Lattner#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1) 52f9f7766846a205bc900b578f944567e679b221aaChris Lattner 53f9f7766846a205bc900b578f944567e679b221aaChris Lattner 54f9f7766846a205bc900b578f944567e679b221aaChris LattnerFileEntry::~FileEntry() { 55f9f7766846a205bc900b578f944567e679b221aaChris Lattner // If this FileEntry owns an open file descriptor that never got used, close 56f9f7766846a205bc900b578f944567e679b221aaChris Lattner // it. 57f9f7766846a205bc900b578f944567e679b221aaChris Lattner if (FD != -1) ::close(FD); 58f9f7766846a205bc900b578f944567e679b221aaChris Lattner} 59f9f7766846a205bc900b578f944567e679b221aaChris Lattner 60cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 61cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Windows. 62cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 63cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#ifdef LLVM_ON_WIN32 656bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 66aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\') 676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremeneknamespace { 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::string GetFullPath(const char *relPath) { 706bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek char *absPathStrPtr = _fullpath(NULL, relPath, 0); 716bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek assert(absPathStrPtr && "_fullpath() returned NULL!"); 726bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 736bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string absPath(absPathStrPtr); 746bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 756bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek free(absPathStrPtr); 766bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return absPath; 776bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 786bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 796bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 806bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 816bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from full path to existing directories/files. 826bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::StringMap<DirectoryEntry> UniqueDirs; 846bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 856bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 866bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 876bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 88f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueDirs.GetOrCreateValue(FullPath).getValue(); 896bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 91f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 926bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 936bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 946bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 956bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from full path to existing directories/files. 966bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// 9775368893339d89f6523c312b0a0eb23d438b6dffTed Kremenek llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles; 986bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 996bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1006bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1016bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::string FullPath(GetFullPath(Name)); 102c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner 103c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner // LowercaseString because Windows filesystem is case insensitive. 104c070da46b896940aa2cbac416e5a2f8eee22d7d8Chris Lattner FullPath = llvm::LowercaseString(FullPath); 105f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner return UniqueFiles.GetOrCreateValue(FullPath).getValue(); 1066bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1076bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 108f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1096bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1106bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 111cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 112cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Unix-like Systems. 113cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 114cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek 1156bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#else 1166bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 117aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/') 1186bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueDirContainer { 1206bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueDirs - Cache from ID's to existing directories/files. 1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs; 1226bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1236bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1246bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) { 1256bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)]; 1266bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1276bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 128f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueDirs.size(); } 1296bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1306bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1316bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekclass FileManager::UniqueFileContainer { 1326bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek /// UniqueFiles - Cache from ID's to existing directories/files. 1336bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek std::set<FileEntry> UniqueFiles; 1346bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1356bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenekpublic: 1366bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &getFile(const char *Name, struct stat &StatBuf) { 1376bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek return 1386bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek const_cast<FileEntry&>( 1396bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek *UniqueFiles.insert(FileEntry(StatBuf.st_dev, 14096438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_ino, 14196438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek StatBuf.st_mode)).first); 1426bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek } 1436bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 144f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner size_t size() const { return UniqueFiles.size(); } 1456bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek}; 1466bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1476bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek#endif 1486bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 149cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 150cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek// Common logic. 151cb8d58b82859d2c56b679b901de38f416e2b6f48Ted Kremenek//===----------------------------------------------------------------------===// 1526bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1537ad97ffa631af6ad678c79b38341ac995f347ce9Chris LattnerFileManager::FileManager(const FileSystemOptions &FSO) 1547ad97ffa631af6ad678c79b38341ac995f347ce9Chris Lattner : FileSystemOpts(FSO), 155f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner UniqueDirs(*new UniqueDirContainer()), 156f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner UniqueFiles(*new UniqueFileContainer()), 15796438f319bb07d9a40564b5e01333f82c0c8a61eTed Kremenek DirEntries(64), FileEntries(64), NextFileUID(0) { 1586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirLookups = NumFileLookups = 0; 1596bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek NumDirCacheMisses = NumFileCacheMisses = 0; 1606bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 1626bb816a3b895e9c983d89b22d510dca58a0eb75eTed KremenekFileManager::~FileManager() { 1636bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueDirs; 1646bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek delete &UniqueFiles; 165f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i) 166f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner delete VirtualFileEntries[i]; 1676bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek} 1686bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 16910e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::addStatCache(FileSystemStatCache *statCache, 17010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner bool AtBeginning) { 17152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor assert(statCache && "No stat cache provided?"); 17252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (AtBeginning || StatCache.get() == 0) { 17352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor statCache->setNextStatCache(StatCache.take()); 17452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(statCache); 17552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 17652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 17752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 17810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *LastCache = StatCache.get(); 17952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (LastCache->getNextStatCache()) 18052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache = LastCache->getNextStatCache(); 18152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor LastCache->setNextStatCache(statCache); 18352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 18452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18510e286aa8d39fb51a21412850265d9dae74613eeChris Lattnervoid FileManager::removeStatCache(FileSystemStatCache *statCache) { 18652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (!statCache) 18752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 18852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 18952e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor if (StatCache.get() == statCache) { 19052e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // This is the first stat cache. 19152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatCache.reset(StatCache->takeNextStatCache()); 19252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor return; 19352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor } 19452e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 19552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor // Find the stat cache in the list. 19610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner FileSystemStatCache *PrevCache = StatCache.get(); 19752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor while (PrevCache && PrevCache->getNextStatCache() != statCache) 19852e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PrevCache = PrevCache->getNextStatCache(); 199f9f7766846a205bc900b578f944567e679b221aaChris Lattner 200f9f7766846a205bc900b578f944567e679b221aaChris Lattner assert(PrevCache && "Stat cache not found for removal"); 201f9f7766846a205bc900b578f944567e679b221aaChris Lattner PrevCache->setNextStatCache(statCache->getNextStatCache()); 20252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor} 20352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor 204057e567f1b375190779e5341f42861896cdee442Douglas Gregor/// \brief Retrieve the directory that the given file name resides in. 205057e567f1b375190779e5341f42861896cdee442Douglas Gregorstatic const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, 20639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner llvm::StringRef Filename) { 207057e567f1b375190779e5341f42861896cdee442Douglas Gregor // Figure out what directory it is in. If the string contains a / in it, 208057e567f1b375190779e5341f42861896cdee442Douglas Gregor // strip off everything after it. 209057e567f1b375190779e5341f42861896cdee442Douglas Gregor // FIXME: this logic should be in sys::Path. 210aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer size_t SlashPos = Filename.size(); 211aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer while (SlashPos != 0 && !IS_DIR_SEPARATOR_CHAR(Filename[SlashPos-1])) 212aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer --SlashPos; 213aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 214f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Use the current directory if file has no path component. 215aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer if (SlashPos == 0) 21639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return FileMgr.getDirectory("."); 217057e567f1b375190779e5341f42861896cdee442Douglas Gregor 218f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner if (SlashPos == Filename.size()-1) 219057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; // If filename ends with a /, it's a directory. 220aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 221f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner // Ignore repeated //'s. 222aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer while (SlashPos != 0 && IS_DIR_SEPARATOR_CHAR(Filename[SlashPos-1])) 223f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner --SlashPos; 224aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer 22539b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner return FileMgr.getDirectory(Filename.substr(0, SlashPos)); 226057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 227057e567f1b375190779e5341f42861896cdee442Douglas Gregor 2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getDirectory - Lookup, cache, and verify the specified directory. This 2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// returns null if the directory doesn't exist. 2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 23139b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst DirectoryEntry *FileManager::getDirectory(llvm::StringRef Filename) { 2329a6ac540bab63380a4a78d8fad87f23c50878685John Thompson // stat doesn't like trailing separators (at least on Windows). 233aa8b2d95bc108e8f3a443e4a936e1ed8a3cc1cc6Benjamin Kramer if (Filename.size() > 1 && IS_DIR_SEPARATOR_CHAR(Filename.back())) 234f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner Filename = Filename.substr(0, Filename.size()-1); 2359a6ac540bab63380a4a78d8fad87f23c50878685John Thompson 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirLookups; 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt = 238f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner DirEntries.GetOrCreateValue(Filename); 2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedDirEnt.getValue()) 2423d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedDirEnt.getValue() == NON_EXISTENT_DIR 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedDirEnt.getValue(); 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumDirCacheMisses; 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2483d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedDirEnt.setValue(NON_EXISTENT_DIR); 2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated directory name as stored as the key of the 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // DirEntries map. 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndDirName = NamedDirEnt.getKeyData(); 2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Check to see if the directory exists. 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 256898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (getStatValue(InterndDirName, StatBuf, 0/*directory lookup*/)) 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 2586bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek 2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // It exists. See if we have already opened a directory with the same inode. 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // This occurs when one dir is symlinked to another, for example. 2616bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf); 2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedDirEnt.setValue(&UDE); 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (UDE.getName()) // Already have an entry with this inode, return it. 2655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. We use the string 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key from the DirEntries map as the string. 2695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UDE.Name = InterndDirName; 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UDE; 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFile - Lookup, cache, and verify the specified file. This returns null 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if the file doesn't exist. 2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 27639b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattnerconst FileEntry *FileManager::getFile(llvm::StringRef Filename) { 2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileLookups; 2781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 281f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner FileEntries.GetOrCreateValue(Filename); 2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // See if there is already an entry in the map. 2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (NamedFileEnt.getValue()) 2853d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek return NamedFileEnt.getValue() == NON_EXISTENT_FILE 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ? 0 : NamedFileEnt.getValue(); 2871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ++NumFileCacheMisses; 2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // By default, initialize it to invalid. 2913d2da3d765123e15290c38ba44f4434462bb88d5Ted Kremenek NamedFileEnt.setValue(NON_EXISTENT_FILE); 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Get the null-terminated file name as stored as the key of the 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FileEntries map. 2965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *InterndFileName = NamedFileEnt.getKeyData(); 2971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 298f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner 299f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // Look up the directory for the file. When looking up something like 300f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // sys/foo.h we'll discover all of the search directories that have a 'sys' 301f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // subdirectory. This will let us avoid having to waste time on known-to-fail 302f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // searches when we go to find sys/bar.h, because all the search directories 303f3e8a9961d000fb9e093593b6a1bf72313b90d06Chris Lattner // without a 'sys' subdir will get a cached failure result. 30439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); 305057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (DirInfo == 0) // Directory doesn't exist, file can't exist. 306057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 307057e567f1b375190779e5341f42861896cdee442Douglas Gregor 3085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Use the directory info to prune this, before doing the stat syscall. 3095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: This will reduce the # syscalls. 3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, there isn't. Check to see if the file exists. 312898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int FileDescriptor = -1; 3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct stat StatBuf; 314898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) 3155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 317bca6d125c77c93c7fa41798c15348175a6bb1267Ted Kremenek // It exists. See if we have already opened a file with the same inode. 3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // This occurs when one dir is symlinked to another, for example. 3196bb816a3b895e9c983d89b22d510dca58a0eb75eTed Kremenek FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf); 3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NamedFileEnt.setValue(&UFE); 322898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (UFE.getName()) { // Already have an entry with this inode, return it. 323898a061f69e1145bf89a987c08203132b9922a3cChris Lattner // If the stat process opened the file, close it to avoid a FD leak. 324898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (FileDescriptor != -1) 325898a061f69e1145bf89a987c08203132b9922a3cChris Lattner close(FileDescriptor); 326898a061f69e1145bf89a987c08203132b9922a3cChris Lattner 3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 328898a061f69e1145bf89a987c08203132b9922a3cChris Lattner } 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we don't have this directory yet, add it. 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FIXME: Change the name to be a char* that points back to the 'FileEntries' 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // key. 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Name = InterndFileName; 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Size = StatBuf.st_size; 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.ModTime = StatBuf.st_mtime; 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.Dir = DirInfo; 3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer UFE.UID = NextFileUID++; 338898a061f69e1145bf89a987c08203132b9922a3cChris Lattner UFE.FD = FileDescriptor; 3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &UFE; 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 342057e567f1b375190779e5341f42861896cdee442Douglas Gregorconst FileEntry * 343ec1b1cc006cef19e0a95d0ea6fbfd37d0d615066Benjamin KramerFileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, 34439b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner time_t ModificationTime) { 345057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileLookups; 346057e567f1b375190779e5341f42861896cdee442Douglas Gregor 347057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 348057e567f1b375190779e5341f42861896cdee442Douglas Gregor llvm::StringMapEntry<FileEntry *> &NamedFileEnt = 349f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattner FileEntries.GetOrCreateValue(Filename); 350057e567f1b375190779e5341f42861896cdee442Douglas Gregor 351057e567f1b375190779e5341f42861896cdee442Douglas Gregor // See if there is already an entry in the map. 352057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (NamedFileEnt.getValue()) 353057e567f1b375190779e5341f42861896cdee442Douglas Gregor return NamedFileEnt.getValue() == NON_EXISTENT_FILE 354057e567f1b375190779e5341f42861896cdee442Douglas Gregor ? 0 : NamedFileEnt.getValue(); 355057e567f1b375190779e5341f42861896cdee442Douglas Gregor 356057e567f1b375190779e5341f42861896cdee442Douglas Gregor ++NumFileCacheMisses; 357057e567f1b375190779e5341f42861896cdee442Douglas Gregor 358057e567f1b375190779e5341f42861896cdee442Douglas Gregor // By default, initialize it to invalid. 359057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(NON_EXISTENT_FILE); 360057e567f1b375190779e5341f42861896cdee442Douglas Gregor 36139b49bcaaddb1049234fca9500c0ac02c088e23dChris Lattner const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); 362057e567f1b375190779e5341f42861896cdee442Douglas Gregor if (DirInfo == 0) // Directory doesn't exist, file can't exist. 363057e567f1b375190779e5341f42861896cdee442Douglas Gregor return 0; 364057e567f1b375190779e5341f42861896cdee442Douglas Gregor 365057e567f1b375190779e5341f42861896cdee442Douglas Gregor FileEntry *UFE = new FileEntry(); 366057e567f1b375190779e5341f42861896cdee442Douglas Gregor VirtualFileEntries.push_back(UFE); 367057e567f1b375190779e5341f42861896cdee442Douglas Gregor NamedFileEnt.setValue(UFE); 368057e567f1b375190779e5341f42861896cdee442Douglas Gregor 369f9f7766846a205bc900b578f944567e679b221aaChris Lattner // Get the null-terminated file name as stored as the key of the 370f9f7766846a205bc900b578f944567e679b221aaChris Lattner // FileEntries map. 371f9f7766846a205bc900b578f944567e679b221aaChris Lattner const char *InterndFileName = NamedFileEnt.getKeyData(); 372f9f7766846a205bc900b578f944567e679b221aaChris Lattner 373f9f7766846a205bc900b578f944567e679b221aaChris Lattner UFE->Name = InterndFileName; 374057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Size = Size; 375057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->ModTime = ModificationTime; 376057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->Dir = DirInfo; 377057e567f1b375190779e5341f42861896cdee442Douglas Gregor UFE->UID = NextFileUID++; 3783e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor 3793e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor // If this virtual file resolves to a file, also map that file to the 3803e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor // newly-created file entry. 381898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int FileDescriptor = -1; 3823e15e0a7b4da6d906357b00b1bd2bba5ec3195edDouglas Gregor struct stat StatBuf; 383898a061f69e1145bf89a987c08203132b9922a3cChris Lattner if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) 384f9f7766846a205bc900b578f944567e679b221aaChris Lattner return UFE; 385898a061f69e1145bf89a987c08203132b9922a3cChris Lattner 386898a061f69e1145bf89a987c08203132b9922a3cChris Lattner UFE->FD = FileDescriptor; 387f9f7766846a205bc900b578f944567e679b221aaChris Lattner llvm::sys::Path FilePath(UFE->Name); 388f9f7766846a205bc900b578f944567e679b221aaChris Lattner FilePath.makeAbsolute(); 389f9f7766846a205bc900b578f944567e679b221aaChris Lattner FileEntries[FilePath.str()] = UFE; 390057e567f1b375190779e5341f42861896cdee442Douglas Gregor return UFE; 391057e567f1b375190779e5341f42861896cdee442Douglas Gregor} 392057e567f1b375190779e5341f42861896cdee442Douglas Gregor 39367452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattnervoid FileManager::FixupRelativePath(llvm::sys::Path &path, 39467452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner const FileSystemOptions &FSOpts) { 395256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (FSOpts.WorkingDir.empty() || llvm::sys::path::is_absolute(path.str())) 396256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer return; 397256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer 398256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer llvm::SmallString<128> NewPath(FSOpts.WorkingDir); 399256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer llvm::sys::path::append(NewPath, path.str()); 40067452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner path = NewPath; 40167452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner} 40267452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 40375dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattnerllvm::MemoryBuffer *FileManager:: 40475dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { 4054eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer llvm::OwningPtr<llvm::MemoryBuffer> Result; 4063a321e23f66128dbb986343927456ff6702af617Michael J. Spencer llvm::error_code ec; 4075cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner if (FileSystemOpts.WorkingDir.empty()) { 4085cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner const char *Filename = Entry->getName(); 4095cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner // If the file is already open, use the open file descriptor. 4105cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner if (Entry->FD != -1) { 4114eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, 4124eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer Entry->getSize()); 4134eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ErrorStr) 4143a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4155cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner // getOpenFile will have closed the file descriptor, don't reuse or 4165cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner // reclose it. 4175cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner Entry->FD = -1; 4184eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 4195cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner } 4205cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner 4215cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner // Otherwise, open the file. 4224eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize()); 4234eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4243a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4254eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 4265cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner } 42775dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner 4285cc1c738b0c51af55cbfe7672c284c19f8e30eb2Chris Lattner llvm::sys::Path FilePath(Entry->getName()); 42975dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner FixupRelativePath(FilePath, FileSystemOpts); 4304eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result, Entry->getSize()); 4314eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4323a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4334eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 43475dfb65c38d51772df9a00ce2d2feeefd55667adChris Lattner} 43567452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner 436f69a1f319bd3c846c4a9ab84ea615e4e37dfd359Chris Lattnerllvm::MemoryBuffer *FileManager:: 43775dfb65c38d51772df9a00ce2d2feeefd55667adChris LattnergetBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) { 4384eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer llvm::OwningPtr<llvm::MemoryBuffer> Result; 4393a321e23f66128dbb986343927456ff6702af617Michael J. Spencer llvm::error_code ec; 4403a321e23f66128dbb986343927456ff6702af617Michael J. Spencer if (FileSystemOpts.WorkingDir.empty()) { 4414eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(Filename, Result); 4424eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4433a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4444eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 4453a321e23f66128dbb986343927456ff6702af617Michael J. Spencer } 4463a321e23f66128dbb986343927456ff6702af617Michael J. Spencer 44767452f51aec1ad8a3e4c6622c0c57c5d8dc1b6a3Chris Lattner llvm::sys::Path FilePath(Filename); 448389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FixupRelativePath(FilePath, FileSystemOpts); 4494eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result); 4504eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer if (ec && ErrorStr) 4513a321e23f66128dbb986343927456ff6702af617Michael J. Spencer *ErrorStr = ec.message(); 4524eeebc464e1f968d9968a4786c82558f18ac2ed8Michael J. Spencer return Result.take(); 453389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 454389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 45510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// getStatValue - Get the 'stat' information for the specified path, using the 456c0f31fd08537b65ad92db8ce860747e3402a07e6Chris Lattner/// cache to accelerate it if possible. This returns true if the path does not 45710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner/// exist or false if it exists. 458f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// 459f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// The isForDir member indicates whether this is a directory lookup or not. 460f9f7766846a205bc900b578f944567e679b221aaChris Lattner/// This will return failure if the lookup isn't the expected kind. 461f9f7766846a205bc900b578f944567e679b221aaChris Lattnerbool FileManager::getStatValue(const char *Path, struct stat &StatBuf, 462898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int *FileDescriptor) { 46310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be 46410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner // absolute! 46511aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner if (FileSystemOpts.WorkingDir.empty()) 466898a061f69e1145bf89a987c08203132b9922a3cChris Lattner return FileSystemStatCache::get(Path, StatBuf, FileDescriptor, 467898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 46810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 46910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner llvm::sys::Path FilePath(Path); 470389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis FixupRelativePath(FilePath, FileSystemOpts); 47111aa4b03b054cb9d3c201bba5632241145865e29Chris Lattner 472898a061f69e1145bf89a987c08203132b9922a3cChris Lattner return FileSystemStatCache::get(FilePath.c_str(), StatBuf, FileDescriptor, 473898a061f69e1145bf89a987c08203132b9922a3cChris Lattner StatCache.get()); 474389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis} 475389db16c63eec6ecfa9b235155252d8da766e94eArgyrios Kyrtzidis 47610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 47710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner 4785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid FileManager::PrintStats() const { 4796cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "\n*** File Manager Stats:\n"; 4806cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << UniqueFiles.size() << " files found, " 4816cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << UniqueDirs.size() << " dirs found.\n"; 4826cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumDirLookups << " dir lookups, " 4836cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumDirCacheMisses << " dir cache misses.\n"; 4846cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << NumFileLookups << " file lookups, " 4856cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer << NumFileCacheMisses << " file cache misses.\n"; 4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4876cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer //llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups; 4885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4894fed3f47f6b9e31d603c5c2d1f6d8ec2e1241e57Douglas Gregor 490