Skip to content

[SwiftCaching] Create standalone reproducer from swift caching build #82128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,11 @@ ERROR(error_load_input_from_cas, none, "failed to load input '%0' from CAS", (St

ERROR(error_wrong_input_num_for_input_file_key, none, "-input-file-key only support one input file", ())

ERROR(error_gen_reproducer_not_caching, none, "-gen-reproducer only supports swift caching", ())
ERROR(error_cannot_create_reproducer_dir, none, "failed to create reproducer director '%0': %1", (StringRef, StringRef))

NOTE(note_reproducer, none, "reproducer is available at: %0", (StringRef))

// Dependency Verifier Diagnostics
ERROR(missing_member_dependency,none,
"expected "
Expand Down
5 changes: 5 additions & 0 deletions include/swift/Frontend/CompileJobCacheKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ llvm::Error printCompileJobCacheKey(llvm::cas::ObjectStore &CAS,
llvm::cas::ObjectRef Key,
llvm::raw_ostream &os);

/// Iterating through command-line options in cache key.
llvm::Error iterateCommandLine(llvm::cas::ObjectStore &CAS,
llvm::cas::ObjectRef Key,
std::function<llvm::Error(StringRef)> Callback);

} // namespace swift

#endif
6 changes: 6 additions & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ class FrontendOptions {
/// by the Clang importer as part of semantic analysis.
bool ModuleHasBridgingHeader = false;

/// Generate reproducer.
bool GenReproducer = false;

/// Directory to generate reproducer.
std::string GenReproducerDir;

/// Indicates whether or not the frontend should print statistics upon
/// termination.
bool PrintStats = false;
Expand Down
6 changes: 6 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,12 @@ def enable_address_dependencies : Flag<["-"], "enable-address-dependencies">,
def disable_address_dependencies : Flag<["-"], "disable-address-dependencies">,
HelpText<"Disable enforcement of lifetime dependencies on addressable values.">;

def gen_reproducer : Flag<["-"], "gen-reproducer">,
HelpText<"Generate a reproducer for current compilation.">;
def gen_reproducer_dir
: Separate<["-"], "gen-reproducer-dir">,
HelpText<"Path to directory where reproducers write to.">;

} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

def disable_experimental_parser_round_trip : Flag<["-"],
Expand Down
3 changes: 3 additions & 0 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ bool ArgsToFrontendOptionsConverter::convert(
Opts.ParallelDependencyScan = Args.hasFlag(OPT_parallel_scan,
OPT_no_parallel_scan,
true);
Opts.GenReproducer |= Args.hasArg(OPT_gen_reproducer);
Opts.GenReproducerDir = Args.getLastArgValue(OPT_gen_reproducer_dir);

if (const Arg *A = Args.getLastArg(OPT_dependency_scan_cache_path)) {
Opts.SerializedDependencyScannerCachePath = A->getValue();
}
Expand Down
54 changes: 49 additions & 5 deletions lib/Frontend/CompileJobCacheKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,23 @@ swift::createCompileJobCacheKeyForOutput(llvm::cas::ObjectStore &CAS,
return CAS.storeFromString({BaseKey}, OS.str());
}

static llvm::Error validateCacheKeyNode(llvm::cas::ObjectProxy Proxy) {
if (Proxy.getData().size() != sizeof(uint32_t))
return llvm::createStringError("incorrect size for cache key node");
if (Proxy.getNumReferences() != 1)
return llvm::createStringError("incorrect child number for cache key node");

return llvm::Error::success();
}

llvm::Error swift::printCompileJobCacheKey(llvm::cas::ObjectStore &CAS,
llvm::cas::ObjectRef Key,
llvm::raw_ostream &OS) {
auto Proxy = CAS.getProxy(Key);
if (!Proxy)
return Proxy.takeError();

if (Proxy->getData().size() != sizeof(uint32_t))
return llvm::createStringError("incorrect size for cache key node");
if (Proxy->getNumReferences() != 1)
return llvm::createStringError("incorrect child number for cache key node");
if (auto Err = validateCacheKeyNode(*Proxy))
return Err;

uint32_t InputIndex = llvm::support::endian::read<uint32_t>(
Proxy->getData().data(), llvm::endianness::little);
Expand Down Expand Up @@ -153,3 +159,41 @@ llvm::Error swift::printCompileJobCacheKey(llvm::cas::ObjectStore &CAS,

return llvm::Error::success();
}

llvm::Error
swift::iterateCommandLine(llvm::cas::ObjectStore &CAS, llvm::cas::ObjectRef Key,
std::function<llvm::Error(StringRef)> Callback) {
auto Proxy = CAS.getProxy(Key);
if (!Proxy)
return Proxy.takeError();

if (auto Err = validateCacheKeyNode(*Proxy))
return Err;

auto Base = Proxy->getReference(0);
llvm::cas::TreeSchema Schema(CAS);
auto Tree = Schema.load(Base);
if (!Tree)
return Tree.takeError();

std::string BaseStr;
llvm::raw_string_ostream BaseOS(BaseStr);
return Tree->forEachEntry(
[&](const llvm::cas::NamedTreeEntry &Entry) -> llvm::Error {
auto Ref = Entry.getRef();
auto DataProxy = CAS.getProxy(Ref);
if (!DataProxy)
return DataProxy.takeError();

if (Entry.getName() != "command-line")
return llvm::Error::success();

StringRef Line, Remain = DataProxy->getData();
while (!Remain.empty()) {
std::tie(Line, Remain) = Remain.split(0);
if (auto Err = Callback(Line))
return Err;
}
return llvm::Error::success();
});
}
Loading