Serialization: Change InputFile to use FileEntryRef and add getVirtualFileRef, NFC

Change the `InputFile` class to store `Optional<FileEntryRef>` instead
of `FileEntry*`. This paged in a few API changes:

- Added `FileManager::getVirtualFileRef`, and converted `getVirtualFile`
  to a wrapper of it.
- Updated `SourceManager::bypassFileContentsOverride` to take
  `FileEntryRef` and return `Optional<FileEntryRef>`
  (`ASTReader::getInputFile` is the only caller).

Differential Revision: https://reviews.llvm.org/D90053
This commit is contained in:
Duncan P. N. Exon Smith 2020-10-21 23:38:12 -04:00 committed by Duncan P. N. Exon Smith
parent 9615890db5
commit ac40a2d8f1
6 changed files with 44 additions and 40 deletions

View File

@ -239,6 +239,9 @@ public:
/// if there were a file with the given name on disk. /// if there were a file with the given name on disk.
/// ///
/// The file itself is not accessed. /// The file itself is not accessed.
FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size,
time_t ModificationTime);
const FileEntry *getVirtualFile(StringRef Filename, off_t Size, const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
time_t ModificationTime); time_t ModificationTime);

View File

@ -35,6 +35,7 @@
#define LLVM_CLANG_BASIC_SOURCEMANAGER_H #define LLVM_CLANG_BASIC_SOURCEMANAGER_H
#include "clang/Basic/Diagnostic.h" #include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h" #include "llvm/ADT/BitVector.h"
@ -60,8 +61,6 @@ namespace clang {
class ASTReader; class ASTReader;
class ASTWriter; class ASTWriter;
class FileManager; class FileManager;
class FileEntry;
class FileEntryRef;
class LineTableInfo; class LineTableInfo;
class SourceManager; class SourceManager;
@ -982,11 +981,11 @@ public:
} }
/// Bypass the overridden contents of a file. This creates a new FileEntry /// Bypass the overridden contents of a file. This creates a new FileEntry
/// and initializes the content cache for it. Returns nullptr if there is no /// and initializes the content cache for it. Returns None if there is no
/// such file in the filesystem. /// such file in the filesystem.
/// ///
/// This should be called before parsing has begun. /// This should be called before parsing has begun.
const FileEntry *bypassFileContentsOverride(const FileEntry &File); Optional<FileEntryRef> bypassFileContentsOverride(FileEntryRef File);
/// Specify that a file is transient. /// Specify that a file is transient.
void setFileIsTransient(const FileEntry *SourceFile); void setFileIsTransient(const FileEntry *SourceFile);

View File

@ -67,13 +67,13 @@ class InputFile {
OutOfDate = 2, OutOfDate = 2,
NotFound = 3 NotFound = 3
}; };
llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val; llvm::PointerIntPair<const FileEntryRef::MapEntry *, 2, unsigned> Val;
public: public:
InputFile() = default; InputFile() = default;
InputFile(const FileEntry *File, InputFile(FileEntryRef File, bool isOverridden = false,
bool isOverridden = false, bool isOutOfDate = false) { bool isOutOfDate = false) {
assert(!(isOverridden && isOutOfDate) && assert(!(isOverridden && isOutOfDate) &&
"an overridden cannot be out-of-date"); "an overridden cannot be out-of-date");
unsigned intVal = 0; unsigned intVal = 0;
@ -81,7 +81,7 @@ public:
intVal = Overridden; intVal = Overridden;
else if (isOutOfDate) else if (isOutOfDate)
intVal = OutOfDate; intVal = OutOfDate;
Val.setPointerAndInt(File, intVal); Val.setPointerAndInt(&File.getMapEntry(), intVal);
} }
static InputFile getNotFound() { static InputFile getNotFound() {
@ -90,7 +90,11 @@ public:
return File; return File;
} }
const FileEntry *getFile() const { return Val.getPointer(); } OptionalFileEntryRefDegradesToFileEntryPtr getFile() const {
if (auto *P = Val.getPointer())
return FileEntryRef(*P);
return None;
}
bool isOverridden() const { return Val.getInt() == Overridden; } bool isOverridden() const { return Val.getInt() == Overridden; }
bool isOutOfDate() const { return Val.getInt() == OutOfDate; } bool isOutOfDate() const { return Val.getInt() == OutOfDate; }
bool isNotFound() const { return Val.getInt() == NotFound; } bool isNotFound() const { return Val.getInt() == NotFound; }

View File

@ -335,9 +335,13 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
return ReturnedRef; return ReturnedRef;
} }
const FileEntry * const FileEntry *FileManager::getVirtualFile(StringRef Filename, off_t Size,
FileManager::getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime) {
time_t ModificationTime) { return &getVirtualFileRef(Filename, Size, ModificationTime).getFileEntry();
}
FileEntryRef FileManager::getVirtualFileRef(StringRef Filename, off_t Size,
time_t ModificationTime) {
++NumFileLookups; ++NumFileLookups;
// See if there is already an entry in the map for an existing file. // See if there is already an entry in the map for an existing file.
@ -345,12 +349,10 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
{Filename, std::errc::no_such_file_or_directory}).first; {Filename, std::errc::no_such_file_or_directory}).first;
if (NamedFileEnt.second) { if (NamedFileEnt.second) {
FileEntryRef::MapValue Value = *NamedFileEnt.second; FileEntryRef::MapValue Value = *NamedFileEnt.second;
FileEntry *FE; if (LLVM_LIKELY(Value.V.is<FileEntry *>()))
if (LLVM_LIKELY(FE = Value.V.dyn_cast<FileEntry *>())) return FileEntryRef(NamedFileEnt);
return FE; return FileEntryRef(*reinterpret_cast<const FileEntryRef::MapEntry *>(
return &FileEntryRef(*reinterpret_cast<const FileEntryRef::MapEntry *>( Value.V.get<const void *>()));
Value.V.get<const void *>()))
.getFileEntry();
} }
// We've not seen this before, or the file is cached as non-existent. // We've not seen this before, or the file is cached as non-existent.
@ -389,7 +391,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
// FIXME: Surely this should add a reference by the new name, and return // FIXME: Surely this should add a reference by the new name, and return
// it instead... // it instead...
if (UFE->isValid()) if (UFE->isValid())
return UFE; return FileEntryRef(NamedFileEnt);
UFE->UniqueID = Status.getUniqueID(); UFE->UniqueID = Status.getUniqueID();
UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file; UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
@ -407,7 +409,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
UFE->UID = NextFileUID++; UFE->UID = NextFileUID++;
UFE->IsValid = true; UFE->IsValid = true;
UFE->File.reset(); UFE->File.reset();
return UFE; return FileEntryRef(NamedFileEnt);
} }
llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) { llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) {

View File

@ -698,19 +698,17 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile,
getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
} }
const FileEntry * Optional<FileEntryRef>
SourceManager::bypassFileContentsOverride(const FileEntry &File) { SourceManager::bypassFileContentsOverride(FileEntryRef File) {
assert(isFileOverridden(&File)); assert(isFileOverridden(&File.getFileEntry()));
llvm::Optional<FileEntryRef> BypassFile = llvm::Optional<FileEntryRef> BypassFile = FileMgr.getBypassFile(File);
FileMgr.getBypassFile(File.getLastRef());
// If the file can't be found in the FS, give up. // If the file can't be found in the FS, give up.
if (!BypassFile) if (!BypassFile)
return nullptr; return None;
const FileEntry *FE = &BypassFile->getFileEntry(); (void)getOrCreateContentCache(&BypassFile->getFileEntry());
(void)getOrCreateContentCache(FE); return BypassFile;
return FE;
} }
void SourceManager::setFileIsTransient(const FileEntry *File) { void SourceManager::setFileIsTransient(const FileEntry *File) {

View File

@ -2296,27 +2296,25 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
StringRef Filename = FI.Filename; StringRef Filename = FI.Filename;
uint64_t StoredContentHash = FI.ContentHash; uint64_t StoredContentHash = FI.ContentHash;
const FileEntry *File = nullptr; OptionalFileEntryRefDegradesToFileEntryPtr File =
if (auto FE = FileMgr.getFile(Filename, /*OpenFile=*/false)) expectedToOptional(FileMgr.getFileRef(Filename, /*OpenFile=*/false));
File = *FE;
// If we didn't find the file, resolve it relative to the // If we didn't find the file, resolve it relative to the
// original directory from which this AST file was created. // original directory from which this AST file was created.
if (File == nullptr && !F.OriginalDir.empty() && !F.BaseDirectory.empty() && if (!File && !F.OriginalDir.empty() && !F.BaseDirectory.empty() &&
F.OriginalDir != F.BaseDirectory) { F.OriginalDir != F.BaseDirectory) {
std::string Resolved = resolveFileRelativeToOriginalDir( std::string Resolved = resolveFileRelativeToOriginalDir(
std::string(Filename), F.OriginalDir, F.BaseDirectory); std::string(Filename), F.OriginalDir, F.BaseDirectory);
if (!Resolved.empty()) if (!Resolved.empty())
if (auto FE = FileMgr.getFile(Resolved)) File = expectedToOptional(FileMgr.getFileRef(Resolved));
File = *FE;
} }
// For an overridden file, create a virtual file with the stored // For an overridden file, create a virtual file with the stored
// size/timestamp. // size/timestamp.
if ((Overridden || Transient) && File == nullptr) if ((Overridden || Transient) && !File)
File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime); File = FileMgr.getVirtualFileRef(Filename, StoredSize, StoredTime);
if (File == nullptr) { if (!File) {
if (Complain) { if (Complain) {
std::string ErrorStr = "could not find file '"; std::string ErrorStr = "could not find file '";
ErrorStr += Filename; ErrorStr += Filename;
@ -2418,7 +2416,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// FIXME: If the file is overridden and we've already opened it, // FIXME: If the file is overridden and we've already opened it,
// issue an error (or split it into a separate FileEntry). // issue an error (or split it into a separate FileEntry).
InputFile IF = InputFile(File, Overridden || Transient, IsOutOfDate); InputFile IF = InputFile(*File, Overridden || Transient, IsOutOfDate);
// Note that we've loaded this input file. // Note that we've loaded this input file.
F.InputFilesLoaded[ID-1] = IF; F.InputFilesLoaded[ID-1] = IF;
@ -9274,7 +9272,7 @@ void ASTReader::visitTopLevelModuleMaps(
InputFileInfo IFI = readInputFileInfo(MF, I + 1); InputFileInfo IFI = readInputFileInfo(MF, I + 1);
if (IFI.TopLevelModuleMap) if (IFI.TopLevelModuleMap)
// FIXME: This unnecessarily re-reads the InputFileInfo. // FIXME: This unnecessarily re-reads the InputFileInfo.
if (auto *FE = getInputFile(MF, I + 1).getFile()) if (auto FE = getInputFile(MF, I + 1).getFile())
Visitor(FE); Visitor(FE);
} }
} }