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;
40     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