@@ -275,15 +275,15 @@ SupplementaryOutputPathsComputer::computeOutputPaths() const {
275275
276276 if (InputsAndOutputs.hasPrimaryInputs ())
277277 assert (OutputFiles.size () == pathsFromUser->size ());
278- else if (InputsAndOutputs.isSingleThreadedWMO ())
279- assert (OutputFiles.size () == pathsFromUser->size () &&
280- pathsFromUser->size () == 1 );
281278 else {
282- // Multi-threaded WMO is the exception
283- assert (OutputFiles.size () == InputsAndOutputs.inputCount () &&
284- pathsFromUser->size () == (InputsAndOutputs.hasInputs () ? 1 : 0 ));
279+ if (!InputsAndOutputs.isSingleThreadedWMO ()) {
280+ assert (OutputFiles.size () == InputsAndOutputs.inputCount ());
281+ }
282+ assert (pathsFromUser->size () == 1 ||
283+ pathsFromUser->size () == InputsAndOutputs.inputCount ());
285284 }
286285
286+ // For other cases, process the paths normally
287287 std::vector<SupplementaryOutputPaths> outputPaths;
288288 unsigned i = 0 ;
289289 bool hadError = InputsAndOutputs.forEachInputProducingSupplementaryOutput (
@@ -380,39 +380,78 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
380380 options::OPT_emit_module_semantic_info_path);
381381 auto optRecordOutput = getSupplementaryFilenamesFromArguments (
382382 options::OPT_save_optimization_record_path);
383+ auto silOutput =
384+ getSupplementaryFilenamesFromArguments (options::OPT_sil_output_path);
385+ auto irOutput =
386+ getSupplementaryFilenamesFromArguments (options::OPT_ir_output_path);
383387 if (!clangHeaderOutput || !moduleOutput || !moduleDocOutput ||
384388 !dependenciesFile || !referenceDependenciesFile ||
385389 !serializedDiagnostics || !loadedModuleTrace || !TBD ||
386- !moduleInterfaceOutput || !privateModuleInterfaceOutput || !packageModuleInterfaceOutput ||
387- !moduleSourceInfoOutput || !moduleSummaryOutput || !abiDescriptorOutput ||
388- !moduleSemanticInfoOutput || !optRecordOutput) {
390+ !moduleInterfaceOutput || !privateModuleInterfaceOutput ||
391+ !packageModuleInterfaceOutput || !moduleSourceInfoOutput ||
392+ !moduleSummaryOutput || !abiDescriptorOutput ||
393+ !moduleSemanticInfoOutput || !optRecordOutput || !silOutput ||
394+ !irOutput) {
389395 return std::nullopt ;
390396 }
391397 std::vector<SupplementaryOutputPaths> result;
392398
393- const unsigned N =
394- InputsAndOutputs.countOfFilesProducingSupplementaryOutput ();
399+ // In WMO mode with multiple IR output paths, we need to create one
400+ // SupplementaryOutputPaths per input file, not just one for the module
401+ unsigned N = InputsAndOutputs.countOfFilesProducingSupplementaryOutput ();
402+ if (!InputsAndOutputs.hasPrimaryInputs () && irOutput->size () > 1 ) {
403+ // WMO mode with multiple IR outputs: use input count instead of 1
404+ N = InputsAndOutputs.inputCount ();
405+ }
406+
407+ // Find the index of SIL output path matching module name
408+ auto findSILIndexForModuleName = [&]() -> unsigned {
409+ if (!InputsAndOutputs.hasPrimaryInputs () && silOutput->size () > 1 ) {
410+ // In WMO mode with multiple SIL output paths, find the one whose matches
411+ // module name
412+ for (unsigned i = 0 ; i < silOutput->size (); ++i) {
413+ StringRef silPath = (*silOutput)[i];
414+ if (!silPath.empty ()) {
415+ StringRef basename = llvm::sys::path::stem (silPath);
416+ if (basename == ModuleName) {
417+ return i;
418+ }
419+ }
420+ }
421+ // If no match found, fall back to first
422+ return 0 ;
423+ }
424+ return 0 ;
425+ };
426+
427+ unsigned silOutputIndex = findSILIndexForModuleName ();
428+
395429 for (unsigned i = 0 ; i < N; ++i) {
396430 SupplementaryOutputPaths sop;
397- sop.ClangHeaderOutputPath = (*clangHeaderOutput)[i];
398- sop.ModuleOutputPath = (*moduleOutput)[i];
399- sop.ModuleDocOutputPath = (*moduleDocOutput)[i];
400- sop.DependenciesFilePath = (*dependenciesFile)[i];
401- sop.ReferenceDependenciesFilePath = (*referenceDependenciesFile)[i];
402- sop.SerializedDiagnosticsPath = (*serializedDiagnostics)[i];
403- sop.LoadedModuleTracePath = (*loadedModuleTrace)[i];
404- sop.TBDPath = (*TBD)[i];
405- sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[i];
406- sop.PrivateModuleInterfaceOutputPath = (*privateModuleInterfaceOutput)[i];
407- sop.PackageModuleInterfaceOutputPath = (*packageModuleInterfaceOutput)[i];
408- sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i];
409- sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[i];
410- sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[i];
411- sop.APIDescriptorOutputPath = (*apiDescriptorOutput)[i];
412- sop.ConstValuesOutputPath = (*constValuesOutput)[i];
413- sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[i];
414- sop.YAMLOptRecordPath = (*optRecordOutput)[i];
415- sop.BitstreamOptRecordPath = (*optRecordOutput)[i];
431+ // In multi-threaded WMO with multiple IR outputs, most supplementary outputs
432+ // are per-module (size 1), only IR is per-file. Use index 0 for module outputs.
433+ unsigned moduleIndex = (!InputsAndOutputs.hasPrimaryInputs () && irOutput->size () > 1 ) ? 0 : i;
434+ sop.ClangHeaderOutputPath = (*clangHeaderOutput)[moduleIndex];
435+ sop.ModuleOutputPath = (*moduleOutput)[moduleIndex];
436+ sop.ModuleDocOutputPath = (*moduleDocOutput)[moduleIndex];
437+ sop.DependenciesFilePath = (*dependenciesFile)[moduleIndex];
438+ sop.ReferenceDependenciesFilePath = (*referenceDependenciesFile)[moduleIndex];
439+ sop.SerializedDiagnosticsPath = (*serializedDiagnostics)[moduleIndex];
440+ sop.LoadedModuleTracePath = (*loadedModuleTrace)[moduleIndex];
441+ sop.TBDPath = (*TBD)[moduleIndex];
442+ sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[moduleIndex];
443+ sop.PrivateModuleInterfaceOutputPath = (*privateModuleInterfaceOutput)[moduleIndex];
444+ sop.PackageModuleInterfaceOutputPath = (*packageModuleInterfaceOutput)[moduleIndex];
445+ sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[moduleIndex];
446+ sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[moduleIndex];
447+ sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[moduleIndex];
448+ sop.APIDescriptorOutputPath = (*apiDescriptorOutput)[moduleIndex];
449+ sop.ConstValuesOutputPath = (*constValuesOutput)[moduleIndex];
450+ sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[moduleIndex];
451+ sop.YAMLOptRecordPath = (*optRecordOutput)[moduleIndex];
452+ sop.BitstreamOptRecordPath = (*optRecordOutput)[moduleIndex];
453+ sop.SILOutputPath = (*silOutput)[silOutputIndex];
454+ sop.LLVMIROutputPath = (*irOutput)[i];
416455 result.push_back (sop);
417456 }
418457 return result;
@@ -439,6 +478,15 @@ SupplementaryOutputPathsComputer::getSupplementaryFilenamesFromArguments(
439478 paths.emplace_back ();
440479 return paths;
441480 }
481+ // Special handling for SIL and IR output paths: allow multiple paths per file
482+ // type
483+ else if ((pathID == options::OPT_sil_output_path ||
484+ pathID == options::OPT_ir_output_path) &&
485+ paths.size () > N) {
486+ // For parallel compilation, we can have multiple SIL/IR output paths
487+ // so return all the paths.
488+ return paths;
489+ }
442490
443491 if (paths.empty ())
444492 return std::vector<std::string>(N, std::string ());
@@ -613,6 +661,9 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
613661 file_types::TY_BitstreamOptRecord, " " ,
614662 defaultSupplementaryOutputPathExcludingExtension);
615663
664+ auto SILOutputPath = pathsFromArguments.SILOutputPath ;
665+ auto LLVMIROutputPath = pathsFromArguments.LLVMIROutputPath ;
666+
616667 SupplementaryOutputPaths sop;
617668 sop.ClangHeaderOutputPath = clangHeaderOutputPath;
618669 sop.ModuleOutputPath = moduleOutputPath;
@@ -635,6 +686,8 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
635686 sop.ModuleSemanticInfoOutputPath = ModuleSemanticInfoOutputPath;
636687 sop.YAMLOptRecordPath = YAMLOptRecordPath;
637688 sop.BitstreamOptRecordPath = bitstreamOptRecordPath;
689+ sop.SILOutputPath = SILOutputPath;
690+ sop.LLVMIROutputPath = LLVMIROutputPath;
638691 return sop;
639692}
640693
@@ -741,18 +794,18 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
741794
742795std::optional<std::vector<SupplementaryOutputPaths>>
743796SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap () const {
744- if (Arg *A = Args.getLastArg (options::OPT_emit_objc_header_path,
745- options::OPT_emit_module_path,
746- options::OPT_emit_module_doc_path,
747- options::OPT_emit_dependencies_path,
748- options::OPT_emit_reference_dependencies_path,
749- options::OPT_serialize_diagnostics_path,
750- options::OPT_emit_loaded_module_trace_path,
751- options::OPT_emit_module_interface_path,
752- options::OPT_emit_private_module_interface_path,
753- options::OPT_emit_package_module_interface_path,
754- options::OPT_emit_module_source_info_path,
755- options::OPT_emit_tbd_path )) {
797+ if (Arg *A = Args.getLastArg (
798+ options::OPT_emit_objc_header_path, options::OPT_emit_module_path,
799+ options::OPT_emit_module_doc_path,
800+ options::OPT_emit_dependencies_path,
801+ options::OPT_emit_reference_dependencies_path,
802+ options::OPT_serialize_diagnostics_path,
803+ options::OPT_emit_loaded_module_trace_path,
804+ options::OPT_emit_module_interface_path,
805+ options::OPT_emit_private_module_interface_path,
806+ options::OPT_emit_package_module_interface_path,
807+ options::OPT_emit_module_source_info_path, options::OPT_emit_tbd_path ,
808+ options::OPT_sil_output_path, options::OPT_ir_output_path )) {
756809 Diags.diagnose (SourceLoc (),
757810 diag::error_cannot_have_supplementary_outputs,
758811 A->getSpelling (), " -supplementary-output-file-map" );
0 commit comments