11 #include "llvm/Support/MemoryBuffer.h" 12 #include "llvm/Support/Threading.h" 14 using namespace clang;
15 using namespace tooling;
16 using namespace dependencies;
19 StringRef
Filename, llvm::vfs::FileSystem &FS,
bool Minimize) {
21 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> MaybeFile =
22 FS.openFileForRead(Filename);
24 return MaybeFile.getError();
25 llvm::ErrorOr<llvm::vfs::Status> Stat = (*MaybeFile)->status();
27 return Stat.getError();
29 llvm::vfs::File &F = **MaybeFile;
30 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MaybeBuffer =
31 F.getBuffer(Stat->getName());
33 return MaybeBuffer.getError();
37 const auto &Buffer = *MaybeBuffer;
40 Buffer->getBuffer(), MinimizedFileContents, Tokens)) {
45 Result.MaybeStat = std::move(*Stat);
46 Result.Contents.reserve(Buffer->getBufferSize() + 1);
47 Result.Contents.append(Buffer->getBufferStart(), Buffer->getBufferEnd());
49 Result.Contents.push_back(
'\0');
50 Result.Contents.pop_back();
55 size_t Size = MinimizedFileContents.size();
56 Result.MaybeStat = llvm::vfs::Status(Stat->getName(), Stat->getUniqueID(),
57 Stat->getLastModificationTime(),
58 Stat->getUser(), Stat->getGroup(), Size,
59 Stat->getType(), Stat->getPermissions());
61 assert(MinimizedFileContents.data()[MinimizedFileContents.size()] ==
'\0' &&
62 "not null terminated contents");
67 MinimizedFileContents.push_back(
'\0');
68 Result.Contents = std::move(MinimizedFileContents);
71 Result.Contents.pop_back();
80 for (
const auto &
Range : SkippedRanges) {
81 if (
Range.Length < 16) {
89 Result.PPSkippedRangeMapping = std::move(Mapping);
96 assert(Stat.isDirectory() &&
"not a directory!");
98 Result.MaybeStat = std::move(Stat);
109 NumShards =
std::max(2u, llvm::hardware_concurrency() / 4);
110 CacheShards = std::make_unique<CacheShard[]>(NumShards);
120 std::unique_lock<std::mutex> LockGuard(Shard.CacheLock);
121 auto It = Shard.Cache.try_emplace(Key);
122 return It.first->getValue();
131 StringRef Ext = llvm::sys::path::extension(Filename);
134 return llvm::StringSwitch<bool>(Ext)
135 .CasesLower(
".c",
".cc",
".cpp",
".c++",
".cxx",
true)
136 .CasesLower(
".h",
".hh",
".hpp",
".h++",
".hxx",
true)
137 .CasesLower(
".m",
".mm",
true)
138 .CasesLower(
".i",
".ii",
".mi",
".mmi",
true)
139 .CasesLower(
".def",
".inc",
true)
145 StringRef Ext = llvm::sys::path::extension(Filename);
151 llvm::ErrorOr<const CachedFileSystemEntry *>
152 DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry(
161 bool KeepOriginalSource = IgnoredFiles.count(Filename) ||
164 &SharedCacheEntry = SharedCache.get(Filename);
167 std::unique_lock<std::mutex> LockGuard(SharedCacheEntry.
ValueLock);
171 llvm::vfs::FileSystem &FS = getUnderlyingFS();
172 auto MaybeStatus = FS.status(Filename);
179 return MaybeStatus.getError();
182 }
else if (MaybeStatus->isDirectory())
184 std::move(*MaybeStatus));
187 Filename, FS, !KeepOriginalSource);
190 Result = &CacheEntry;
194 setCachedEntry(Filename, Result);
198 llvm::ErrorOr<llvm::vfs::Status>
201 StringRef
Filename = Path.toStringRef(OwnedFilename);
202 const llvm::ErrorOr<const CachedFileSystemEntry *> Result =
203 getOrCreateFileSystemEntry(Filename);
205 return Result.getError();
206 return (*Result)->getStatus();
213 class MinimizedVFSFile final :
public llvm::vfs::File {
215 MinimizedVFSFile(std::unique_ptr<llvm::MemoryBuffer> Buffer,
216 llvm::vfs::Status Stat)
217 : Buffer(std::move(Buffer)), Stat(std::move(Stat)) {}
219 llvm::ErrorOr<llvm::vfs::Status> status()
override {
return Stat; }
221 const llvm::MemoryBuffer *getBufferPtr()
const {
return Buffer.get(); }
223 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
224 getBuffer(
const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator,
225 bool IsVolatile)
override {
226 return std::move(Buffer);
229 std::error_code close()
override {
return {}; }
232 std::unique_ptr<llvm::MemoryBuffer> Buffer;
233 llvm::vfs::Status Stat;
236 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
240 return llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>(
242 llvm::ErrorOr<StringRef> Contents = Entry->
getContents();
244 return Contents.getError();
245 auto Result = std::make_unique<MinimizedVFSFile>(
246 llvm::MemoryBuffer::getMemBuffer(*Contents, Entry->
getName(),
250 (*PPSkipMappings)[Result->getBufferPtr()] =
252 return llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>(
253 std::unique_ptr<llvm::vfs::File>(std::move(Result)));
258 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
261 StringRef
Filename = Path.toStringRef(OwnedFilename);
263 const llvm::ErrorOr<const CachedFileSystemEntry *> Result =
264 getOrCreateFileSystemEntry(Filename);
266 return Result.getError();
267 return createFile(Result.get(), PPSkipMappings);
bool minimizeSourceToDependencyDirectives(llvm::StringRef Input, llvm::SmallVectorImpl< char > &Output, llvm::SmallVectorImpl< minimize_source_to_dependency_directives::Token > &Tokens, DiagnosticsEngine *Diags=nullptr, SourceLocation InputSourceLoc=SourceLocation())
Minimize the input down to the preprocessor directives that might have an effect on the dependencies ...
CachedFileSystemEntry()
Default constructor creates an entry with an invalid stat.
StringRef getName() const
__DEVICE__ int max(int __a, int __b)
static bool shouldMinimize(StringRef Filename)
Whitelist file extensions that should be minimized, treating no extension as a source file that shoul...
static CachedFileSystemEntry createFileEntry(StringRef Filename, llvm::vfs::FileSystem &FS, bool Minimize=true)
Create an entry that represents an opened source file with minimized or original contents.
llvm::hash_code hash_value(const clang::SanitizerMask &Arg)
static bool shouldCacheStatFailures(StringRef Filename)
static CachedFileSystemEntry createDirectoryEntry(llvm::vfs::Status &&Stat)
Create an entry that represents a directory on the filesystem.
const PreprocessorSkippedRangeMapping & getPPSkippedRangeMapping() const
Return the mapping between location -> distance that is used to speed up the block skipping in the pr...
llvm::ErrorOr< llvm::vfs::Status > getStatus() const
Dataflow Directional Tag Classes.
llvm::DenseMap< unsigned, unsigned > PreprocessorSkippedRangeMapping
A mapping from an offset into a buffer to the number of bytes that can be skipped by the preprocessor...
llvm::DenseMap< const llvm::MemoryBuffer *, const PreprocessorSkippedRangeMapping * > ExcludedPreprocessorDirectiveSkipMapping
The datastructure that holds the mapping between the active memory buffers and the individual skip ma...
This is the interface for minimizing header and source files to the minimum necessary preprocessor di...
llvm::ErrorOr< StringRef > getContents() const
An in-memory representation of a file system entity that is of interest to the dependency scanning fi...
bool computeSkippedRanges(ArrayRef< Token > Input, llvm::SmallVectorImpl< SkippedRange > &Range)
Computes the potential source ranges that can be skipped by the preprocessor when skipping a directiv...
CachedFileSystemEntry Value