1 //===- InMemoryModuleCache.h - In-memory cache for modules ------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_SERIALIZATION_INMEMORYMODULECACHE_H 10 #define LLVM_CLANG_SERIALIZATION_INMEMORYMODULECACHE_H 11 12 #include "llvm/ADT/IntrusiveRefCntPtr.h" 13 #include "llvm/ADT/StringMap.h" 14 #include "llvm/Support/MemoryBuffer.h" 15 #include <memory> 16 17 namespace clang { 18 19 /// In-memory cache for modules. 20 /// 21 /// This is a cache for modules for use across a compilation, sharing state 22 /// between the CompilerInstances in an implicit modules build. It must be 23 /// shared by each CompilerInstance, ASTReader, ASTWriter, and ModuleManager 24 /// that are coordinating. 25 /// 26 /// Critically, it ensures that a single process has a consistent view of each 27 /// PCM. This is used by \a CompilerInstance when building PCMs to ensure that 28 /// each \a ModuleManager sees the same files. 29 class InMemoryModuleCache : public llvm::RefCountedBase<InMemoryModuleCache> { 30 struct PCM { 31 std::unique_ptr<llvm::MemoryBuffer> Buffer; 32 33 /// Track whether this PCM is known to be good (either built or 34 /// successfully imported by a CompilerInstance/ASTReader using this 35 /// cache). 36 bool IsFinal = false; 37 38 PCM() = default; PCMPCM39 PCM(std::unique_ptr<llvm::MemoryBuffer> Buffer) 40 : Buffer(std::move(Buffer)) {} 41 }; 42 43 /// Cache of buffers. 44 llvm::StringMap<PCM> PCMs; 45 46 public: 47 /// There are four states for a PCM. It must monotonically increase. 48 /// 49 /// 1. Unknown: the PCM has neither been read from disk nor built. 50 /// 2. Tentative: the PCM has been read from disk but not yet imported or 51 /// built. It might work. 52 /// 3. ToBuild: the PCM read from disk did not work but a new one has not 53 /// been built yet. 54 /// 4. Final: indicating that the current PCM was either built in this 55 /// process or has been successfully imported. 56 enum State { Unknown, Tentative, ToBuild, Final }; 57 58 /// Get the state of the PCM. 59 State getPCMState(llvm::StringRef Filename) const; 60 61 /// Store the PCM under the Filename. 62 /// 63 /// \pre state is Unknown 64 /// \post state is Tentative 65 /// \return a reference to the buffer as a convenience. 66 llvm::MemoryBuffer &addPCM(llvm::StringRef Filename, 67 std::unique_ptr<llvm::MemoryBuffer> Buffer); 68 69 /// Store a just-built PCM under the Filename. 70 /// 71 /// \pre state is Unknown or ToBuild. 72 /// \pre state is not Tentative. 73 /// \return a reference to the buffer as a convenience. 74 llvm::MemoryBuffer &addBuiltPCM(llvm::StringRef Filename, 75 std::unique_ptr<llvm::MemoryBuffer> Buffer); 76 77 /// Try to remove a buffer from the cache. No effect if state is Final. 78 /// 79 /// \pre state is Tentative/Final. 80 /// \post Tentative => ToBuild or Final => Final. 81 /// \return false on success, i.e. if Tentative => ToBuild. 82 bool tryToDropPCM(llvm::StringRef Filename); 83 84 /// Mark a PCM as final. 85 /// 86 /// \pre state is Tentative or Final. 87 /// \post state is Final. 88 void finalizePCM(llvm::StringRef Filename); 89 90 /// Get a pointer to the pCM if it exists; else nullptr. 91 llvm::MemoryBuffer *lookupPCM(llvm::StringRef Filename) const; 92 93 /// Check whether the PCM is final and has been shown to work. 94 /// 95 /// \return true iff state is Final. 96 bool isPCMFinal(llvm::StringRef Filename) const; 97 98 /// Check whether the PCM is waiting to be built. 99 /// 100 /// \return true iff state is ToBuild. 101 bool shouldBuildPCM(llvm::StringRef Filename) const; 102 }; 103 104 } // end namespace clang 105 106 #endif // LLVM_CLANG_SERIALIZATION_INMEMORYMODULECACHE_H 107