Skip to content

Commit afc2bab

Browse files
Merge pull request #67942 from cachemeifyoucan/eng/PR-swift-scan-plugin-cas-support
[SwiftScan][Caching] Add support for plugin CAS for caching
2 parents 5eebfc0 + 0f53e7d commit afc2bab

File tree

6 files changed

+189
-100
lines changed

6 files changed

+189
-100
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
2626
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
2727
#define SWIFTSCAN_VERSION_MAJOR 0
28-
#define SWIFTSCAN_VERSION_MINOR 4
28+
#define SWIFTSCAN_VERSION_MINOR 5
2929

3030
SWIFTSCAN_BEGIN_DECLS
3131

@@ -430,6 +430,9 @@ SWIFTSCAN_PUBLIC int invoke_swift_compiler(int argc, const char **argv);
430430

431431
//=== Scanner CAS Operations ----------------------------------------------===//
432432

433+
/// Opaque container for a CASOptions that describe how CAS should be created.
434+
typedef struct swiftscan_cas_options_s *swiftscan_cas_options_t;
435+
433436
/// Opaque container for a CAS instance that includes both ObjectStore and
434437
/// ActionCache.
435438
typedef struct swiftscan_cas_s *swiftscan_cas_t;
@@ -445,22 +448,54 @@ typedef enum {
445448
SWIFTSCAN_OUTPUT_TYPE_CLANG_PCH = 5
446449
} swiftscan_output_kind_t;
447450

448-
/// Create a \c cas instance that points to path.
449-
SWIFTSCAN_PUBLIC swiftscan_cas_t swiftscan_cas_create(const char *path);
451+
/// Create a \c CASOptions for creating CAS inside scanner specified.
452+
SWIFTSCAN_PUBLIC swiftscan_cas_options_t swiftscan_cas_options_create(void);
453+
454+
/// Dispose \c CASOptions.
455+
SWIFTSCAN_PUBLIC void
456+
swiftscan_cas_options_dispose(swiftscan_cas_options_t options);
457+
458+
/// Set on-disk path for the \c cas.
459+
SWIFTSCAN_PUBLIC void
460+
swiftscan_cas_options_set_ondisk_path(swiftscan_cas_options_t options,
461+
const char *path);
462+
463+
/// Set plugin path for the \c cas.
464+
SWIFTSCAN_PUBLIC void
465+
swiftscan_cas_options_set_plugin_path(swiftscan_cas_options_t options,
466+
const char *path);
467+
468+
/// Set option using a name/value pair. Return true if error.
469+
/// If error happens, the error message is returned via `error` parameter, and
470+
/// caller needs to free the error message via `swiftscan_string_dispose`.
471+
SWIFTSCAN_PUBLIC bool
472+
swiftscan_cas_options_set_option(swiftscan_cas_options_t options,
473+
const char *name, const char *value,
474+
swiftscan_string_ref_t *error);
475+
476+
/// Create a \c cas instance from plugin. Return NULL if error.
477+
/// If error happens, the error message is returned via `error` parameter, and
478+
/// caller needs to free the error message via `swiftscan_string_dispose`.
479+
SWIFTSCAN_PUBLIC swiftscan_cas_t swiftscan_cas_create_from_options(
480+
swiftscan_cas_options_t options, swiftscan_string_ref_t *error);
450481

451482
/// Dispose the \c cas instance.
452483
SWIFTSCAN_PUBLIC void swiftscan_cas_dispose(swiftscan_cas_t cas);
453484

454-
/// Store content into CAS. Return \c CASID as string.
455-
SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_cas_store(swiftscan_cas_t cas,
456-
uint8_t *data,
457-
unsigned size);
485+
/// Store content into CAS. Return \c CASID as string. Return NULL on error.
486+
/// If error happens, the error message is returned via `error` parameter, and
487+
/// caller needs to free the error message via `swiftscan_string_dispose`.
488+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
489+
swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, unsigned size,
490+
swiftscan_string_ref_t *error);
458491

459492
/// Compute \c CacheKey for output of \c kind from the compiler invocation \c
460493
/// argc and \c argv with \c input. Return \c CacheKey as string.
461-
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
462-
swiftscan_compute_cache_key(swiftscan_cas_t cas, int argc, const char **argv,
463-
const char *input, swiftscan_output_kind_t kind);
494+
/// If error happens, the error message is returned via `error` parameter, and
495+
/// caller needs to free the error message via `swiftscan_string_dispose`.
496+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_compute_cache_key(
497+
swiftscan_cas_t cas, int argc, const char **argv, const char *input,
498+
swiftscan_output_kind_t kind, swiftscan_string_ref_t *error);
464499

465500
//===----------------------------------------------------------------------===//
466501

include/swift/AST/DiagnosticsCommon.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ ERROR(scanner_find_cycle, none,
201201
ERROR(scanner_arguments_invalid, none,
202202
"dependencies scanner cannot be configured with arguments: '%0'", (StringRef))
203203

204+
ERROR(error_scanner_extra, none,
205+
"failed inside dependency scanner: '%0'", (StringRef))
206+
204207
WARNING(warn_scanner_deserialize_failed, none,
205208
"Failed to load module scanning dependency cache from: '%0', re-building scanner cache from scratch.", (StringRef))
206209

include/swift/Frontend/CachingUtils.h

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515

1616
#include "swift/Frontend/CachedDiagnostics.h"
1717
#include "swift/Frontend/FrontendInputsAndOutputs.h"
18+
#include "clang/CAS/CASOptions.h"
1819
#include "llvm/ADT/IntrusiveRefCntPtr.h"
1920
#include "llvm/CAS/ActionCache.h"
20-
#include "llvm/CAS/ObjectStore.h"
2121
#include "llvm/CAS/CASReference.h"
22+
#include "llvm/CAS/ObjectStore.h"
2223
#include "llvm/Support/VirtualFileSystem.h"
2324
#include "llvm/Support/VirtualOutputBackend.h"
2425
#include <memory>
@@ -58,29 +59,6 @@ llvm::Error storeCachedCompilerOutput(llvm::cas::ObjectStore &CAS,
5859
llvm::Expected<llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
5960
createCASFileSystem(llvm::cas::ObjectStore &CAS, ArrayRef<std::string> FSRoots,
6061
ArrayRef<std::string> IncludeTreeRoots);
61-
62-
namespace cas {
63-
/// Helper class to manage CAS/Caching from libSwiftScan C APIs.
64-
class CachingTool {
65-
public:
66-
// Create the tool with a list of arguments from compiler invocation.
67-
CachingTool(llvm::StringRef Path);
68-
69-
// Compute the CASID for PCH output from invocation.
70-
std::string computeCacheKey(llvm::ArrayRef<const char *> Args,
71-
StringRef InputPath, file_types::ID OutputKind);
72-
73-
// Store content into CAS.
74-
std::string storeContent(llvm::StringRef Content);
75-
76-
// Check if the tool is correctly initialized.
77-
bool isValid() const { return CAS && Cache; }
78-
79-
private:
80-
std::unique_ptr<llvm::cas::ObjectStore> CAS;
81-
std::unique_ptr<llvm::cas::ActionCache> Cache;
82-
};
83-
} // namespace cas
8462
}
8563

8664
#endif

lib/Frontend/CachingUtils.cpp

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/AST/DiagnosticsFrontend.h"
1616
#include "swift/Basic/FileTypes.h"
1717
#include "swift/Frontend/CompileJobCacheKey.h"
18+
#include "clang/CAS/CASOptions.h"
1819
#include "clang/CAS/IncludeTree.h"
1920
#include "clang/Frontend/CompileJobCacheResult.h"
2021
#include "llvm/ADT/STLExtras.h"
@@ -422,51 +423,4 @@ createCASFileSystem(ObjectStore &CAS, ArrayRef<std::string> FSRoots,
422423
return CASFS;
423424
}
424425

425-
namespace cas {
426-
427-
CachingTool::CachingTool(StringRef Path) {
428-
auto DB = llvm::cas::createOnDiskUnifiedCASDatabases(Path);
429-
if (!DB) {
430-
llvm::errs() << "Failed to create CAS at " << Path << ": "
431-
<< toString(DB.takeError()) << "\n";
432-
return;
433-
}
434-
435-
CAS = std::move(DB->first);
436-
Cache = std::move(DB->second);
437-
}
438-
439-
std::string CachingTool::computeCacheKey(ArrayRef<const char *> Args,
440-
StringRef InputPath,
441-
file_types::ID OutputKind) {
442-
auto BaseKey = createCompileJobBaseCacheKey(*CAS, Args);
443-
if (!BaseKey) {
444-
llvm::errs() << "Failed to create cache key: "
445-
<< toString(BaseKey.takeError()) << "\n";
446-
return "";
447-
}
448-
449-
auto Key =
450-
createCompileJobCacheKeyForOutput(*CAS, *BaseKey, InputPath, OutputKind);
451-
if (!Key) {
452-
llvm::errs() << "Failed to create cache key: " << toString(Key.takeError())
453-
<< "\n";
454-
return "";
455-
}
456-
457-
return CAS->getID(*Key).toString();
458-
}
459-
460-
std::string CachingTool::storeContent(StringRef Content) {
461-
auto Result = CAS->storeFromString({}, Content);
462-
if (!Result) {
463-
llvm::errs() << "Failed to store to CAS: " << toString(Result.takeError())
464-
<< "\n";
465-
return "";
466-
}
467-
468-
return CAS->getID(*Result).toString();
469-
}
470-
471-
} // namespace cas
472426
} // namespace swift

tools/libSwiftScan/libSwiftScan.cpp

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,55 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#include "swift/Basic/LLVMInitialize.h"
1817
#include "swift/Basic/InitializeSwiftModules.h"
19-
#include "swift/DriverTool/DriverTool.h"
18+
#include "swift/Basic/LLVMInitialize.h"
2019
#include "swift/DependencyScan/DependencyScanImpl.h"
2120
#include "swift/DependencyScan/DependencyScanningTool.h"
2221
#include "swift/DependencyScan/StringUtils.h"
23-
#include "swift/Frontend/CachingUtils.h"
22+
#include "swift/DriverTool/DriverTool.h"
23+
#include "swift/Frontend/CompileJobCacheKey.h"
2424
#include "swift/Option/Options.h"
25+
#include "clang/CAS/CASOptions.h"
26+
#include "llvm/CAS/ActionCache.h"
27+
#include "llvm/CAS/BuiltinUnifiedCASDatabases.h"
2528
#include "llvm/CAS/ObjectStore.h"
29+
#include "llvm/Support/Error.h"
30+
#include <memory>
2631

2732
using namespace swift::dependencies;
28-
using namespace swift::cas;
33+
34+
namespace {
35+
/// Helper class to manage CAS/Caching from libSwiftScan C APIs.
36+
class SwiftScanCAS {
37+
public:
38+
// Compute the CASID for PCH output from invocation.
39+
llvm::Expected<std::string> computeCacheKey(llvm::ArrayRef<const char *> Args,
40+
llvm::StringRef InputPath,
41+
swift::file_types::ID OutputKind);
42+
43+
// Store content into CAS.
44+
llvm::Expected<std::string> storeContent(llvm::StringRef Content);
45+
46+
// Construct SwiftScanCAS.
47+
static llvm::Expected<SwiftScanCAS *>
48+
createSwiftScanCAS(llvm::StringRef Path);
49+
50+
static llvm::Expected<SwiftScanCAS *>
51+
createSwiftScanCAS(clang::CASOptions &CASOpts);
52+
53+
private:
54+
SwiftScanCAS(std::shared_ptr<llvm::cas::ObjectStore> CAS,
55+
std::shared_ptr<llvm::cas::ActionCache> Cache)
56+
: CAS(CAS), Cache(Cache) {}
57+
58+
std::shared_ptr<llvm::cas::ObjectStore> CAS;
59+
std::shared_ptr<llvm::cas::ActionCache> Cache;
60+
};
61+
} // namespace
2962

3063
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScanningTool, swiftscan_scanner_t)
31-
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CachingTool, swiftscan_cas_t)
64+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(clang::CASOptions, swiftscan_cas_options_t)
65+
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SwiftScanCAS, swiftscan_cas_t)
3266

3367
//=== Private Cleanup Functions -------------------------------------------===//
3468

@@ -671,26 +705,58 @@ swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics){
671705

672706
//=== CAS Functions ----------------------------------------------------------//
673707

674-
swiftscan_cas_t swiftscan_cas_create(const char *path) {
675-
std::string CASPath(path);
676-
if (CASPath.empty())
677-
CASPath = llvm::cas::getDefaultOnDiskCASPath();
708+
swiftscan_cas_options_t swiftscan_cas_options_create() {
709+
clang::CASOptions *CASOpts = new clang::CASOptions();
710+
return wrap(CASOpts);
711+
}
712+
713+
void swiftscan_cas_options_dispose(swiftscan_cas_options_t options) {
714+
delete unwrap(options);
715+
}
716+
717+
void swiftscan_cas_options_set_ondisk_path(swiftscan_cas_options_t options,
718+
const char *path) {
719+
unwrap(options)->CASPath = path;
720+
}
721+
722+
void swiftscan_cas_options_set_plugin_path(swiftscan_cas_options_t options,
723+
const char *path) {
724+
unwrap(options)->PluginPath = path;
725+
}
726+
727+
bool swiftscan_cas_options_set_option(swiftscan_cas_options_t options,
728+
const char *name, const char *value,
729+
swiftscan_string_ref_t *error) {
730+
unwrap(options)->PluginOptions.emplace_back(name, value);
731+
return false;
732+
}
678733

679-
CachingTool *tool = new CachingTool(CASPath);
680-
if (!tool->isValid()) {
681-
delete tool;
734+
swiftscan_cas_t
735+
swiftscan_cas_create_from_options(swiftscan_cas_options_t options,
736+
swiftscan_string_ref_t *error) {
737+
clang::CASOptions *opts = unwrap(options);
738+
auto cas = SwiftScanCAS::createSwiftScanCAS(*opts);
739+
if (!cas) {
740+
*error =
741+
swift::c_string_utils::create_clone(toString(cas.takeError()).c_str());
682742
return nullptr;
683743
}
684-
return wrap(tool);
744+
return wrap(*cas);
685745
}
686746

687747
void swiftscan_cas_dispose(swiftscan_cas_t cas) { delete unwrap(cas); }
688748

689-
swiftscan_string_ref_t
690-
swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, unsigned size) {
749+
swiftscan_string_ref_t swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data,
750+
unsigned size,
751+
swiftscan_string_ref_t *error) {
691752
llvm::StringRef StrContent((char*)data, size);
692753
auto ID = unwrap(cas)->storeContent(StrContent);
693-
return swift::c_string_utils::create_clone(ID.c_str());
754+
if (!ID) {
755+
*error =
756+
swift::c_string_utils::create_clone(toString(ID.takeError()).c_str());
757+
return swift::c_string_utils::create_null();
758+
}
759+
return swift::c_string_utils::create_clone(ID->c_str());
694760
}
695761

696762
static swift::file_types::ID
@@ -713,14 +779,62 @@ getFileTypeFromScanOutputKind(swiftscan_output_kind_t kind) {
713779

714780
swiftscan_string_ref_t
715781
swiftscan_compute_cache_key(swiftscan_cas_t cas, int argc, const char **argv,
716-
const char *input, swiftscan_output_kind_t kind) {
782+
const char *input, swiftscan_output_kind_t kind,
783+
swiftscan_string_ref_t *error) {
717784
std::vector<const char *> Compilation;
718785
for (int i = 0; i < argc; ++i)
719786
Compilation.push_back(argv[i]);
720787

721788
auto ID = unwrap(cas)->computeCacheKey(Compilation, input,
722789
getFileTypeFromScanOutputKind(kind));
723-
return swift::c_string_utils::create_clone(ID.c_str());
790+
if (!ID) {
791+
*error =
792+
swift::c_string_utils::create_clone(toString(ID.takeError()).c_str());
793+
return swift::c_string_utils::create_null();
794+
}
795+
return swift::c_string_utils::create_clone(ID->c_str());
796+
}
797+
798+
llvm::Expected<SwiftScanCAS *>
799+
SwiftScanCAS::createSwiftScanCAS(llvm::StringRef Path) {
800+
clang::CASOptions Opts;
801+
Opts.CASPath = Path;
802+
803+
return createSwiftScanCAS(Opts);
804+
}
805+
806+
llvm::Expected<SwiftScanCAS *>
807+
SwiftScanCAS::createSwiftScanCAS(clang::CASOptions &CASOpts) {
808+
auto DB = CASOpts.getOrCreateDatabases();
809+
if (!DB)
810+
return DB.takeError();
811+
812+
return new SwiftScanCAS(std::move(DB->first), std::move(DB->second));
813+
}
814+
815+
llvm::Expected<std::string>
816+
SwiftScanCAS::computeCacheKey(llvm::ArrayRef<const char *> Args,
817+
llvm::StringRef InputPath,
818+
swift::file_types::ID OutputKind) {
819+
auto BaseKey = swift::createCompileJobBaseCacheKey(*CAS, Args);
820+
if (!BaseKey)
821+
return BaseKey.takeError();
822+
823+
auto Key = swift::createCompileJobCacheKeyForOutput(*CAS, *BaseKey, InputPath,
824+
OutputKind);
825+
if (!Key)
826+
return Key.takeError();
827+
828+
return CAS->getID(*Key).toString();
829+
}
830+
831+
llvm::Expected<std::string>
832+
SwiftScanCAS::storeContent(llvm::StringRef Content) {
833+
auto Result = CAS->storeFromString({}, Content);
834+
if (!Result)
835+
return Result.takeError();
836+
837+
return CAS->getID(*Result).toString();
724838
}
725839

726840
//=== Experimental Compiler Invocation Functions ------------------------===//

0 commit comments

Comments
 (0)