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

Reply via email to