1//===- InMemoryModuleCache.cpp - Cache for loaded memory buffers ----------===//
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#include "clang/Serialization/InMemoryModuleCache.h"
10#include "clang/Basic/AtomicLineLogger.h"
11#include "llvm/Support/MemoryBuffer.h"
12
13using namespace clang;
14
15InMemoryModuleCache::State
16InMemoryModuleCache::getPCMState(llvm::StringRef Filename) const {
17 auto I = PCMs.find(Key: Filename);
18 if (I == PCMs.end())
19 return Unknown;
20 if (I->second.IsFinal)
21 return Final;
22 return I->second.Buffer ? Tentative : ToBuild;
23}
24
25llvm::MemoryBuffer &
26InMemoryModuleCache::addPCM(llvm::StringRef Filename,
27 std::unique_ptr<llvm::MemoryBuffer> Buffer,
28 off_t Size, time_t ModTime) {
29 Logger.log() << "pcm_add: " << Filename;
30 auto Insertion = PCMs.insert(
31 KV: std::make_pair(x&: Filename, y: PCM(std::move(Buffer), Size, ModTime)));
32 assert(Insertion.second && "Already has a PCM");
33 return *Insertion.first->second.Buffer;
34}
35
36llvm::MemoryBuffer &
37InMemoryModuleCache::addBuiltPCM(llvm::StringRef Filename,
38 std::unique_ptr<llvm::MemoryBuffer> Buffer,
39 off_t Size, time_t ModTime) {
40 Logger.log() << "pcm_add_built: " << Filename;
41 auto &PCM = PCMs[Filename];
42 assert(!PCM.IsFinal && "Trying to override finalized PCM?");
43 assert(!PCM.Buffer && "Trying to override tentative PCM?");
44 PCM.Buffer = std::move(Buffer);
45 PCM.Size = Size;
46 PCM.ModTime = ModTime;
47 PCM.IsFinal = true;
48 return *PCM.Buffer;
49}
50
51llvm::MemoryBuffer *InMemoryModuleCache::lookupPCM(llvm::StringRef Filename,
52 off_t &Size,
53 time_t &ModTime) const {
54 Logger.log() << "pcm_read_cached: " << Filename;
55 auto I = PCMs.find(Key: Filename);
56 if (I == PCMs.end())
57 return nullptr;
58 Size = I->second.Size;
59 ModTime = I->second.ModTime;
60 return I->second.Buffer.get();
61}
62
63bool InMemoryModuleCache::isPCMFinal(llvm::StringRef Filename) const {
64 return getPCMState(Filename) == Final;
65}
66
67bool InMemoryModuleCache::shouldBuildPCM(llvm::StringRef Filename) const {
68 return getPCMState(Filename) == ToBuild;
69}
70
71bool InMemoryModuleCache::tryToDropPCM(llvm::StringRef Filename) {
72 auto I = PCMs.find(Key: Filename);
73 assert(I != PCMs.end() && "PCM to remove is unknown...");
74
75 auto &PCM = I->second;
76 assert(PCM.Buffer && "PCM to remove is scheduled to be built...");
77
78 if (PCM.IsFinal) {
79 Logger.log() << "pcm_not_dropped: " << Filename;
80 return true;
81 }
82
83 Logger.log() << "pcm_dropped: " << Filename;
84 PCM.Buffer.reset();
85 return false;
86}
87
88void InMemoryModuleCache::finalizePCM(llvm::StringRef Filename) {
89 Logger.log() << "pcm_finalized: " << Filename;
90
91 auto I = PCMs.find(Key: Filename);
92 assert(I != PCMs.end() && "PCM to finalize is unknown...");
93
94 auto &PCM = I->second;
95 assert(PCM.Buffer && "Trying to finalize a dropped PCM...");
96 PCM.IsFinal = true;
97}
98