1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
//===- CASOptions.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/CAS/CASOptions.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticCAS.h"
#include "llvm/CAS/ActionCache.h"
#include "llvm/CAS/BuiltinUnifiedCASDatabases.h"
#include "llvm/CAS/ObjectStore.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
using namespace clang;
using namespace llvm::cas;
std::pair<std::shared_ptr<llvm::cas::ObjectStore>,
std::shared_ptr<llvm::cas::ActionCache>>
CASOptions::getOrCreateDatabases(DiagnosticsEngine &Diags,
bool CreateEmptyDBsOnFailure) const {
if (Cache.Config.IsFrozen)
return {Cache.CAS, Cache.AC};
if (auto E = initCache())
Diags.Report(diag::err_cas_cannot_be_initialized) << toString(std::move(E));
if (!Cache.CAS && CreateEmptyDBsOnFailure)
Cache.CAS = llvm::cas::createInMemoryCAS();
if (!Cache.AC && CreateEmptyDBsOnFailure)
Cache.AC = llvm::cas::createInMemoryActionCache();
return {Cache.CAS, Cache.AC};
}
llvm::Expected<std::pair<std::shared_ptr<llvm::cas::ObjectStore>,
std::shared_ptr<llvm::cas::ActionCache>>>
CASOptions::getOrCreateDatabases() const {
if (auto E = initCache())
return std::move(E);
return std::pair{Cache.CAS, Cache.AC};
}
void CASOptions::freezeConfig(DiagnosticsEngine &Diags) {
if (Cache.Config.IsFrozen)
return;
// Make sure the cache is initialized.
if (auto E = initCache())
Diags.Report(diag::err_cas_cannot_be_initialized) << toString(std::move(E));
// Freeze the CAS and wipe out the visible config to hide it from future
// accesses. For example, future diagnostics cannot see this. Something that
// needs direct access to the CAS configuration will need to be
// scheduled/executed at a level that has access to the configuration.
auto &CurrentConfig = static_cast<CASConfiguration &>(*this);
CurrentConfig = CASConfiguration();
CurrentConfig.IsFrozen = Cache.Config.IsFrozen = true;
if (Cache.CAS) {
// Set the CASPath to the hash schema, since that leaks through CASContext's
// API and is observable.
CurrentConfig.CASPath =
Cache.CAS->getContext().getHashSchemaIdentifier().str();
CurrentConfig.PluginPath.clear();
CurrentConfig.PluginOptions.clear();
}
}
void CASOptions::ensurePersistentCAS() {
assert(!IsFrozen && "Expected to check for a persistent CAS before freezing");
switch (getKind()) {
case UnknownCAS:
llvm_unreachable("Cannot ensure persistent CAS if it's unknown / frozen");
case InMemoryCAS:
CASPath = "auto";
break;
case OnDiskCAS:
break;
}
}
llvm::Error CASOptions::initCache() const {
auto &CurrentConfig = static_cast<const CASConfiguration &>(*this);
if (CurrentConfig == Cache.Config && Cache.CAS && Cache.AC)
return llvm::Error::success();
Cache.Config = CurrentConfig;
StringRef CASPath = Cache.Config.CASPath;
if (!PluginPath.empty()) {
std::pair<std::shared_ptr<ObjectStore>, std::shared_ptr<ActionCache>> DBs;
if (llvm::Error E =
createPluginCASDatabases(PluginPath, CASPath, PluginOptions)
.moveInto(DBs)) {
return E;
}
std::tie(Cache.CAS, Cache.AC) = std::move(DBs);
return llvm::Error::success();
}
if (CASPath.empty()) {
Cache.CAS = llvm::cas::createInMemoryCAS();
Cache.AC = llvm::cas::createInMemoryActionCache();
return llvm::Error::success();
}
SmallString<256> PathBuf;
if (CASPath == "auto") {
getDefaultOnDiskCASPath(PathBuf);
CASPath = PathBuf;
}
std::pair<std::unique_ptr<ObjectStore>, std::unique_ptr<ActionCache>> DBs;
if (llvm::Error E = createOnDiskUnifiedCASDatabases(CASPath).moveInto(DBs))
return E;
std::tie(Cache.CAS, Cache.AC) = std::move(DBs);
return llvm::Error::success();
}
|