Skip to content
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
4 changes: 4 additions & 0 deletions include/swift/AST/IRGenRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct IRGenDescriptor {
const PrimarySpecificPaths &PSPs;
StringRef PrivateDiscriminator;
ArrayRef<std::string> parallelOutputFilenames;
ArrayRef<std::string> parallelIROutputFilenames;
llvm::GlobalVariable **outModuleHash;
llvm::raw_pwrite_stream *out = nullptr;

Expand Down Expand Up @@ -188,6 +189,7 @@ struct IRGenDescriptor {
PSPs,
PrivateDiscriminator,
{},
{},
outModuleHash};
}

Expand All @@ -197,6 +199,7 @@ struct IRGenDescriptor {
std::unique_ptr<SILModule> &&SILMod, StringRef ModuleName,
const PrimarySpecificPaths &PSPs, SymsToEmit symsToEmit = std::nullopt,
ArrayRef<std::string> parallelOutputFilenames = {},
ArrayRef<std::string> parallelIROutputFilenames = {},
llvm::GlobalVariable **outModuleHash = nullptr) {
return IRGenDescriptor{M,
symsToEmit,
Expand All @@ -209,6 +212,7 @@ struct IRGenDescriptor {
PSPs,
"",
parallelOutputFilenames,
parallelIROutputFilenames,
outModuleHash};
}

Expand Down
6 changes: 6 additions & 0 deletions include/swift/Basic/SupplementaryOutputPaths.def
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,9 @@ OUTPUT(YAMLOptRecordPath, TY_YAMLOptRecord)

/// The output path for bitstream optimization record file.
OUTPUT(BitstreamOptRecordPath, TY_BitstreamOptRecord)

/// The output path to which we should output SIL as extra compilation output.
OUTPUT(SILOutputPath, TY_SIL)

/// The output path to which we should output LLVM IR as extra compilation output.
OUTPUT(LLVMIROutputPath, TY_LLVM_IR)
3 changes: 2 additions & 1 deletion include/swift/FrontendTool/FrontendTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ int performFrontend(ArrayRef<const char *> args,
FrontendObserver *observer = nullptr);

bool performCompileStepsPostSema(CompilerInstance &Instance, int &ReturnValue,
FrontendObserver *observer);
FrontendObserver *observer,
ArrayRef<const char *> CommandLineArgs);

} // namespace swift

Expand Down
14 changes: 13 additions & 1 deletion include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ def emit_module_semantic_info_path
: Separate<["-"], "emit-module-semantic-info-path">, MetaVarName<"<path>">,
HelpText<"Output semantic info of current module to <path>">;

def sil_output_path
: Separate<["-"], "sil-output-path">, MetaVarName<"<path>">,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are being modeled as additional supplementary outputs they also need a flag SupplementaryOutput:

def SupplementaryOutput : OptionFlag;

Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
SupplementaryOutput, CacheInvariant]>,
HelpText<"Output SIL to <path> as additional output during compilation">;

def ir_output_path
: Separate<["-"], "ir-output-path">, MetaVarName<"<path>">,
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
SupplementaryOutput, CacheInvariant]>,
HelpText<"Output LLVM IR to <path> as additional output during compilation">;

def diagnostic_documentation_path
: Separate<["-"], "diagnostic-documentation-path">, MetaVarName<"<path>">,
HelpText<"Path to diagnostic documentation resources">;
Expand Down Expand Up @@ -266,7 +278,7 @@ def serialize_dependency_scan_cache : Flag<["-"], "serialize-dependency-scan-cac

def reuse_dependency_scan_cache : Flag<["-"], "load-dependency-scan-cache">,
HelpText<"For performing a dependency scan, deserialize the scanner's internal state from a prior scan.">;

def validate_prior_dependency_scan_cache : Flag<["-"], "validate-prior-dependency-scan-cache">,
HelpText<"For performing a dependency scan with a prior scanner state, validate module dependencies.">;

Expand Down
5 changes: 3 additions & 2 deletions include/swift/Subsystems.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,10 @@ namespace swift {
GeneratedModule
performIRGeneration(ModuleDecl *M, const IRGenOptions &Opts,
const TBDGenOptions &TBDOpts,
std::unique_ptr<SILModule> SILMod,
StringRef ModuleName, const PrimarySpecificPaths &PSPs,
std::unique_ptr<SILModule> SILMod, StringRef ModuleName,
const PrimarySpecificPaths &PSPs,
ArrayRef<std::string> parallelOutputFilenames,
ArrayRef<std::string> parallelIROutputFilenames,
llvm::GlobalVariable **outModuleHash = nullptr);

/// Turn the given Swift file into LLVM IR and return the generated module.
Expand Down
12 changes: 12 additions & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,12 @@ void ToolChain::JobContext::addFrontendSupplementaryOutputArguments(
addOutputsOfType(arguments, Output, Args,
file_types::TY_SwiftModuleSummaryFile,
"-emit-module-summary-path");

// Add extra output paths for SIL and LLVM IR
addOutputsOfType(arguments, Output, Args, file_types::TY_SIL,
"-sil-output-path");
addOutputsOfType(arguments, Output, Args, file_types::TY_LLVM_IR,
"-ir-output-path");
}

ToolChain::InvocationInfo
Expand Down Expand Up @@ -1237,6 +1243,12 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
addOutputsOfType(Arguments, context.Output, context.Args, file_types::TY_TBD,
"-emit-tbd-path");

// Add extra output paths for SIL and LLVM IR
addOutputsOfType(Arguments, context.Output, context.Args, file_types::TY_SIL,
"-sil-output-path");
addOutputsOfType(Arguments, context.Output, context.Args,
file_types::TY_LLVM_IR, "-ir-output-path");

context.Args.AddLastArg(Arguments, options::OPT_emit_symbol_graph);
context.Args.AddLastArg(Arguments, options::OPT_emit_symbol_graph_dir);
context.Args.AddLastArg(Arguments, options::OPT_include_spi_symbols);
Expand Down
137 changes: 95 additions & 42 deletions lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,15 +275,15 @@ SupplementaryOutputPathsComputer::computeOutputPaths() const {

if (InputsAndOutputs.hasPrimaryInputs())
assert(OutputFiles.size() == pathsFromUser->size());
else if (InputsAndOutputs.isSingleThreadedWMO())
assert(OutputFiles.size() == pathsFromUser->size() &&
pathsFromUser->size() == 1);
else {
// Multi-threaded WMO is the exception
assert(OutputFiles.size() == InputsAndOutputs.inputCount() &&
pathsFromUser->size() == (InputsAndOutputs.hasInputs() ? 1 : 0));
if (!InputsAndOutputs.isSingleThreadedWMO()) {
assert(OutputFiles.size() == InputsAndOutputs.inputCount());
}
assert(pathsFromUser->size() == 1 ||
pathsFromUser->size() == InputsAndOutputs.inputCount());
}

// For other cases, process the paths normally
std::vector<SupplementaryOutputPaths> outputPaths;
unsigned i = 0;
bool hadError = InputsAndOutputs.forEachInputProducingSupplementaryOutput(
Expand Down Expand Up @@ -380,39 +380,78 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
options::OPT_emit_module_semantic_info_path);
auto optRecordOutput = getSupplementaryFilenamesFromArguments(
options::OPT_save_optimization_record_path);
auto silOutput =
getSupplementaryFilenamesFromArguments(options::OPT_sil_output_path);
auto irOutput =
getSupplementaryFilenamesFromArguments(options::OPT_ir_output_path);
if (!clangHeaderOutput || !moduleOutput || !moduleDocOutput ||
!dependenciesFile || !referenceDependenciesFile ||
!serializedDiagnostics || !loadedModuleTrace || !TBD ||
!moduleInterfaceOutput || !privateModuleInterfaceOutput || !packageModuleInterfaceOutput ||
!moduleSourceInfoOutput || !moduleSummaryOutput || !abiDescriptorOutput ||
!moduleSemanticInfoOutput || !optRecordOutput) {
!moduleInterfaceOutput || !privateModuleInterfaceOutput ||
!packageModuleInterfaceOutput || !moduleSourceInfoOutput ||
!moduleSummaryOutput || !abiDescriptorOutput ||
!moduleSemanticInfoOutput || !optRecordOutput || !silOutput ||
!irOutput) {
return std::nullopt;
}
std::vector<SupplementaryOutputPaths> result;

const unsigned N =
InputsAndOutputs.countOfFilesProducingSupplementaryOutput();
// In WMO mode with multiple IR output paths, we need to create one
// SupplementaryOutputPaths per input file, not just one for the module
unsigned N = InputsAndOutputs.countOfFilesProducingSupplementaryOutput();
if (!InputsAndOutputs.hasPrimaryInputs() && irOutput->size() > 1) {
// WMO mode with multiple IR outputs: use input count instead of 1
N = InputsAndOutputs.inputCount();
}

// Find the index of SIL output path matching module name
auto findSILIndexForModuleName = [&]() -> unsigned {
if (!InputsAndOutputs.hasPrimaryInputs() && silOutput->size() > 1) {
// In WMO mode with multiple SIL output paths, find the one whose matches
// module name
for (unsigned i = 0; i < silOutput->size(); ++i) {
StringRef silPath = (*silOutput)[i];
if (!silPath.empty()) {
StringRef basename = llvm::sys::path::stem(silPath);
if (basename == ModuleName) {
return i;
}
}
}
// If no match found, fall back to first
return 0;
}
return 0;
};

unsigned silOutputIndex = findSILIndexForModuleName();

for (unsigned i = 0; i < N; ++i) {
SupplementaryOutputPaths sop;
sop.ClangHeaderOutputPath = (*clangHeaderOutput)[i];
sop.ModuleOutputPath = (*moduleOutput)[i];
sop.ModuleDocOutputPath = (*moduleDocOutput)[i];
sop.DependenciesFilePath = (*dependenciesFile)[i];
sop.ReferenceDependenciesFilePath = (*referenceDependenciesFile)[i];
sop.SerializedDiagnosticsPath = (*serializedDiagnostics)[i];
sop.LoadedModuleTracePath = (*loadedModuleTrace)[i];
sop.TBDPath = (*TBD)[i];
sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[i];
sop.PrivateModuleInterfaceOutputPath = (*privateModuleInterfaceOutput)[i];
sop.PackageModuleInterfaceOutputPath = (*packageModuleInterfaceOutput)[i];
sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i];
sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[i];
sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[i];
sop.APIDescriptorOutputPath = (*apiDescriptorOutput)[i];
sop.ConstValuesOutputPath = (*constValuesOutput)[i];
sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[i];
sop.YAMLOptRecordPath = (*optRecordOutput)[i];
sop.BitstreamOptRecordPath = (*optRecordOutput)[i];
// In multi-threaded WMO with multiple IR outputs, most supplementary outputs
// are per-module (size 1), only IR is per-file. Use index 0 for module outputs.
unsigned moduleIndex = (!InputsAndOutputs.hasPrimaryInputs() && irOutput->size() > 1) ? 0 : i;
sop.ClangHeaderOutputPath = (*clangHeaderOutput)[moduleIndex];
sop.ModuleOutputPath = (*moduleOutput)[moduleIndex];
sop.ModuleDocOutputPath = (*moduleDocOutput)[moduleIndex];
sop.DependenciesFilePath = (*dependenciesFile)[moduleIndex];
sop.ReferenceDependenciesFilePath = (*referenceDependenciesFile)[moduleIndex];
sop.SerializedDiagnosticsPath = (*serializedDiagnostics)[moduleIndex];
sop.LoadedModuleTracePath = (*loadedModuleTrace)[moduleIndex];
sop.TBDPath = (*TBD)[moduleIndex];
sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[moduleIndex];
sop.PrivateModuleInterfaceOutputPath = (*privateModuleInterfaceOutput)[moduleIndex];
sop.PackageModuleInterfaceOutputPath = (*packageModuleInterfaceOutput)[moduleIndex];
sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[moduleIndex];
sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[moduleIndex];
sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[moduleIndex];
sop.APIDescriptorOutputPath = (*apiDescriptorOutput)[moduleIndex];
sop.ConstValuesOutputPath = (*constValuesOutput)[moduleIndex];
sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[moduleIndex];
sop.YAMLOptRecordPath = (*optRecordOutput)[moduleIndex];
sop.BitstreamOptRecordPath = (*optRecordOutput)[moduleIndex];
sop.SILOutputPath = (*silOutput)[silOutputIndex];
sop.LLVMIROutputPath = (*irOutput)[i];
result.push_back(sop);
}
return result;
Expand All @@ -439,6 +478,15 @@ SupplementaryOutputPathsComputer::getSupplementaryFilenamesFromArguments(
paths.emplace_back();
return paths;
}
// Special handling for SIL and IR output paths: allow multiple paths per file
// type
else if ((pathID == options::OPT_sil_output_path ||
pathID == options::OPT_ir_output_path) &&
paths.size() > N) {
// For parallel compilation, we can have multiple SIL/IR output paths
// so return all the paths.
return paths;
}

if (paths.empty())
return std::vector<std::string>(N, std::string());
Expand Down Expand Up @@ -613,6 +661,9 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
file_types::TY_BitstreamOptRecord, "",
defaultSupplementaryOutputPathExcludingExtension);

auto SILOutputPath = pathsFromArguments.SILOutputPath;
auto LLVMIROutputPath = pathsFromArguments.LLVMIROutputPath;

SupplementaryOutputPaths sop;
sop.ClangHeaderOutputPath = clangHeaderOutputPath;
sop.ModuleOutputPath = moduleOutputPath;
Expand All @@ -635,6 +686,8 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
sop.ModuleSemanticInfoOutputPath = ModuleSemanticInfoOutputPath;
sop.YAMLOptRecordPath = YAMLOptRecordPath;
sop.BitstreamOptRecordPath = bitstreamOptRecordPath;
sop.SILOutputPath = SILOutputPath;
sop.LLVMIROutputPath = LLVMIROutputPath;
return sop;
}

Expand Down Expand Up @@ -741,18 +794,18 @@ createFromTypeToPathMap(const TypeToPathMap *map) {

std::optional<std::vector<SupplementaryOutputPaths>>
SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap() const {
if (Arg *A = Args.getLastArg(options::OPT_emit_objc_header_path,
options::OPT_emit_module_path,
options::OPT_emit_module_doc_path,
options::OPT_emit_dependencies_path,
options::OPT_emit_reference_dependencies_path,
options::OPT_serialize_diagnostics_path,
options::OPT_emit_loaded_module_trace_path,
options::OPT_emit_module_interface_path,
options::OPT_emit_private_module_interface_path,
options::OPT_emit_package_module_interface_path,
options::OPT_emit_module_source_info_path,
options::OPT_emit_tbd_path)) {
if (Arg *A = Args.getLastArg(
options::OPT_emit_objc_header_path, options::OPT_emit_module_path,
options::OPT_emit_module_doc_path,
options::OPT_emit_dependencies_path,
options::OPT_emit_reference_dependencies_path,
options::OPT_serialize_diagnostics_path,
options::OPT_emit_loaded_module_trace_path,
options::OPT_emit_module_interface_path,
options::OPT_emit_private_module_interface_path,
options::OPT_emit_package_module_interface_path,
options::OPT_emit_module_source_info_path, options::OPT_emit_tbd_path,
options::OPT_sil_output_path, options::OPT_ir_output_path)) {
Diags.diagnose(SourceLoc(),
diag::error_cannot_have_supplementary_outputs,
A->getSpelling(), "-supplementary-output-file-map");
Expand Down
Loading