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