diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-02 18:12:28 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-02 18:12:28 +0000 |
commit | 057e567f1b375190779e5341f42861896cdee442 (patch) | |
tree | 4e0cb8a63e2b0400633510ff2db66b22e3d054ad /lib/Basic/FileManager.cpp | |
parent | 5ec02ae147760c32ad5b6fb0fec30ab3b3696778 (diff) |
Extend -remap-file=from;to to permit mapping from a non-existent
file. This is accomplished by introducing the notion of a "virtual"
file into the file manager, which provides a FileEntry* for a named
file whose size and modification time are known but which may not
exist on disk.
Added a cute little test that remaps both a .c file and a .h file it
includes to alternative files.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90329 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Basic/FileManager.cpp')
-rw-r--r-- | lib/Basic/FileManager.cpp | 95 |
1 files changed, 73 insertions, 22 deletions
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index ee4309de93..9c5f1d59c1 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -147,6 +147,12 @@ FileManager::FileManager() FileManager::~FileManager() { delete &UniqueDirs; delete &UniqueFiles; + for (llvm::SmallVectorImpl<FileEntry *>::iterator + V = VirtualFileEntries.begin(), + VEnd = VirtualFileEntries.end(); + V != VEnd; + ++V) + delete *V; } void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) { @@ -184,6 +190,30 @@ void FileManager::removeStatCache(StatSysCallCache *statCache) { assert(false && "Stat cache not found for removal"); } +/// \brief Retrieve the directory that the given file name resides in. +static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr, + const char *NameStart, + const char *NameEnd) { + // Figure out what directory it is in. If the string contains a / in it, + // strip off everything after it. + // FIXME: this logic should be in sys::Path. + const char *SlashPos = NameEnd-1; + while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) + --SlashPos; + // Ignore duplicate //'s. + while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1])) + --SlashPos; + + if (SlashPos < NameStart) { + // Use the current directory if file has no path component. + const char *Name = "."; + return FileMgr.getDirectory(Name, Name+1); + } else if (SlashPos == NameEnd-1) + return 0; // If filename ends with a /, it's a directory. + else + return FileMgr.getDirectory(NameStart, SlashPos); +} + /// getDirectory - Lookup, cache, and verify the specified directory. This /// returns null if the directory doesn't exist. /// @@ -252,33 +282,16 @@ const FileEntry *FileManager::getFile(const char *NameStart, // By default, initialize it to invalid. NamedFileEnt.setValue(NON_EXISTENT_FILE); - // Figure out what directory it is in. If the string contains a / in it, - // strip off everything after it. - // FIXME: this logic should be in sys::Path. - const char *SlashPos = NameEnd-1; - while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0])) - --SlashPos; - // Ignore duplicate //'s. - while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1])) - --SlashPos; - - const DirectoryEntry *DirInfo; - if (SlashPos < NameStart) { - // Use the current directory if file has no path component. - const char *Name = "."; - DirInfo = getDirectory(Name, Name+1); - } else if (SlashPos == NameEnd-1) - return 0; // If filename ends with a /, it's a directory. - else - DirInfo = getDirectory(NameStart, SlashPos); - - if (DirInfo == 0) // Directory doesn't exist, file can't exist. - return 0; // Get the null-terminated file name as stored as the key of the // FileEntries map. const char *InterndFileName = NamedFileEnt.getKeyData(); + const DirectoryEntry *DirInfo + = getDirectoryFromFile(*this, NameStart, NameEnd); + if (DirInfo == 0) // Directory doesn't exist, file can't exist. + return 0; + // FIXME: Use the directory info to prune this, before doing the stat syscall. // FIXME: This will reduce the # syscalls. @@ -312,6 +325,44 @@ const FileEntry *FileManager::getFile(const char *NameStart, return &UFE; } +const FileEntry * +FileManager::getVirtualFile(const llvm::StringRef &Filename, + off_t Size, time_t ModificationTime) { + const char *NameStart = Filename.begin(), *NameEnd = Filename.end(); + + ++NumFileLookups; + + // See if there is already an entry in the map. + llvm::StringMapEntry<FileEntry *> &NamedFileEnt = + FileEntries.GetOrCreateValue(NameStart, NameEnd); + + // See if there is already an entry in the map. + if (NamedFileEnt.getValue()) + return NamedFileEnt.getValue() == NON_EXISTENT_FILE + ? 0 : NamedFileEnt.getValue(); + + ++NumFileCacheMisses; + + // By default, initialize it to invalid. + NamedFileEnt.setValue(NON_EXISTENT_FILE); + + const DirectoryEntry *DirInfo + = getDirectoryFromFile(*this, NameStart, NameEnd); + if (DirInfo == 0) // Directory doesn't exist, file can't exist. + return 0; + + FileEntry *UFE = new FileEntry(); + VirtualFileEntries.push_back(UFE); + NamedFileEnt.setValue(UFE); + + UFE->Name = NamedFileEnt.getKeyData(); + UFE->Size = Size; + UFE->ModTime = ModificationTime; + UFE->Dir = DirInfo; + UFE->UID = NextFileUID++; + return UFE; +} + void FileManager::PrintStats() const { llvm::errs() << "\n*** File Manager Stats:\n"; llvm::errs() << UniqueFiles.size() << " files found, " |