[Caching] Add new CacheReplay APIs to libSwiftScan

Add new APIs libSwiftScan that can be used for cache query and cache
replay. This enables swift-driver or build system to query the cache and
replay the compilation results without invocation swift-frontend for
better scheduling.
This commit is contained in:
Steven Wu
2023-10-26 10:48:05 -07:00
parent 30cfa3deb2
commit 034c15ce54
13 changed files with 1437 additions and 245 deletions

View File

@@ -20,48 +20,11 @@
#include "swift/DependencyScan/DependencyScanningTool.h"
#include "swift/DependencyScan/StringUtils.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;
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);
// 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(clang::CASOptions, swiftscan_cas_options_t)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SwiftScanCAS, swiftscan_cas_t)
//=== Private Cleanup Functions -------------------------------------------===//
@@ -714,119 +677,6 @@ swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics){
delete diagnostics;
}
//=== CAS Functions ----------------------------------------------------------//
swiftscan_cas_options_t swiftscan_cas_options_create() {
clang::CASOptions *CASOpts = new clang::CASOptions();
return wrap(CASOpts);
}
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(*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 *error) {
llvm::StringRef StrContent((char*)data, size);
auto ID = unwrap(cas)->storeContent(StrContent);
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());
}
swiftscan_string_ref_t
swiftscan_cache_compute_key(swiftscan_cas_t cas, int argc, const char **argv,
const char *input, 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);
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) {
auto BaseKey = swift::createCompileJobBaseCacheKey(*CAS, Args);
if (!BaseKey)
return BaseKey.takeError();
auto Key =
swift::createCompileJobCacheKeyForOutput(*CAS, *BaseKey, InputPath);
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 ------------------------===//
int invoke_swift_compiler(int argc, const char **argv) {