mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
204
tools/swift-scan-test/swift-scan-test.cpp
Normal file
204
tools/swift-scan-test/swift-scan-test.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
//===--- swift-scan-test.cpp - Test libSwiftScan Dylib --------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2022 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// A simple program to test libSwiftScan interfaces.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/Basic/FileTypes.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
enum Actions {
|
||||
compute_cache_key,
|
||||
cache_query,
|
||||
replay_result,
|
||||
};
|
||||
|
||||
llvm::cl::OptionCategory Category("swift-scan-test Options");
|
||||
llvm::cl::opt<std::string> CASPath("cas-path", llvm::cl::desc("<path>"),
|
||||
llvm::cl::cat(Category));
|
||||
llvm::cl::opt<std::string> CASID("id", llvm::cl::desc("<casid>"),
|
||||
llvm::cl::cat(Category));
|
||||
llvm::cl::opt<std::string> Input("input", llvm::cl::desc("<file>"),
|
||||
llvm::cl::cat(Category));
|
||||
llvm::cl::opt<Actions>
|
||||
Action("action", llvm::cl::desc("<action>"),
|
||||
llvm::cl::values(clEnumVal(compute_cache_key, "compute cache key"),
|
||||
clEnumVal(cache_query, "cache query"),
|
||||
clEnumVal(replay_result, "replay result")),
|
||||
llvm::cl::cat(Category));
|
||||
llvm::cl::list<std::string>
|
||||
SwiftCommands(llvm::cl::Positional, llvm::cl::desc("<swift-frontend args>"),
|
||||
llvm::cl::cat(Category));
|
||||
|
||||
} // namespace
|
||||
|
||||
static StringRef toString(swiftscan_string_ref_t str) {
|
||||
return StringRef((const char *)str.data, str.length);
|
||||
}
|
||||
|
||||
static int printError(swiftscan_string_ref_t err) {
|
||||
llvm::errs() << toString(err) << "\n";
|
||||
swiftscan_string_dispose(err);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int action_compute_cache_key(swiftscan_cas_t cas, StringRef input,
|
||||
std::vector<const char *> &Args) {
|
||||
if (input.empty()) {
|
||||
llvm::errs() << "-input is not specified for compute_cache_key\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t err_msg;
|
||||
auto key = swiftscan_cache_compute_key(cas, Args.size(), Args.data(),
|
||||
input.str().c_str(), &err_msg);
|
||||
if (key.length == 0)
|
||||
return printError(err_msg);
|
||||
|
||||
llvm::outs() << toString(key) << "\n";
|
||||
swiftscan_string_dispose(key);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int print_cached_compilation(swiftscan_cached_compilation_t comp,
|
||||
const char *key) {
|
||||
auto numOutput = swiftscan_cached_compilation_get_num_outputs(comp);
|
||||
llvm::outs() << "Cached Compilation for key \"" << key << "\" has "
|
||||
<< numOutput << " outputs: \n";
|
||||
|
||||
for (unsigned i = 0; i < numOutput; ++i) {
|
||||
swiftscan_cached_output_t out =
|
||||
swiftscan_cached_compilation_get_output(comp, i);
|
||||
swiftscan_string_ref_t id = swiftscan_cached_output_get_casid(out);
|
||||
swiftscan_string_ref_t kind = swiftscan_cached_output_get_name(out);
|
||||
SWIFT_DEFER { swiftscan_string_dispose(kind); };
|
||||
llvm::outs() << toString(kind) << ": " << toString(id) << "\n";
|
||||
swiftscan_string_dispose(id);
|
||||
}
|
||||
llvm::outs() << "\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int action_cache_query(swiftscan_cas_t cas, const char *key) {
|
||||
swiftscan_string_ref_t err_msg;
|
||||
auto comp = swiftscan_cache_query(cas, key, /*globally=*/false, &err_msg);
|
||||
if (err_msg.length != 0)
|
||||
return printError(err_msg);
|
||||
|
||||
if (!comp) {
|
||||
llvm::errs() << "cached output not found for \"" << key << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
SWIFT_DEFER { swiftscan_cached_compilation_dispose(comp); };
|
||||
return print_cached_compilation(comp, key);
|
||||
}
|
||||
|
||||
static int action_replay_result(swiftscan_cas_t cas, const char *key,
|
||||
std::vector<const char *> &Args) {
|
||||
swiftscan_string_ref_t err_msg;
|
||||
auto comp = swiftscan_cache_query(cas, key, /*globally=*/false, &err_msg);
|
||||
if (!comp)
|
||||
return printError(err_msg);
|
||||
|
||||
SWIFT_DEFER { swiftscan_cached_compilation_dispose(comp); };
|
||||
auto numOutput = swiftscan_cached_compilation_get_num_outputs(comp);
|
||||
for (unsigned i = 0; i < numOutput; ++i) {
|
||||
auto output = swiftscan_cached_compilation_get_output(comp, i);
|
||||
SWIFT_DEFER { swiftscan_cached_output_dispose(output); };
|
||||
|
||||
if (swiftscan_cached_output_is_materialized(output))
|
||||
continue;
|
||||
|
||||
auto load = swiftscan_cached_output_load(output, &err_msg);
|
||||
if (err_msg.length != 0)
|
||||
return printError(err_msg);
|
||||
|
||||
if (!load) {
|
||||
llvm::errs() << "output at index " << i
|
||||
<< " cannot be loaded for key: " << key << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
auto instance = swiftscan_cache_replay_instance_create(Args.size(),
|
||||
Args.data(), &err_msg);
|
||||
if (!instance)
|
||||
return printError(err_msg);
|
||||
SWIFT_DEFER { swiftscan_cache_replay_instance_dispose(instance); };
|
||||
|
||||
auto result = swiftscan_cache_replay_compilation(instance, comp, &err_msg);
|
||||
if (err_msg.length != 0)
|
||||
return printError(err_msg);
|
||||
|
||||
SWIFT_DEFER { swiftscan_cache_replay_result_dispose(result); };
|
||||
|
||||
llvm::outs() << toString(swiftscan_cache_replay_result_get_stdout(result));
|
||||
llvm::errs() << toString(swiftscan_cache_replay_result_get_stderr(result));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static std::vector<const char *> createArgs(ArrayRef<std::string> Cmd,
|
||||
StringSaver &Saver) {
|
||||
if (!Cmd.empty() && StringRef(Cmd.front()).endswith("swift-frontend"))
|
||||
Cmd = Cmd.drop_front();
|
||||
|
||||
std::vector<const char *> Args;
|
||||
for (auto A : Cmd) {
|
||||
StringRef Arg = Saver.save(A);
|
||||
Args.push_back(Arg.data());
|
||||
}
|
||||
|
||||
return Args;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
llvm::cl::HideUnrelatedOptions(Category);
|
||||
llvm::cl::ParseCommandLineOptions(argc, argv,
|
||||
"Test libSwiftScan interfaces\n");
|
||||
|
||||
// Create CAS.
|
||||
auto option = swiftscan_cas_options_create();
|
||||
SWIFT_DEFER { swiftscan_cas_options_dispose(option); };
|
||||
swiftscan_cas_options_set_ondisk_path(option, CASPath.c_str());
|
||||
|
||||
swiftscan_string_ref_t err_msg;
|
||||
auto cas = swiftscan_cas_create_from_options(option, &err_msg);
|
||||
if (!cas)
|
||||
return printError(err_msg);
|
||||
SWIFT_DEFER { swiftscan_cas_dispose(cas); };
|
||||
|
||||
// Convert commands.
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
llvm::StringSaver Saver(Alloc);
|
||||
auto Args = createArgs(SwiftCommands, Saver);
|
||||
|
||||
switch (Action) {
|
||||
case compute_cache_key:
|
||||
return action_compute_cache_key(cas, Input, Args);
|
||||
case cache_query:
|
||||
return action_cache_query(cas, CASID.c_str());
|
||||
case replay_result:
|
||||
return action_replay_result(cas, CASID.c_str(), Args);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user