[SwiftScan][Caching] Add support for plugin CAS for caching

Teach libSwiftScan about plugin CAS and add API to create plugin CAS to
use for dependency scanning and cas operations.
This commit is contained in:
Steven Wu
2023-08-15 10:35:38 -07:00
parent 2c3c3c1933
commit 0f53e7db46
6 changed files with 189 additions and 100 deletions

View File

@@ -14,21 +14,55 @@
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/InitializeSwiftModules.h"
#include "swift/DriverTool/DriverTool.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/DependencyScan/DependencyScanImpl.h"
#include "swift/DependencyScan/DependencyScanningTool.h"
#include "swift/DependencyScan/StringUtils.h"
#include "swift/Frontend/CachingUtils.h"
#include "swift/DriverTool/DriverTool.h"
#include "swift/Frontend/CompileJobCacheKey.h"
#include "swift/Option/Options.h"
#include "clang/CAS/CASOptions.h"
#include "llvm/CAS/ActionCache.h"
#include "llvm/CAS/BuiltinUnifiedCASDatabases.h"
#include "llvm/CAS/ObjectStore.h"
#include "llvm/Support/Error.h"
#include <memory>
using namespace swift::dependencies;
using namespace swift::cas;
namespace {
/// Helper class to manage CAS/Caching from libSwiftScan C APIs.
class SwiftScanCAS {
public:
// Compute the CASID for PCH output from invocation.
llvm::Expected<std::string> computeCacheKey(llvm::ArrayRef<const char *> Args,
llvm::StringRef InputPath,
swift::file_types::ID OutputKind);
// Store content into CAS.
llvm::Expected<std::string> storeContent(llvm::StringRef Content);
// Construct SwiftScanCAS.
static llvm::Expected<SwiftScanCAS *>
createSwiftScanCAS(llvm::StringRef Path);
static llvm::Expected<SwiftScanCAS *>
createSwiftScanCAS(clang::CASOptions &CASOpts);
private:
SwiftScanCAS(std::shared_ptr<llvm::cas::ObjectStore> CAS,
std::shared_ptr<llvm::cas::ActionCache> Cache)
: CAS(CAS), Cache(Cache) {}
std::shared_ptr<llvm::cas::ObjectStore> CAS;
std::shared_ptr<llvm::cas::ActionCache> Cache;
};
} // namespace
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScanningTool, swiftscan_scanner_t)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CachingTool, swiftscan_cas_t)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(clang::CASOptions, swiftscan_cas_options_t)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SwiftScanCAS, swiftscan_cas_t)
//=== Private Cleanup Functions -------------------------------------------===//
@@ -671,26 +705,58 @@ swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics){
//=== CAS Functions ----------------------------------------------------------//
swiftscan_cas_t swiftscan_cas_create(const char *path) {
std::string CASPath(path);
if (CASPath.empty())
CASPath = llvm::cas::getDefaultOnDiskCASPath();
swiftscan_cas_options_t swiftscan_cas_options_create() {
clang::CASOptions *CASOpts = new clang::CASOptions();
return wrap(CASOpts);
}
CachingTool *tool = new CachingTool(CASPath);
if (!tool->isValid()) {
delete tool;
void swiftscan_cas_options_dispose(swiftscan_cas_options_t options) {
delete unwrap(options);
}
void swiftscan_cas_options_set_ondisk_path(swiftscan_cas_options_t options,
const char *path) {
unwrap(options)->CASPath = path;
}
void swiftscan_cas_options_set_plugin_path(swiftscan_cas_options_t options,
const char *path) {
unwrap(options)->PluginPath = path;
}
bool swiftscan_cas_options_set_option(swiftscan_cas_options_t options,
const char *name, const char *value,
swiftscan_string_ref_t *error) {
unwrap(options)->PluginOptions.emplace_back(name, value);
return false;
}
swiftscan_cas_t
swiftscan_cas_create_from_options(swiftscan_cas_options_t options,
swiftscan_string_ref_t *error) {
clang::CASOptions *opts = unwrap(options);
auto cas = SwiftScanCAS::createSwiftScanCAS(*opts);
if (!cas) {
*error =
swift::c_string_utils::create_clone(toString(cas.takeError()).c_str());
return nullptr;
}
return wrap(tool);
return wrap(*cas);
}
void swiftscan_cas_dispose(swiftscan_cas_t cas) { delete unwrap(cas); }
swiftscan_string_ref_t
swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, unsigned size) {
swiftscan_string_ref_t swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data,
unsigned size,
swiftscan_string_ref_t *error) {
llvm::StringRef StrContent((char*)data, size);
auto ID = unwrap(cas)->storeContent(StrContent);
return swift::c_string_utils::create_clone(ID.c_str());
if (!ID) {
*error =
swift::c_string_utils::create_clone(toString(ID.takeError()).c_str());
return swift::c_string_utils::create_null();
}
return swift::c_string_utils::create_clone(ID->c_str());
}
static swift::file_types::ID
@@ -713,14 +779,62 @@ getFileTypeFromScanOutputKind(swiftscan_output_kind_t kind) {
swiftscan_string_ref_t
swiftscan_compute_cache_key(swiftscan_cas_t cas, int argc, const char **argv,
const char *input, swiftscan_output_kind_t kind) {
const char *input, swiftscan_output_kind_t kind,
swiftscan_string_ref_t *error) {
std::vector<const char *> Compilation;
for (int i = 0; i < argc; ++i)
Compilation.push_back(argv[i]);
auto ID = unwrap(cas)->computeCacheKey(Compilation, input,
getFileTypeFromScanOutputKind(kind));
return swift::c_string_utils::create_clone(ID.c_str());
if (!ID) {
*error =
swift::c_string_utils::create_clone(toString(ID.takeError()).c_str());
return swift::c_string_utils::create_null();
}
return swift::c_string_utils::create_clone(ID->c_str());
}
llvm::Expected<SwiftScanCAS *>
SwiftScanCAS::createSwiftScanCAS(llvm::StringRef Path) {
clang::CASOptions Opts;
Opts.CASPath = Path;
return createSwiftScanCAS(Opts);
}
llvm::Expected<SwiftScanCAS *>
SwiftScanCAS::createSwiftScanCAS(clang::CASOptions &CASOpts) {
auto DB = CASOpts.getOrCreateDatabases();
if (!DB)
return DB.takeError();
return new SwiftScanCAS(std::move(DB->first), std::move(DB->second));
}
llvm::Expected<std::string>
SwiftScanCAS::computeCacheKey(llvm::ArrayRef<const char *> Args,
llvm::StringRef InputPath,
swift::file_types::ID OutputKind) {
auto BaseKey = swift::createCompileJobBaseCacheKey(*CAS, Args);
if (!BaseKey)
return BaseKey.takeError();
auto Key = swift::createCompileJobCacheKeyForOutput(*CAS, *BaseKey, InputPath,
OutputKind);
if (!Key)
return Key.takeError();
return CAS->getID(*Key).toString();
}
llvm::Expected<std::string>
SwiftScanCAS::storeContent(llvm::StringRef Content) {
auto Result = CAS->storeFromString({}, Content);
if (!Result)
return Result.takeError();
return CAS->getID(*Result).toString();
}
//=== Experimental Compiler Invocation Functions ------------------------===//