blob: 7b5b5c1cf1be95bc4f286a654ee5ae3341075e67 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===- 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
18namespace 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.
30class 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
47public:
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