https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/188876
>From ea542c7a001a8f27d01b72aa2196bb1945679875 Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Thu, 12 Mar 2026 12:47:26 -0700 Subject: [PATCH 1/2] [clang] Introduce `ModuleCache::read()` --- .../include/clang/Serialization/ModuleCache.h | 12 +++++- .../InProcessModuleCache.cpp | 7 ++++ clang/lib/Serialization/ModuleCache.cpp | 26 ++++++++++++ clang/lib/Serialization/ModuleManager.cpp | 41 ++++++++++--------- 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/Serialization/ModuleCache.h b/clang/include/clang/Serialization/ModuleCache.h index c6795c5dc358a..3846f9cecd36f 100644 --- a/clang/include/clang/Serialization/ModuleCache.h +++ b/clang/include/clang/Serialization/ModuleCache.h @@ -10,11 +10,14 @@ #define LLVM_CLANG_SERIALIZATION_MODULECACHE_H #include "clang/Basic/LLVM.h" +#include "llvm/Support/ErrorOr.h" #include <ctime> +#include <memory> namespace llvm { class AdvisoryLock; +class MemoryBuffer; } // namespace llvm namespace clang { @@ -52,7 +55,10 @@ class ModuleCache { virtual InMemoryModuleCache &getInMemoryModuleCache() = 0; virtual const InMemoryModuleCache &getInMemoryModuleCache() const = 0; - // TODO: Virtualize writing/reading PCM files, etc. + // TODO: Virtualize writing PCM files. + + virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + read(StringRef FileName, off_t &Size, time_t &ModTime) = 0; virtual ~ModuleCache() = default; }; @@ -65,6 +71,10 @@ std::shared_ptr<ModuleCache> createCrossProcessModuleCache(); /// Shared implementation of `ModuleCache::maybePrune()`. void maybePruneImpl(StringRef Path, time_t PruneInterval, time_t PruneAfter); + +/// Shared implementation of `ModuleCache::load()`. +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +readImpl(StringRef FileName, off_t &Size, time_t &ModTime); } // namespace clang #endif diff --git a/clang/lib/DependencyScanning/InProcessModuleCache.cpp b/clang/lib/DependencyScanning/InProcessModuleCache.cpp index cd7385c8f38c2..b8db12689c837 100644 --- a/clang/lib/DependencyScanning/InProcessModuleCache.cpp +++ b/clang/lib/DependencyScanning/InProcessModuleCache.cpp @@ -131,6 +131,13 @@ class InProcessModuleCache : public ModuleCache { const InMemoryModuleCache &getInMemoryModuleCache() const override { return InMemory; } + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + read(StringRef FileName, off_t &Size, time_t &ModTime) override { + // FIXME: This only needs to go to disk once per build, not in every + // compilation. Introduce in-memory cache. + return readImpl(FileName, Size, ModTime); + } }; } // namespace diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp index 658da6e3b7145..11c9ba8f5d17d 100644 --- a/clang/lib/Serialization/ModuleCache.cpp +++ b/clang/lib/Serialization/ModuleCache.cpp @@ -101,6 +101,24 @@ void clang::maybePruneImpl(StringRef Path, time_t PruneInterval, } } +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +clang::readImpl(StringRef FileName, off_t &Size, time_t &ModTime) { + std::error_code EC; + int FD; + if ((EC = llvm::sys::fs::openFileForRead(FileName, FD))) + return EC; + llvm::sys::fs::file_status Status; + if ((EC = llvm::sys::fs::status(FD, Status))) + return EC; + auto BufOrErr = llvm::MemoryBuffer::getOpenFile( + FD, FileName, Status.getSize(), /*RequiresNullTerminator=*/false); + if (!BufOrErr) + return BufOrErr.getError(); + Size = Status.getSize(); + ModTime = llvm::sys::toTimeT(Status.getLastModificationTime()); + return std::move(*BufOrErr); +} + namespace { class CrossProcessModuleCache : public ModuleCache { InMemoryModuleCache InMemory; @@ -161,6 +179,14 @@ class CrossProcessModuleCache : public ModuleCache { const InMemoryModuleCache &getInMemoryModuleCache() const override { return InMemory; } + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + read(StringRef FileName, off_t &Size, time_t &ModTime) override { + // This is a compiler-internal input/output, let's bypass the sandbox. + auto BypassSandbox = llvm::sys::sandbox::scopedDisable(); + + return readImpl(FileName, Size, ModTime); + } }; } // namespace diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index ed7b6cf67674e..32914e43cf6a0 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -188,33 +188,34 @@ ModuleManager::AddModuleResult ModuleManager::addModule( // import it earlier. return OutOfDate; } else { - OptionalFileEntryRef Entry = - expectedToOptional(FileName == StringRef("-") - ? FileMgr.getSTDIN() - : FileMgr.getFileRef(FileName, /*OpenFile=*/true, - /*CacheFailure=*/false)); - if (!Entry) { - ErrorStr = "module file not found"; - return Missing; - } + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf = nullptr; + if (FileName.getImplicitModuleSuffixLength()) { + Buf = ModCache.read(FileName, Size, ModTime); + } else { + OptionalFileEntryRef Entry = expectedToOptional( + FileName == StringRef("-") + ? FileMgr.getSTDIN() + : FileMgr.getFileRef(FileName, /*OpenFile=*/true, + /*CacheFailure=*/false)); + if (!Entry) { + ErrorStr = "module file not found"; + return Missing; + } - // Get a buffer of the file and close the file descriptor when done. - // The file is volatile because in a parallel build we expect multiple - // compiler processes to use the same module file rebuilding it if needed. - // - // RequiresNullTerminator is false because module files don't need it, and - // this allows the file to still be mmapped. - auto Buf = FileMgr.getBufferForFile(*Entry, - /*IsVolatile=*/true, - /*RequiresNullTerminator=*/false); + Size = Entry->getSize(); + ModTime = Entry->getModificationTime(); + + // RequiresNullTerminator is false because module files don't need it, and + // this allows the file to still be mmapped. + Buf = FileMgr.getBufferForFile(*Entry, /*IsVolatile=*/false, + /*RequiresNullTerminator=*/false); + } if (!Buf) { ErrorStr = Buf.getError().message(); return Missing; } - Size = Entry->getSize(); - ModTime = Entry->getModificationTime(); NewFileBuffer = std::move(*Buf); ModuleBuffer = NewFileBuffer.get(); } >From dabb1d50468d494b6b7913f0a4ab5f7a7250817f Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Fri, 27 Mar 2026 09:50:18 -0700 Subject: [PATCH 2/2] Use `llvm::sys::fs::file_t` --- clang/lib/Serialization/ModuleCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp index 11c9ba8f5d17d..ec93ea2896eab 100644 --- a/clang/lib/Serialization/ModuleCache.cpp +++ b/clang/lib/Serialization/ModuleCache.cpp @@ -104,7 +104,7 @@ void clang::maybePruneImpl(StringRef Path, time_t PruneInterval, llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> clang::readImpl(StringRef FileName, off_t &Size, time_t &ModTime) { std::error_code EC; - int FD; + llvm::sys::fs::file_t FD; if ((EC = llvm::sys::fs::openFileForRead(FileName, FD))) return EC; llvm::sys::fs::file_status Status; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
