Skip to content

Commit 6cd1543

Browse files
[CAS] Remove CAS dependency from LLVM_Utils module
Fix the proper laying of the llvm library by splitting CAS reference away from FileSystem references. This has some behavior changes: * The common base class for FileSystem configured with a CAS-backing is now `llvm::cas::CASBackedFileSystem` and migrate CAS related FileSystem APIs to the new class. * ThreadSafeFileSystem is folded into CASBackedFileSystem to avoid diamond class hierachies. * llvm::vfs::File needs to be RTTIExtended, so that a user can tell if the file is CAS backed when there are overlaying file system. * When configured with multi-layer CAS backed file system, the file content is available in every CAS along the way the file is resolved and the returned CASID is from the top layer. This is a more deterministic behavior than current one, that only the lowest level CAS has the reference, and user actually don't know which CAS it is associated with unless know in advance which layer vended the file.
1 parent 2bb0d99 commit 6cd1543

File tree

18 files changed

+351
-257
lines changed

18 files changed

+351
-257
lines changed

clang/include/clang/Tooling/DependencyScanning/DependencyScanningCASFilesystem.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
#include "llvm/ADT/StringMap.h"
1515
#include "llvm/ADT/StringSet.h"
1616
#include "llvm/CAS/ActionCache.h"
17+
#include "llvm/CAS/CASFileSystem.h"
1718
#include "llvm/CAS/CASID.h"
1819
#include "llvm/CAS/CASReference.h"
19-
#include "llvm/CAS/ThreadSafeFileSystem.h"
2020
#include "llvm/Support/Allocator.h"
2121
#include "llvm/Support/ErrorOr.h"
2222
#include "llvm/Support/VirtualFileSystem.h"
@@ -32,8 +32,12 @@ namespace clang {
3232
namespace tooling {
3333
namespace dependencies {
3434

35-
class DependencyScanningCASFilesystem : public llvm::cas::ThreadSafeFileSystem {
35+
class DependencyScanningCASFilesystem
36+
: public llvm::RTTIExtends<DependencyScanningCASFilesystem,
37+
llvm::cas::CASBackedFileSystem> {
3638
public:
39+
static const char ID;
40+
3741
DependencyScanningCASFilesystem(
3842
IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem> WorkerFS,
3943
llvm::cas::ActionCache &Cache);
@@ -59,13 +63,13 @@ class DependencyScanningCASFilesystem : public llvm::cas::ThreadSafeFileSystem {
5963
return FS->isLocal(Path, Result);
6064
}
6165

62-
IntrusiveRefCntPtr<llvm::cas::ThreadSafeFileSystem>
66+
IntrusiveRefCntPtr<llvm::cas::CASBackedFileSystem>
6367
createThreadSafeProxyFS() override;
6468

6569
llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override;
6670
bool exists(const Twine &Path) override;
67-
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
68-
openFileForRead(const Twine &Path) override;
71+
llvm::Expected<std::unique_ptr<llvm::cas::CASBackedFile>>
72+
openCASBackedFileForRead(const Twine &Path) override;
6973

7074
/// \returns The scanned preprocessor directive tokens of the file that are
7175
/// used to speed up preprocessing, if available.

clang/lib/Basic/FileManager.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/Basic/FileSystemStatCache.h"
2121
#include "llvm/ADT/SmallString.h"
2222
#include "llvm/ADT/Statistic.h"
23+
#include "llvm/CAS/CASFileSystem.h"
2324
#include "llvm/CAS/CASReference.h"
2425
#include "llvm/Config/llvm-config.h"
2526
#include "llvm/Support/FileSystem.h"
@@ -536,10 +537,10 @@ FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile,
536537
auto Result = Entry->File->getBuffer(Filename, FileSize,
537538
RequiresNullTerminator, isVolatile);
538539
if (CASContents) {
539-
auto CASRef = Entry->File->getObjectRefForContent();
540-
if (!CASRef)
541-
return CASRef.getError();
542-
*CASContents = *CASRef;
540+
if (auto *CASFile = dyn_cast<llvm::cas::CASBackedFile>(Entry->File.get()))
541+
*CASContents = CASFile->getObjectRefForContent();
542+
else
543+
*CASContents = std::nullopt;
543544
}
544545
Entry->closeFile();
545546
return Result;
@@ -555,25 +556,52 @@ FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize,
555556
bool isVolatile, bool RequiresNullTerminator,
556557
bool IsText,
557558
std::optional<cas::ObjectRef> *CASContents) const {
559+
auto getBufferImpl = [&](StringRef Name)
560+
-> llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> {
561+
auto F = FS->openFileForRead(Name);
562+
if (!F)
563+
return F.getError();
564+
565+
if (CASContents) {
566+
if (auto *CASFile = dyn_cast<llvm::cas::CASBackedFile>(F->get()))
567+
*CASContents = CASFile->getObjectRefForContent();
568+
else
569+
*CASContents = std::nullopt;
570+
}
571+
return FS->getBufferForFile(Name, FileSize, RequiresNullTerminator,
572+
isVolatile, IsText);
573+
};
574+
558575
if (FileSystemOpts.WorkingDir.empty())
559-
return FS->getBufferForFile(Filename, FileSize, RequiresNullTerminator,
560-
isVolatile, IsText, CASContents);
576+
return getBufferImpl(Filename);
561577

562578
SmallString<128> FilePath(Filename);
563579
FixupRelativePath(FilePath);
564-
return FS->getBufferForFile(FilePath, FileSize, RequiresNullTerminator,
565-
isVolatile, IsText, CASContents);
580+
return getBufferImpl(FilePath);
566581
}
567582

568583
llvm::ErrorOr<std::optional<cas::ObjectRef>>
569584
FileManager::getObjectRefForFileContent(const Twine &Filename) {
585+
auto getObjectRefImpl =
586+
[&](const Twine &Name) -> llvm::ErrorOr<std::optional<cas::ObjectRef>> {
587+
auto F = FS->openFileForRead(Name);
588+
if (!F)
589+
return F.getError();
590+
591+
auto *CASFile = dyn_cast<llvm::cas::CASBackedFile>(F->get());
592+
if (!CASFile)
593+
return std::nullopt;
594+
595+
return CASFile->getObjectRefForContent();
596+
};
597+
570598
if (FileSystemOpts.WorkingDir.empty())
571-
return FS->getObjectRefForFileContent(Filename);
599+
return getObjectRefImpl(Filename);
572600

573601
SmallString<128> FilePath;
574602
Filename.toVector(FilePath);
575603
FixupRelativePath(FilePath);
576-
return FS->getObjectRefForFileContent(FilePath);
604+
return getObjectRefImpl(FilePath);
577605
}
578606

579607
/// getStatValue - Get the 'stat' information for the specified path,

clang/lib/CAS/IncludeTree.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "clang/CAS/IncludeTree.h"
1010
#include "llvm/ADT/ArrayRef.h"
1111
#include "llvm/ADT/SmallBitVector.h"
12+
#include "llvm/CAS/CASFileSystem.h"
1213
#include "llvm/CAS/ObjectStore.h"
1314
#include "llvm/Support/EndianStream.h"
1415
#include "llvm/Support/Error.h"
@@ -899,11 +900,11 @@ namespace {
899900
/// of the preprocessor, for creating \p FileEntries using a file path, while
900901
/// "replaying" an \p IncludeTreeRoot. It is not intended to be a complete
901902
/// implementation of a file system.
902-
class IncludeTreeFileSystem : public llvm::vfs::FileSystem {
903+
class IncludeTreeFileSystem final : public llvm::cas::CASBackedFileSystem {
903904
llvm::cas::ObjectStore &CAS;
904905

905906
public:
906-
class IncludeTreeFile : public llvm::vfs::File {
907+
class IncludeTreeFile final : public llvm::cas::CASBackedFile {
907908
llvm::vfs::Status Stat;
908909
StringRef Contents;
909910
cas::ObjectRef ContentsRef;
@@ -924,10 +925,7 @@ class IncludeTreeFileSystem : public llvm::vfs::FileSystem {
924925
Name.toStringRef(NameBuf));
925926
}
926927

927-
llvm::ErrorOr<std::optional<cas::ObjectRef>>
928-
getObjectRefForContent() override {
929-
return ContentsRef;
930-
}
928+
cas::ObjectRef getObjectRefForContent() override { return ContentsRef; }
931929

932930
std::error_code close() override { return std::error_code(); }
933931
};
@@ -972,13 +970,13 @@ class IncludeTreeFileSystem : public llvm::vfs::FileSystem {
972970
return llvm::errorToErrorCode(fileError(Filename));
973971
}
974972

975-
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
976-
openFileForRead(const Twine &Path) override {
973+
llvm::Expected<std::unique_ptr<llvm::cas::CASBackedFile>>
974+
openCASBackedFileForRead(const Twine &Path) override {
977975
SmallString<128> Filename;
978976
getPath(Path, Filename);
979977
auto MaterializedFile = materialize(Filename);
980978
if (!MaterializedFile)
981-
return llvm::errorToErrorCode(MaterializedFile.takeError());
979+
return MaterializedFile.takeError();
982980
llvm::vfs::Status Stat = makeStatus(
983981
Filename, MaterializedFile->Contents.size(), MaterializedFile->UniqueID,
984982
llvm::sys::fs::file_type::regular_file);
@@ -1037,6 +1035,10 @@ class IncludeTreeFileSystem : public llvm::vfs::FileSystem {
10371035
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
10381036
return llvm::errc::operation_not_permitted;
10391037
}
1038+
IntrusiveRefCntPtr<llvm::cas::CASBackedFileSystem>
1039+
createThreadSafeProxyFS() override {
1040+
llvm::report_fatal_error("not implemented");
1041+
}
10401042
};
10411043
} // namespace
10421044

clang/lib/Tooling/DependencyScanning/DependencyScanningCASFilesystem.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ DependencyScanningCASFilesystem::DependencyScanningCASFilesystem(
4040
: FS(WorkerFS), Entries(EntryAlloc), CAS(WorkerFS->getCAS()), Cache(Cache) {
4141
}
4242

43+
const char DependencyScanningCASFilesystem::ID = 0;
4344
DependencyScanningCASFilesystem::~DependencyScanningCASFilesystem() = default;
4445

4546
static Expected<cas::ObjectRef>
@@ -276,19 +277,18 @@ bool DependencyScanningCASFilesystem::exists(const Twine &Path) {
276277
return getCachingFS().exists(Path);
277278
}
278279

279-
IntrusiveRefCntPtr<llvm::cas::ThreadSafeFileSystem>
280+
IntrusiveRefCntPtr<llvm::cas::CASBackedFileSystem>
280281
DependencyScanningCASFilesystem::createThreadSafeProxyFS() {
281282
llvm::report_fatal_error("not implemented");
282283
}
283284

284285
namespace {
285286

286-
class DepScanFile final : public llvm::vfs::File {
287+
class DepScanFile final : public llvm::cas::CASBackedFile {
287288
public:
288-
DepScanFile(StringRef Buffer, std::optional<cas::ObjectRef> CASContents,
289+
DepScanFile(StringRef Buffer, cas::ObjectRef CASContents,
289290
llvm::vfs::Status Stat)
290-
: Buffer(Buffer), CASContents(std::move(CASContents)),
291-
Stat(std::move(Stat)) {}
291+
: Buffer(Buffer), CASContents(CASContents), Stat(std::move(Stat)) {}
292292

293293
llvm::ErrorOr<llvm::vfs::Status> status() override { return Stat; }
294294

@@ -299,36 +299,35 @@ class DepScanFile final : public llvm::vfs::File {
299299
return llvm::MemoryBuffer::getMemBuffer(Buffer, Name.toStringRef(Storage));
300300
}
301301

302-
llvm::ErrorOr<std::optional<cas::ObjectRef>>
303-
getObjectRefForContent() override {
304-
return CASContents;
305-
}
302+
cas::ObjectRef getObjectRefForContent() override { return CASContents; }
306303

307304
std::error_code close() override { return {}; }
308305

309306
private:
310307
StringRef Buffer;
311-
std::optional<cas::ObjectRef> CASContents;
308+
cas::ObjectRef CASContents;
312309
llvm::vfs::Status Stat;
313310
};
314311

315312
} // end anonymous namespace
316313

317-
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
318-
DependencyScanningCASFilesystem::openFileForRead(const Twine &Path) {
314+
Expected<std::unique_ptr<llvm::cas::CASBackedFile>>
315+
DependencyScanningCASFilesystem::openCASBackedFileForRead(const Twine &Path) {
319316
LookupPathResult Result = lookupPath(Path);
320317
if (!Result.Entry) {
321318
if (std::error_code EC = Result.Status.getError())
322-
return EC;
319+
return llvm::errorCodeToError(EC);
323320
assert(Result.Status->getType() ==
324321
llvm::sys::fs::file_type::directory_file);
325-
return std::make_error_code(std::errc::is_a_directory);
322+
return llvm::createFileError(
323+
Path, std::make_error_code(std::errc::is_a_directory));
326324
}
327325
if (Result.Entry->EC)
328-
return Result.Entry->EC;
326+
return llvm::errorCodeToError(Result.Entry->EC);
329327

328+
assert(Result.Entry->CASContents);
330329
return std::make_unique<DepScanFile>(
331-
*Result.Entry->Buffer, Result.Entry->CASContents, Result.Entry->Status);
330+
*Result.Entry->Buffer, *Result.Entry->CASContents, Result.Entry->Status);
332331
}
333332

334333
std::optional<ArrayRef<dependency_directives_scan::Directive>>

clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
10+
#include "llvm/CAS/CASFileSystem.h"
1011
#include "llvm/Support/MemoryBuffer.h"
1112
#include "llvm/Support/Threading.h"
1213
#include <optional>
@@ -33,10 +34,9 @@ DependencyScanningWorkerFilesystem::readFile(StringRef Filename) {
3334
return MaybeBuffer.getError();
3435
auto Buffer = std::move(*MaybeBuffer);
3536

36-
auto MaybeCASContents = File->getObjectRefForContent();
37-
if (!MaybeCASContents)
38-
return MaybeCASContents.getError();
39-
auto CASContents = std::move(*MaybeCASContents);
37+
std::optional<cas::ObjectRef> CASContents;
38+
if (auto *CASFile = dyn_cast<llvm::cas::CASBackedFile>(File.get()))
39+
CASContents = CASFile->getObjectRefForContent();
4040

4141
// If the file size changed between read and stat, pretend it didn't.
4242
if (Stat.getSize() != Buffer->getBufferSize())
@@ -362,9 +362,8 @@ namespace {
362362
class DepScanFile final : public llvm::vfs::File {
363363
public:
364364
DepScanFile(std::unique_ptr<llvm::MemoryBuffer> Buffer,
365-
std::optional<cas::ObjectRef> CASContents, llvm::vfs::Status Stat)
366-
: Buffer(std::move(Buffer)), CASContents(std::move(CASContents)),
367-
Stat(std::move(Stat)) {}
365+
llvm::vfs::Status Stat)
366+
: Buffer(std::move(Buffer)), Stat(std::move(Stat)) {}
368367

369368
static llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> create(EntryRef Entry);
370369

@@ -376,16 +375,37 @@ class DepScanFile final : public llvm::vfs::File {
376375
return std::move(Buffer);
377376
}
378377

379-
llvm::ErrorOr<std::optional<cas::ObjectRef>>
380-
getObjectRefForContent() override {
381-
return CASContents;
378+
std::error_code close() override { return {}; }
379+
380+
private:
381+
std::unique_ptr<llvm::MemoryBuffer> Buffer;
382+
llvm::vfs::Status Stat;
383+
};
384+
385+
class DepScanCASFile final : public llvm::cas::CASBackedFile {
386+
public:
387+
DepScanCASFile(std::unique_ptr<llvm::MemoryBuffer> Buffer,
388+
cas::ObjectRef CASContents, llvm::vfs::Status Stat)
389+
: Buffer(std::move(Buffer)), CASContents(CASContents),
390+
Stat(std::move(Stat)) {}
391+
392+
static llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> create(EntryRef Entry);
393+
394+
llvm::ErrorOr<llvm::vfs::Status> status() override { return Stat; }
395+
396+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
397+
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
398+
bool IsVolatile) override {
399+
return std::move(Buffer);
382400
}
383401

402+
cas::ObjectRef getObjectRefForContent() override { return CASContents; }
403+
384404
std::error_code close() override { return {}; }
385405

386406
private:
387407
std::unique_ptr<llvm::MemoryBuffer> Buffer;
388-
std::optional<cas::ObjectRef> CASContents;
408+
cas::ObjectRef CASContents;
389409
llvm::vfs::Status Stat;
390410
};
391411

@@ -398,14 +418,22 @@ DepScanFile::create(EntryRef Entry) {
398418
if (Entry.isDirectory())
399419
return std::make_error_code(std::errc::is_a_directory);
400420

401-
auto Result = std::make_unique<DepScanFile>(
421+
std::unique_ptr<llvm::vfs::File> Result;
422+
if (Entry.getObjectRefForContent())
423+
Result = std::make_unique<DepScanCASFile>(
402424
llvm::MemoryBuffer::getMemBuffer(Entry.getContents(),
403425
Entry.getStatus().getName(),
404426
/*RequiresNullTerminator=*/false),
405-
Entry.getObjectRefForContent(), Entry.getStatus());
427+
*Entry.getObjectRefForContent(), Entry.getStatus());
428+
else
429+
Result = std::make_unique<DepScanFile>(
430+
llvm::MemoryBuffer::getMemBuffer(Entry.getContents(),
431+
Entry.getStatus().getName(),
432+
/*RequiresNullTerminator=*/false),
433+
Entry.getStatus());
434+
406435

407-
return llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>(
408-
std::unique_ptr<llvm::vfs::File>(std::move(Result)));
436+
return Result;
409437
}
410438

411439
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>

0 commit comments

Comments
 (0)