mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Virtualize swift compiler outputs (#63206)
Using a virutal output backend to capture all the outputs from swift-frontend invocation. This allows redirecting and/or mirroring compiler outputs to multiple location using different OutputBackend. As an example usage for the virtual outputs, teach swift compiler to check its output determinism by running the compiler invocation twice and compare the hash of all its outputs. Virtual output will be used to enable caching in the future.
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/VirtualOutputBackend.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/xxhash.h"
|
||||
@@ -901,8 +902,8 @@ class ModuleInterfaceLoaderImpl {
|
||||
/// this. If the write was successful, it also updates the
|
||||
/// list of dependencies to match what was written to the forwarding file.
|
||||
bool writeForwardingModuleAndUpdateDeps(
|
||||
const DiscoveredModule &mod, StringRef outputPath,
|
||||
SmallVectorImpl<FileDependency> &deps) {
|
||||
const DiscoveredModule &mod, llvm::vfs::OutputBackend &backend,
|
||||
StringRef outputPath, SmallVectorImpl<FileDependency> &deps) {
|
||||
assert(mod.isPrebuilt() &&
|
||||
"cannot write forwarding file for non-prebuilt module");
|
||||
ForwardingModule fwd(mod.path);
|
||||
@@ -938,16 +939,12 @@ class ModuleInterfaceLoaderImpl {
|
||||
depsAdjustedToMTime.push_back(adjustedDep);
|
||||
}
|
||||
|
||||
// Create the module cache if we haven't created it yet.
|
||||
StringRef parentDir = path::parent_path(outputPath);
|
||||
(void)llvm::sys::fs::create_directories(parentDir);
|
||||
|
||||
auto hadError = withOutputFile(diags, outputPath,
|
||||
[&](llvm::raw_pwrite_stream &out) {
|
||||
llvm::yaml::Output yamlWriter(out);
|
||||
yamlWriter << fwd;
|
||||
return false;
|
||||
});
|
||||
auto hadError = withOutputPath(diags, backend, outputPath,
|
||||
[&](llvm::raw_pwrite_stream &out) {
|
||||
llvm::yaml::Output yamlWriter(out);
|
||||
yamlWriter << fwd;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hadError)
|
||||
return true;
|
||||
@@ -1006,8 +1003,8 @@ class ModuleInterfaceLoaderImpl {
|
||||
// If it's prebuilt, use this time to generate a forwarding module and
|
||||
// update the dependencies to use modification times.
|
||||
if (module.isPrebuilt())
|
||||
if (writeForwardingModuleAndUpdateDeps(module, cachedOutputPath,
|
||||
allDeps))
|
||||
if (writeForwardingModuleAndUpdateDeps(module, ctx.getOutputBackend(),
|
||||
cachedOutputPath, allDeps))
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
|
||||
// Report the module's dependencies to the dependencyTracker
|
||||
@@ -1251,7 +1248,8 @@ ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface(StringRef mo
|
||||
|
||||
bool ModuleInterfaceCheckerImpl::tryEmitForwardingModule(
|
||||
StringRef moduleName, StringRef interfacePath,
|
||||
ArrayRef<std::string> candidates, StringRef outputPath) {
|
||||
ArrayRef<std::string> candidates, llvm::vfs::OutputBackend &backend,
|
||||
StringRef outputPath) {
|
||||
// Derive .swiftmodule path from the .swiftinterface path.
|
||||
auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
|
||||
llvm::SmallString<32> modulePath = interfacePath;
|
||||
@@ -1269,12 +1267,12 @@ bool ModuleInterfaceCheckerImpl::tryEmitForwardingModule(
|
||||
deps, moduleBuffer)) {
|
||||
// If so, emit a forwarding module to the candidate.
|
||||
ForwardingModule FM(mod);
|
||||
auto hadError = withOutputFile(Ctx.Diags, outputPath,
|
||||
[&](llvm::raw_pwrite_stream &out) {
|
||||
llvm::yaml::Output yamlWriter(out);
|
||||
yamlWriter << FM;
|
||||
return false;
|
||||
});
|
||||
auto hadError = withOutputPath(Ctx.Diags, backend, outputPath,
|
||||
[&](llvm::raw_pwrite_stream &out) {
|
||||
llvm::yaml::Output yamlWriter(out);
|
||||
yamlWriter << FM;
|
||||
return false;
|
||||
});
|
||||
if (!hadError)
|
||||
return true;
|
||||
}
|
||||
@@ -1402,19 +1400,25 @@ bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface(
|
||||
ArrayRef<std::string> CompiledCandidates,
|
||||
DependencyTracker *tracker) {
|
||||
|
||||
// First, check if the expected output already exists and possibly up-to-date w.r.t.
|
||||
// all of the dependencies it was built with. If so, early exit.
|
||||
UpToDateModuleCheker checker(Instance.getASTContext(),
|
||||
RequireOSSAModules_t(Instance.getSILOptions()));
|
||||
ModuleRebuildInfo rebuildInfo;
|
||||
SmallVector<FileDependency, 3> allDeps;
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
|
||||
if (checker.swiftModuleIsUpToDate(outputPath, rebuildInfo, allDeps, moduleBuffer)) {
|
||||
if (Instance.getASTContext().LangOpts.EnableSkipExplicitInterfaceModuleBuildRemarks) {
|
||||
Instance.getDiags().diagnose(SourceLoc(),
|
||||
diag::explicit_interface_build_skipped, outputPath);
|
||||
if (!Instance.getInvocation().getIRGenOptions().AlwaysCompile) {
|
||||
// First, check if the expected output already exists and possibly
|
||||
// up-to-date w.r.t. all of the dependencies it was built with. If so, early
|
||||
// exit.
|
||||
UpToDateModuleCheker checker(
|
||||
Instance.getASTContext(),
|
||||
RequireOSSAModules_t(Instance.getSILOptions()));
|
||||
ModuleRebuildInfo rebuildInfo;
|
||||
SmallVector<FileDependency, 3> allDeps;
|
||||
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
|
||||
if (checker.swiftModuleIsUpToDate(outputPath, rebuildInfo, allDeps,
|
||||
moduleBuffer)) {
|
||||
if (Instance.getASTContext()
|
||||
.LangOpts.EnableSkipExplicitInterfaceModuleBuildRemarks) {
|
||||
Instance.getDiags().diagnose(
|
||||
SourceLoc(), diag::explicit_interface_build_skipped, outputPath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read out the compiler version.
|
||||
|
||||
Reference in New Issue
Block a user