@@ -275,15 +275,15 @@ SupplementaryOutputPathsComputer::computeOutputPaths() const {
275
275
276
276
if (InputsAndOutputs.hasPrimaryInputs ())
277
277
assert (OutputFiles.size () == pathsFromUser->size ());
278
- else if (InputsAndOutputs.isSingleThreadedWMO ())
279
- assert (OutputFiles.size () == pathsFromUser->size () &&
280
- pathsFromUser->size () == 1 );
281
278
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 ());
285
284
}
286
285
286
+ // For other cases, process the paths normally
287
287
std::vector<SupplementaryOutputPaths> outputPaths;
288
288
unsigned i = 0 ;
289
289
bool hadError = InputsAndOutputs.forEachInputProducingSupplementaryOutput (
@@ -380,39 +380,78 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
380
380
options::OPT_emit_module_semantic_info_path);
381
381
auto optRecordOutput = getSupplementaryFilenamesFromArguments (
382
382
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);
383
387
if (!clangHeaderOutput || !moduleOutput || !moduleDocOutput ||
384
388
!dependenciesFile || !referenceDependenciesFile ||
385
389
!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) {
389
395
return std::nullopt ;
390
396
}
391
397
std::vector<SupplementaryOutputPaths> result;
392
398
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
+
395
429
for (unsigned i = 0 ; i < N; ++i) {
396
430
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];
416
455
result.push_back (sop);
417
456
}
418
457
return result;
@@ -439,6 +478,15 @@ SupplementaryOutputPathsComputer::getSupplementaryFilenamesFromArguments(
439
478
paths.emplace_back ();
440
479
return paths;
441
480
}
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
+ }
442
490
443
491
if (paths.empty ())
444
492
return std::vector<std::string>(N, std::string ());
@@ -613,6 +661,9 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
613
661
file_types::TY_BitstreamOptRecord, " " ,
614
662
defaultSupplementaryOutputPathExcludingExtension);
615
663
664
+ auto SILOutputPath = pathsFromArguments.SILOutputPath ;
665
+ auto LLVMIROutputPath = pathsFromArguments.LLVMIROutputPath ;
666
+
616
667
SupplementaryOutputPaths sop;
617
668
sop.ClangHeaderOutputPath = clangHeaderOutputPath;
618
669
sop.ModuleOutputPath = moduleOutputPath;
@@ -635,6 +686,8 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
635
686
sop.ModuleSemanticInfoOutputPath = ModuleSemanticInfoOutputPath;
636
687
sop.YAMLOptRecordPath = YAMLOptRecordPath;
637
688
sop.BitstreamOptRecordPath = bitstreamOptRecordPath;
689
+ sop.SILOutputPath = SILOutputPath;
690
+ sop.LLVMIROutputPath = LLVMIROutputPath;
638
691
return sop;
639
692
}
640
693
@@ -741,18 +794,18 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
741
794
742
795
std::optional<std::vector<SupplementaryOutputPaths>>
743
796
SupplementaryOutputPathsComputer::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 )) {
756
809
Diags.diagnose (SourceLoc (),
757
810
diag::error_cannot_have_supplementary_outputs,
758
811
A->getSpelling (), " -supplementary-output-file-map" );
0 commit comments