rustc_codegen_ssa/back/
write.rs

1use std::assert_matches::assert_matches;
2use std::marker::PhantomData;
3use std::panic::AssertUnwindSafe;
4use std::path::{Path, PathBuf};
5use std::sync::Arc;
6use std::sync::mpsc::{Receiver, Sender, channel};
7use std::{fs, io, mem, str, thread};
8
9use rustc_abi::Size;
10use rustc_ast::attr;
11use rustc_data_structures::fx::FxIndexMap;
12use rustc_data_structures::jobserver::{self, Acquired};
13use rustc_data_structures::memmap::Mmap;
14use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
15use rustc_errors::emitter::Emitter;
16use rustc_errors::translation::Translator;
17use rustc_errors::{
18    Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalErrorMarker, Level, MultiSpan, Style,
19    Suggestions,
20};
21use rustc_fs_util::link_or_copy;
22use rustc_incremental::{
23    copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
24};
25use rustc_metadata::fs::copy_to_stdout;
26use rustc_middle::bug;
27use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
28use rustc_middle::ty::TyCtxt;
29use rustc_session::Session;
30use rustc_session::config::{
31    self, CrateType, Lto, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath,
32};
33use rustc_span::source_map::SourceMap;
34use rustc_span::{FileName, InnerSpan, Span, SpanData, sym};
35use rustc_target::spec::{MergeFunctions, SanitizerSet};
36use tracing::debug;
37
38use super::link::{self, ensure_removed};
39use super::lto::{self, SerializedModule};
40use crate::back::lto::check_lto_allowed;
41use crate::errors::ErrorCreatingRemarkDir;
42use crate::traits::*;
43use crate::{
44    CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
45    errors,
46};
47
48const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
49
50/// What kind of object file to emit.
51#[derive(Clone, Copy, PartialEq)]
52pub enum EmitObj {
53    // No object file.
54    None,
55
56    // Just uncompressed llvm bitcode. Provides easy compatibility with
57    // emscripten's ecc compiler, when used as the linker.
58    Bitcode,
59
60    // Object code, possibly augmented with a bitcode section.
61    ObjectCode(BitcodeSection),
62}
63
64/// What kind of llvm bitcode section to embed in an object file.
65#[derive(Clone, Copy, PartialEq)]
66pub enum BitcodeSection {
67    // No bitcode section.
68    None,
69
70    // A full, uncompressed bitcode section.
71    Full,
72}
73
74/// Module-specific configuration for `optimize_and_codegen`.
75pub struct ModuleConfig {
76    /// Names of additional optimization passes to run.
77    pub passes: Vec<String>,
78    /// Some(level) to optimize at a certain level, or None to run
79    /// absolutely no optimizations (used for the allocator module).
80    pub opt_level: Option<config::OptLevel>,
81
82    pub pgo_gen: SwitchWithOptPath,
83    pub pgo_use: Option<PathBuf>,
84    pub pgo_sample_use: Option<PathBuf>,
85    pub debug_info_for_profiling: bool,
86    pub instrument_coverage: bool,
87
88    pub sanitizer: SanitizerSet,
89    pub sanitizer_recover: SanitizerSet,
90    pub sanitizer_dataflow_abilist: Vec<String>,
91    pub sanitizer_memory_track_origins: usize,
92
93    // Flags indicating which outputs to produce.
94    pub emit_pre_lto_bc: bool,
95    pub emit_no_opt_bc: bool,
96    pub emit_bc: bool,
97    pub emit_ir: bool,
98    pub emit_asm: bool,
99    pub emit_obj: EmitObj,
100    pub emit_thin_lto: bool,
101    pub emit_thin_lto_summary: bool,
102
103    // Miscellaneous flags. These are mostly copied from command-line
104    // options.
105    pub verify_llvm_ir: bool,
106    pub lint_llvm_ir: bool,
107    pub no_prepopulate_passes: bool,
108    pub no_builtins: bool,
109    pub vectorize_loop: bool,
110    pub vectorize_slp: bool,
111    pub merge_functions: bool,
112    pub emit_lifetime_markers: bool,
113    pub llvm_plugins: Vec<String>,
114    pub autodiff: Vec<config::AutoDiff>,
115    pub offload: Vec<config::Offload>,
116}
117
118impl ModuleConfig {
119    fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
120        // If it's a regular module, use `$regular`, otherwise use `$other`.
121        // `$regular` and `$other` are evaluated lazily.
122        macro_rules! if_regular {
123            ($regular: expr, $other: expr) => {
124                if let ModuleKind::Regular = kind { $regular } else { $other }
125            };
126        }
127
128        let sess = tcx.sess;
129        let opt_level_and_size = if_regular!(Some(sess.opts.optimize), None);
130
131        let save_temps = sess.opts.cg.save_temps;
132
133        let should_emit_obj = sess.opts.output_types.contains_key(&OutputType::Exe)
134            || match kind {
135                ModuleKind::Regular => sess.opts.output_types.contains_key(&OutputType::Object),
136                ModuleKind::Allocator => false,
137            };
138
139        let emit_obj = if !should_emit_obj {
140            EmitObj::None
141        } else if sess.target.obj_is_bitcode
142            || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
143        {
144            // This case is selected if the target uses objects as bitcode, or
145            // if linker plugin LTO is enabled. In the linker plugin LTO case
146            // the assumption is that the final link-step will read the bitcode
147            // and convert it to object code. This may be done by either the
148            // native linker or rustc itself.
149            //
150            // Note, however, that the linker-plugin-lto requested here is
151            // explicitly ignored for `#![no_builtins]` crates. These crates are
152            // specifically ignored by rustc's LTO passes and wouldn't work if
153            // loaded into the linker. These crates define symbols that LLVM
154            // lowers intrinsics to, and these symbol dependencies aren't known
155            // until after codegen. As a result any crate marked
156            // `#![no_builtins]` is assumed to not participate in LTO and
157            // instead goes on to generate object code.
158            EmitObj::Bitcode
159        } else if need_bitcode_in_object(tcx) {
160            EmitObj::ObjectCode(BitcodeSection::Full)
161        } else {
162            EmitObj::ObjectCode(BitcodeSection::None)
163        };
164
165        ModuleConfig {
166            passes: if_regular!(sess.opts.cg.passes.clone(), vec![]),
167
168            opt_level: opt_level_and_size,
169
170            pgo_gen: if_regular!(
171                sess.opts.cg.profile_generate.clone(),
172                SwitchWithOptPath::Disabled
173            ),
174            pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None),
175            pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None),
176            debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling,
177            instrument_coverage: if_regular!(sess.instrument_coverage(), false),
178
179            sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()),
180            sanitizer_dataflow_abilist: if_regular!(
181                sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(),
182                Vec::new()
183            ),
184            sanitizer_recover: if_regular!(
185                sess.opts.unstable_opts.sanitizer_recover,
186                SanitizerSet::empty()
187            ),
188            sanitizer_memory_track_origins: if_regular!(
189                sess.opts.unstable_opts.sanitizer_memory_track_origins,
190                0
191            ),
192
193            emit_pre_lto_bc: if_regular!(
194                save_temps || need_pre_lto_bitcode_for_incr_comp(sess),
195                false
196            ),
197            emit_no_opt_bc: if_regular!(save_temps, false),
198            emit_bc: if_regular!(
199                save_temps || sess.opts.output_types.contains_key(&OutputType::Bitcode),
200                save_temps
201            ),
202            emit_ir: if_regular!(
203                sess.opts.output_types.contains_key(&OutputType::LlvmAssembly),
204                false
205            ),
206            emit_asm: if_regular!(
207                sess.opts.output_types.contains_key(&OutputType::Assembly),
208                false
209            ),
210            emit_obj,
211            // thin lto summaries prevent fat lto, so do not emit them if fat
212            // lto is requested. See PR #136840 for background information.
213            emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto && sess.lto() != Lto::Fat,
214            emit_thin_lto_summary: if_regular!(
215                sess.opts.output_types.contains_key(&OutputType::ThinLinkBitcode),
216                false
217            ),
218
219            verify_llvm_ir: sess.verify_llvm_ir(),
220            lint_llvm_ir: sess.opts.unstable_opts.lint_llvm_ir,
221            no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes,
222            no_builtins: no_builtins || sess.target.no_builtins,
223
224            // Copy what clang does by turning on loop vectorization at O2 and
225            // slp vectorization at O3.
226            vectorize_loop: !sess.opts.cg.no_vectorize_loops
227                && (sess.opts.optimize == config::OptLevel::More
228                    || sess.opts.optimize == config::OptLevel::Aggressive),
229            vectorize_slp: !sess.opts.cg.no_vectorize_slp
230                && sess.opts.optimize == config::OptLevel::Aggressive,
231
232            // Some targets (namely, NVPTX) interact badly with the
233            // MergeFunctions pass. This is because MergeFunctions can generate
234            // new function calls which may interfere with the target calling
235            // convention; e.g. for the NVPTX target, PTX kernels should not
236            // call other PTX kernels. MergeFunctions can also be configured to
237            // generate aliases instead, but aliases are not supported by some
238            // backends (again, NVPTX). Therefore, allow targets to opt out of
239            // the MergeFunctions pass, but otherwise keep the pass enabled (at
240            // O2 and O3) since it can be useful for reducing code size.
241            merge_functions: match sess
242                .opts
243                .unstable_opts
244                .merge_functions
245                .unwrap_or(sess.target.merge_functions)
246            {
247                MergeFunctions::Disabled => false,
248                MergeFunctions::Trampolines | MergeFunctions::Aliases => {
249                    use config::OptLevel::*;
250                    match sess.opts.optimize {
251                        Aggressive | More | SizeMin | Size => true,
252                        Less | No => false,
253                    }
254                }
255            },
256
257            emit_lifetime_markers: sess.emit_lifetime_markers(),
258            llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
259            autodiff: if_regular!(sess.opts.unstable_opts.autodiff.clone(), vec![]),
260            offload: if_regular!(sess.opts.unstable_opts.offload.clone(), vec![]),
261        }
262    }
263
264    pub fn bitcode_needed(&self) -> bool {
265        self.emit_bc
266            || self.emit_thin_lto_summary
267            || self.emit_obj == EmitObj::Bitcode
268            || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
269    }
270
271    pub fn embed_bitcode(&self) -> bool {
272        self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
273    }
274}
275
276/// Configuration passed to the function returned by the `target_machine_factory`.
277pub struct TargetMachineFactoryConfig {
278    /// Split DWARF is enabled in LLVM by checking that `TM.MCOptions.SplitDwarfFile` isn't empty,
279    /// so the path to the dwarf object has to be provided when we create the target machine.
280    /// This can be ignored by backends which do not need it for their Split DWARF support.
281    pub split_dwarf_file: Option<PathBuf>,
282
283    /// The name of the output object file. Used for setting OutputFilenames in target options
284    /// so that LLVM can emit the CodeView S_OBJNAME record in pdb files
285    pub output_obj_file: Option<PathBuf>,
286}
287
288impl TargetMachineFactoryConfig {
289    pub fn new(
290        cgcx: &CodegenContext<impl WriteBackendMethods>,
291        module_name: &str,
292    ) -> TargetMachineFactoryConfig {
293        let split_dwarf_file = if cgcx.target_can_use_split_dwarf {
294            cgcx.output_filenames.split_dwarf_path(
295                cgcx.split_debuginfo,
296                cgcx.split_dwarf_kind,
297                module_name,
298                cgcx.invocation_temp.as_deref(),
299            )
300        } else {
301            None
302        };
303
304        let output_obj_file = Some(cgcx.output_filenames.temp_path_for_cgu(
305            OutputType::Object,
306            module_name,
307            cgcx.invocation_temp.as_deref(),
308        ));
309        TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
310    }
311}
312
313pub type TargetMachineFactoryFn<B> = Arc<
314    dyn Fn(
315            TargetMachineFactoryConfig,
316        ) -> Result<
317            <B as WriteBackendMethods>::TargetMachine,
318            <B as WriteBackendMethods>::TargetMachineError,
319        > + Send
320        + Sync,
321>;
322
323/// Additional resources used by optimize_and_codegen (not module specific)
324#[derive(Clone)]
325pub struct CodegenContext<B: WriteBackendMethods> {
326    // Resources needed when running LTO
327    pub prof: SelfProfilerRef,
328    pub lto: Lto,
329    pub save_temps: bool,
330    pub fewer_names: bool,
331    pub time_trace: bool,
332    pub opts: Arc<config::Options>,
333    pub crate_types: Vec<CrateType>,
334    pub output_filenames: Arc<OutputFilenames>,
335    pub invocation_temp: Option<String>,
336    pub module_config: Arc<ModuleConfig>,
337    pub tm_factory: TargetMachineFactoryFn<B>,
338    pub msvc_imps_needed: bool,
339    pub is_pe_coff: bool,
340    pub target_can_use_split_dwarf: bool,
341    pub target_arch: String,
342    pub target_is_like_darwin: bool,
343    pub target_is_like_aix: bool,
344    pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
345    pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
346    pub pointer_size: Size,
347
348    /// All commandline args used to invoke the compiler, with @file args fully expanded.
349    /// This will only be used within debug info, e.g. in the pdb file on windows
350    /// This is mainly useful for other tools that reads that debuginfo to figure out
351    /// how to call the compiler with the same arguments.
352    pub expanded_args: Vec<String>,
353
354    /// Emitter to use for diagnostics produced during codegen.
355    pub diag_emitter: SharedEmitter,
356    /// LLVM optimizations for which we want to print remarks.
357    pub remark: Passes,
358    /// Directory into which should the LLVM optimization remarks be written.
359    /// If `None`, they will be written to stderr.
360    pub remark_dir: Option<PathBuf>,
361    /// The incremental compilation session directory, or None if we are not
362    /// compiling incrementally
363    pub incr_comp_session_dir: Option<PathBuf>,
364    /// `true` if the codegen should be run in parallel.
365    ///
366    /// Depends on [`ExtraBackendMethods::supports_parallel()`] and `-Zno_parallel_backend`.
367    pub parallel: bool,
368}
369
370impl<B: WriteBackendMethods> CodegenContext<B> {
371    pub fn create_dcx(&self) -> DiagCtxt {
372        DiagCtxt::new(Box::new(self.diag_emitter.clone()))
373    }
374}
375
376fn generate_thin_lto_work<B: ExtraBackendMethods>(
377    cgcx: &CodegenContext<B>,
378    exported_symbols_for_lto: &[String],
379    each_linked_rlib_for_lto: &[PathBuf],
380    needs_thin_lto: Vec<(String, B::ThinBuffer)>,
381    import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
382) -> Vec<(WorkItem<B>, u64)> {
383    let _prof_timer = cgcx.prof.generic_activity("codegen_thin_generate_lto_work");
384
385    let (lto_modules, copy_jobs) = B::run_thin_lto(
386        cgcx,
387        exported_symbols_for_lto,
388        each_linked_rlib_for_lto,
389        needs_thin_lto,
390        import_only_modules,
391    );
392    lto_modules
393        .into_iter()
394        .map(|module| {
395            let cost = module.cost();
396            (WorkItem::ThinLto(module), cost)
397        })
398        .chain(copy_jobs.into_iter().map(|wp| {
399            (
400                WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
401                    name: wp.cgu_name.clone(),
402                    source: wp,
403                }),
404                0, // copying is very cheap
405            )
406        }))
407        .collect()
408}
409
410struct CompiledModules {
411    modules: Vec<CompiledModule>,
412    allocator_module: Option<CompiledModule>,
413}
414
415fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool {
416    let sess = tcx.sess;
417    sess.opts.cg.embed_bitcode
418        && tcx.crate_types().contains(&CrateType::Rlib)
419        && sess.opts.output_types.contains_key(&OutputType::Exe)
420}
421
422fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
423    if sess.opts.incremental.is_none() {
424        return false;
425    }
426
427    match sess.lto() {
428        Lto::No => false,
429        Lto::Fat | Lto::Thin | Lto::ThinLocal => true,
430    }
431}
432
433pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
434    backend: B,
435    tcx: TyCtxt<'_>,
436    target_cpu: String,
437    allocator_module: Option<ModuleCodegen<B::Module>>,
438) -> OngoingCodegen<B> {
439    let (coordinator_send, coordinator_receive) = channel();
440
441    let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
442    let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
443
444    let crate_info = CrateInfo::new(tcx, target_cpu);
445
446    let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
447    let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);
448
449    let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
450    let (codegen_worker_send, codegen_worker_receive) = channel();
451
452    let coordinator_thread = start_executing_work(
453        backend.clone(),
454        tcx,
455        &crate_info,
456        shared_emitter,
457        codegen_worker_send,
458        coordinator_receive,
459        Arc::new(regular_config),
460        Arc::new(allocator_config),
461        allocator_module,
462        coordinator_send.clone(),
463    );
464
465    OngoingCodegen {
466        backend,
467        crate_info,
468
469        codegen_worker_receive,
470        shared_emitter_main,
471        coordinator: Coordinator {
472            sender: coordinator_send,
473            future: Some(coordinator_thread),
474            phantom: PhantomData,
475        },
476        output_filenames: Arc::clone(tcx.output_filenames(())),
477    }
478}
479
480fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
481    sess: &Session,
482    compiled_modules: &CompiledModules,
483) -> FxIndexMap<WorkProductId, WorkProduct> {
484    let mut work_products = FxIndexMap::default();
485
486    if sess.opts.incremental.is_none() {
487        return work_products;
488    }
489
490    let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
491
492    for module in &compiled_modules.modules {
493        let mut files = Vec::new();
494        if let Some(object_file_path) = &module.object {
495            files.push((OutputType::Object.extension(), object_file_path.as_path()));
496        }
497        if let Some(dwarf_object_file_path) = &module.dwarf_object {
498            files.push(("dwo", dwarf_object_file_path.as_path()));
499        }
500        if let Some(path) = &module.assembly {
501            files.push((OutputType::Assembly.extension(), path.as_path()));
502        }
503        if let Some(path) = &module.llvm_ir {
504            files.push((OutputType::LlvmAssembly.extension(), path.as_path()));
505        }
506        if let Some(path) = &module.bytecode {
507            files.push((OutputType::Bitcode.extension(), path.as_path()));
508        }
509        if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir(
510            sess,
511            &module.name,
512            files.as_slice(),
513            &module.links_from_incr_cache,
514        ) {
515            work_products.insert(id, product);
516        }
517    }
518
519    work_products
520}
521
522fn produce_final_output_artifacts(
523    sess: &Session,
524    compiled_modules: &CompiledModules,
525    crate_output: &OutputFilenames,
526) {
527    let mut user_wants_bitcode = false;
528    let mut user_wants_objects = false;
529
530    // Produce final compile outputs.
531    let copy_gracefully = |from: &Path, to: &OutFileName| match to {
532        OutFileName::Stdout if let Err(e) = copy_to_stdout(from) => {
533            sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e));
534        }
535        OutFileName::Real(path) if let Err(e) = fs::copy(from, path) => {
536            sess.dcx().emit_err(errors::CopyPath::new(from, path, e));
537        }
538        _ => {}
539    };
540
541    let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| {
542        if let [module] = &compiled_modules.modules[..] {
543            // 1) Only one codegen unit. In this case it's no difficulty
544            //    to copy `foo.0.x` to `foo.x`.
545            let path = crate_output.temp_path_for_cgu(
546                output_type,
547                &module.name,
548                sess.invocation_temp.as_deref(),
549            );
550            let output = crate_output.path(output_type);
551            if !output_type.is_text_output() && output.is_tty() {
552                sess.dcx()
553                    .emit_err(errors::BinaryOutputToTty { shorthand: output_type.shorthand() });
554            } else {
555                copy_gracefully(&path, &output);
556            }
557            if !sess.opts.cg.save_temps && !keep_numbered {
558                // The user just wants `foo.x`, not `foo.#module-name#.x`.
559                ensure_removed(sess.dcx(), &path);
560            }
561        } else {
562            if crate_output.outputs.contains_explicit_name(&output_type) {
563                // 2) Multiple codegen units, with `--emit foo=some_name`. We have
564                //    no good solution for this case, so warn the user.
565                sess.dcx()
566                    .emit_warn(errors::IgnoringEmitPath { extension: output_type.extension() });
567            } else if crate_output.single_output_file.is_some() {
568                // 3) Multiple codegen units, with `-o some_name`. We have
569                //    no good solution for this case, so warn the user.
570                sess.dcx().emit_warn(errors::IgnoringOutput { extension: output_type.extension() });
571            } else {
572                // 4) Multiple codegen units, but no explicit name. We
573                //    just leave the `foo.0.x` files in place.
574                // (We don't have to do any work in this case.)
575            }
576        }
577    };
578
579    // Flag to indicate whether the user explicitly requested bitcode.
580    // Otherwise, we produced it only as a temporary output, and will need
581    // to get rid of it.
582    for output_type in crate_output.outputs.keys() {
583        match *output_type {
584            OutputType::Bitcode => {
585                user_wants_bitcode = true;
586                // Copy to .bc, but always keep the .0.bc. There is a later
587                // check to figure out if we should delete .0.bc files, or keep
588                // them for making an rlib.
589                copy_if_one_unit(OutputType::Bitcode, true);
590            }
591            OutputType::ThinLinkBitcode => {
592                copy_if_one_unit(OutputType::ThinLinkBitcode, false);
593            }
594            OutputType::LlvmAssembly => {
595                copy_if_one_unit(OutputType::LlvmAssembly, false);
596            }
597            OutputType::Assembly => {
598                copy_if_one_unit(OutputType::Assembly, false);
599            }
600            OutputType::Object => {
601                user_wants_objects = true;
602                copy_if_one_unit(OutputType::Object, true);
603            }
604            OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {}
605        }
606    }
607
608    // Clean up unwanted temporary files.
609
610    // We create the following files by default:
611    //  - #crate#.#module-name#.bc
612    //  - #crate#.#module-name#.o
613    //  - #crate#.crate.metadata.bc
614    //  - #crate#.crate.metadata.o
615    //  - #crate#.o (linked from crate.##.o)
616    //  - #crate#.bc (copied from crate.##.bc)
617    // We may create additional files if requested by the user (through
618    // `-C save-temps` or `--emit=` flags).
619
620    if !sess.opts.cg.save_temps {
621        // Remove the temporary .#module-name#.o objects. If the user didn't
622        // explicitly request bitcode (with --emit=bc), and the bitcode is not
623        // needed for building an rlib, then we must remove .#module-name#.bc as
624        // well.
625
626        // Specific rules for keeping .#module-name#.bc:
627        //  - If the user requested bitcode (`user_wants_bitcode`), and
628        //    codegen_units > 1, then keep it.
629        //  - If the user requested bitcode but codegen_units == 1, then we
630        //    can toss .#module-name#.bc because we copied it to .bc earlier.
631        //  - If we're not building an rlib and the user didn't request
632        //    bitcode, then delete .#module-name#.bc.
633        // If you change how this works, also update back::link::link_rlib,
634        // where .#module-name#.bc files are (maybe) deleted after making an
635        // rlib.
636        let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);
637
638        let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units().as_usize() > 1;
639
640        let keep_numbered_objects =
641            needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1);
642
643        for module in compiled_modules.modules.iter() {
644            if !keep_numbered_objects {
645                if let Some(ref path) = module.object {
646                    ensure_removed(sess.dcx(), path);
647                }
648
649                if let Some(ref path) = module.dwarf_object {
650                    ensure_removed(sess.dcx(), path);
651                }
652            }
653
654            if let Some(ref path) = module.bytecode {
655                if !keep_numbered_bitcode {
656                    ensure_removed(sess.dcx(), path);
657                }
658            }
659        }
660
661        if !user_wants_bitcode
662            && let Some(ref allocator_module) = compiled_modules.allocator_module
663            && let Some(ref path) = allocator_module.bytecode
664        {
665            ensure_removed(sess.dcx(), path);
666        }
667    }
668
669    if sess.opts.json_artifact_notifications {
670        if let [module] = &compiled_modules.modules[..] {
671            module.for_each_output(|_path, ty| {
672                if sess.opts.output_types.contains_key(&ty) {
673                    let descr = ty.shorthand();
674                    // for single cgu file is renamed to drop cgu specific suffix
675                    // so we regenerate it the same way
676                    let path = crate_output.path(ty);
677                    sess.dcx().emit_artifact_notification(path.as_path(), descr);
678                }
679            });
680        } else {
681            for module in &compiled_modules.modules {
682                module.for_each_output(|path, ty| {
683                    if sess.opts.output_types.contains_key(&ty) {
684                        let descr = ty.shorthand();
685                        sess.dcx().emit_artifact_notification(&path, descr);
686                    }
687                });
688            }
689        }
690    }
691
692    // We leave the following files around by default:
693    //  - #crate#.o
694    //  - #crate#.crate.metadata.o
695    //  - #crate#.bc
696    // These are used in linking steps and will be cleaned up afterward.
697}
698
699pub(crate) enum WorkItem<B: WriteBackendMethods> {
700    /// Optimize a newly codegened, totally unoptimized module.
701    Optimize(ModuleCodegen<B::Module>),
702    /// Copy the post-LTO artifacts from the incremental cache to the output
703    /// directory.
704    CopyPostLtoArtifacts(CachedModuleCodegen),
705    /// Performs fat LTO on the given module.
706    FatLto {
707        exported_symbols_for_lto: Arc<Vec<String>>,
708        each_linked_rlib_for_lto: Vec<PathBuf>,
709        needs_fat_lto: Vec<FatLtoInput<B>>,
710        import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
711    },
712    /// Performs thin-LTO on the given module.
713    ThinLto(lto::ThinModule<B>),
714}
715
716impl<B: WriteBackendMethods> WorkItem<B> {
717    /// Generate a short description of this work item suitable for use as a thread name.
718    fn short_description(&self) -> String {
719        // `pthread_setname()` on *nix ignores anything beyond the first 15
720        // bytes. Use short descriptions to maximize the space available for
721        // the module name.
722        #[cfg(not(windows))]
723        fn desc(short: &str, _long: &str, name: &str) -> String {
724            // The short label is three bytes, and is followed by a space. That
725            // leaves 11 bytes for the CGU name. How we obtain those 11 bytes
726            // depends on the CGU name form.
727            //
728            // - Non-incremental, e.g. `regex.f10ba03eb5ec7975-cgu.0`: the part
729            //   before the `-cgu.0` is the same for every CGU, so use the
730            //   `cgu.0` part. The number suffix will be different for each
731            //   CGU.
732            //
733            // - Incremental (normal), e.g. `2i52vvl2hco29us0`: use the whole
734            //   name because each CGU will have a unique ASCII hash, and the
735            //   first 11 bytes will be enough to identify it.
736            //
737            // - Incremental (with `-Zhuman-readable-cgu-names`), e.g.
738            //   `regex.f10ba03eb5ec7975-re_builder.volatile`: use the whole
739            //   name. The first 11 bytes won't be enough to uniquely identify
740            //   it, but no obvious substring will, and this is a rarely used
741            //   option so it doesn't matter much.
742            //
743            assert_eq!(short.len(), 3);
744            let name = if let Some(index) = name.find("-cgu.") {
745                &name[index + 1..] // +1 skips the leading '-'.
746            } else {
747                name
748            };
749            format!("{short} {name}")
750        }
751
752        // Windows has no thread name length limit, so use more descriptive names.
753        #[cfg(windows)]
754        fn desc(_short: &str, long: &str, name: &str) -> String {
755            format!("{long} {name}")
756        }
757
758        match self {
759            WorkItem::Optimize(m) => desc("opt", "optimize module", &m.name),
760            WorkItem::CopyPostLtoArtifacts(m) => desc("cpy", "copy LTO artifacts for", &m.name),
761            WorkItem::FatLto { .. } => desc("lto", "fat LTO module", "everything"),
762            WorkItem::ThinLto(m) => desc("lto", "thin-LTO module", m.name()),
763        }
764    }
765}
766
767/// A result produced by the backend.
768pub(crate) enum WorkItemResult<B: WriteBackendMethods> {
769    /// The backend has finished compiling a CGU, nothing more required.
770    Finished(CompiledModule),
771
772    /// The backend has finished compiling a CGU, which now needs to go through
773    /// fat LTO.
774    NeedsFatLto(FatLtoInput<B>),
775
776    /// The backend has finished compiling a CGU, which now needs to go through
777    /// thin LTO.
778    NeedsThinLto(String, B::ThinBuffer),
779}
780
781pub enum FatLtoInput<B: WriteBackendMethods> {
782    Serialized { name: String, buffer: SerializedModule<B::ModuleBuffer> },
783    InMemory(ModuleCodegen<B::Module>),
784}
785
786/// Actual LTO type we end up choosing based on multiple factors.
787pub(crate) enum ComputedLtoType {
788    No,
789    Thin,
790    Fat,
791}
792
793pub(crate) fn compute_per_cgu_lto_type(
794    sess_lto: &Lto,
795    opts: &config::Options,
796    sess_crate_types: &[CrateType],
797) -> ComputedLtoType {
798    // If the linker does LTO, we don't have to do it. Note that we
799    // keep doing full LTO, if it is requested, as not to break the
800    // assumption that the output will be a single module.
801    let linker_does_lto = opts.cg.linker_plugin_lto.enabled();
802
803    // We ignore a request for full crate graph LTO if the crate type
804    // is only an rlib, as there is no full crate graph to process,
805    // that'll happen later.
806    //
807    // This use case currently comes up primarily for targets that
808    // require LTO so the request for LTO is always unconditionally
809    // passed down to the backend, but we don't actually want to do
810    // anything about it yet until we've got a final product.
811    let is_rlib = matches!(sess_crate_types, [CrateType::Rlib]);
812
813    match sess_lto {
814        Lto::ThinLocal if !linker_does_lto => ComputedLtoType::Thin,
815        Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin,
816        Lto::Fat if !is_rlib => ComputedLtoType::Fat,
817        _ => ComputedLtoType::No,
818    }
819}
820
821fn execute_optimize_work_item<B: ExtraBackendMethods>(
822    cgcx: &CodegenContext<B>,
823    mut module: ModuleCodegen<B::Module>,
824) -> WorkItemResult<B> {
825    let dcx = cgcx.create_dcx();
826    let dcx = dcx.handle();
827
828    B::optimize(cgcx, dcx, &mut module, &cgcx.module_config);
829
830    // After we've done the initial round of optimizations we need to
831    // decide whether to synchronously codegen this module or ship it
832    // back to the coordinator thread for further LTO processing (which
833    // has to wait for all the initial modules to be optimized).
834
835    let lto_type = compute_per_cgu_lto_type(&cgcx.lto, &cgcx.opts, &cgcx.crate_types);
836
837    // If we're doing some form of incremental LTO then we need to be sure to
838    // save our module to disk first.
839    let bitcode = if cgcx.module_config.emit_pre_lto_bc {
840        let filename = pre_lto_bitcode_filename(&module.name);
841        cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename))
842    } else {
843        None
844    };
845
846    match lto_type {
847        ComputedLtoType::No => {
848            let module = B::codegen(cgcx, module, &cgcx.module_config);
849            WorkItemResult::Finished(module)
850        }
851        ComputedLtoType::Thin => {
852            let (name, thin_buffer) = B::prepare_thin(module, false);
853            if let Some(path) = bitcode {
854                fs::write(&path, thin_buffer.data()).unwrap_or_else(|e| {
855                    panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
856                });
857            }
858            WorkItemResult::NeedsThinLto(name, thin_buffer)
859        }
860        ComputedLtoType::Fat => match bitcode {
861            Some(path) => {
862                let (name, buffer) = B::serialize_module(module);
863                fs::write(&path, buffer.data()).unwrap_or_else(|e| {
864                    panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
865                });
866                WorkItemResult::NeedsFatLto(FatLtoInput::Serialized {
867                    name,
868                    buffer: SerializedModule::Local(buffer),
869                })
870            }
871            None => WorkItemResult::NeedsFatLto(FatLtoInput::InMemory(module)),
872        },
873    }
874}
875
876fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
877    cgcx: &CodegenContext<B>,
878    module: CachedModuleCodegen,
879) -> WorkItemResult<B> {
880    let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
881
882    let mut links_from_incr_cache = Vec::new();
883
884    let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
885        let source_file = in_incr_comp_dir(incr_comp_session_dir, saved_path);
886        debug!(
887            "copying preexisting module `{}` from {:?} to {}",
888            module.name,
889            source_file,
890            output_path.display()
891        );
892        match link_or_copy(&source_file, &output_path) {
893            Ok(_) => {
894                links_from_incr_cache.push(source_file);
895                Some(output_path)
896            }
897            Err(error) => {
898                cgcx.create_dcx().handle().emit_err(errors::CopyPathBuf {
899                    source_file,
900                    output_path,
901                    error,
902                });
903                None
904            }
905        }
906    };
907
908    let dwarf_object =
909        module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
910            let dwarf_obj_out = cgcx
911                .output_filenames
912                .split_dwarf_path(
913                    cgcx.split_debuginfo,
914                    cgcx.split_dwarf_kind,
915                    &module.name,
916                    cgcx.invocation_temp.as_deref(),
917                )
918                .expect(
919                    "saved dwarf object in work product but `split_dwarf_path` returned `None`",
920                );
921            load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file)
922        });
923
924    let mut load_from_incr_cache = |perform, output_type: OutputType| {
925        if perform {
926            let saved_file = module.source.saved_files.get(output_type.extension())?;
927            let output_path = cgcx.output_filenames.temp_path_for_cgu(
928                output_type,
929                &module.name,
930                cgcx.invocation_temp.as_deref(),
931            );
932            load_from_incr_comp_dir(output_path, &saved_file)
933        } else {
934            None
935        }
936    };
937
938    let module_config = &cgcx.module_config;
939    let should_emit_obj = module_config.emit_obj != EmitObj::None;
940    let assembly = load_from_incr_cache(module_config.emit_asm, OutputType::Assembly);
941    let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly);
942    let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode);
943    let object = load_from_incr_cache(should_emit_obj, OutputType::Object);
944    if should_emit_obj && object.is_none() {
945        cgcx.create_dcx().handle().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
946    }
947
948    WorkItemResult::Finished(CompiledModule {
949        links_from_incr_cache,
950        name: module.name,
951        object,
952        dwarf_object,
953        bytecode,
954        assembly,
955        llvm_ir,
956    })
957}
958
959fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
960    cgcx: &CodegenContext<B>,
961    exported_symbols_for_lto: &[String],
962    each_linked_rlib_for_lto: &[PathBuf],
963    mut needs_fat_lto: Vec<FatLtoInput<B>>,
964    import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
965) -> WorkItemResult<B> {
966    for (module, wp) in import_only_modules {
967        needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module })
968    }
969
970    let module = B::run_and_optimize_fat_lto(
971        cgcx,
972        exported_symbols_for_lto,
973        each_linked_rlib_for_lto,
974        needs_fat_lto,
975    );
976    let module = B::codegen(cgcx, module, &cgcx.module_config);
977    WorkItemResult::Finished(module)
978}
979
980fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
981    cgcx: &CodegenContext<B>,
982    module: lto::ThinModule<B>,
983) -> WorkItemResult<B> {
984    let module = B::optimize_thin(cgcx, module);
985    let module = B::codegen(cgcx, module, &cgcx.module_config);
986    WorkItemResult::Finished(module)
987}
988
989/// Messages sent to the coordinator.
990pub(crate) enum Message<B: WriteBackendMethods> {
991    /// A jobserver token has become available. Sent from the jobserver helper
992    /// thread.
993    Token(io::Result<Acquired>),
994
995    /// The backend has finished processing a work item for a codegen unit.
996    /// Sent from a backend worker thread.
997    WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>> },
998
999    /// The frontend has finished generating something (backend IR or a
1000    /// post-LTO artifact) for a codegen unit, and it should be passed to the
1001    /// backend. Sent from the main thread.
1002    CodegenDone { llvm_work_item: WorkItem<B>, cost: u64 },
1003
1004    /// Similar to `CodegenDone`, but for reusing a pre-LTO artifact
1005    /// Sent from the main thread.
1006    AddImportOnlyModule {
1007        module_data: SerializedModule<B::ModuleBuffer>,
1008        work_product: WorkProduct,
1009    },
1010
1011    /// The frontend has finished generating everything for all codegen units.
1012    /// Sent from the main thread.
1013    CodegenComplete,
1014
1015    /// Some normal-ish compiler error occurred, and codegen should be wound
1016    /// down. Sent from the main thread.
1017    CodegenAborted,
1018}
1019
1020/// A message sent from the coordinator thread to the main thread telling it to
1021/// process another codegen unit.
1022pub struct CguMessage;
1023
1024// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which
1025// can be used to send diagnostics from codegen threads to the main thread.
1026// It's missing the following fields from `rustc_errors::DiagInner`.
1027// - `span`: it doesn't impl `Send`.
1028// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen
1029//   diagnostics.
1030// - `sort_span`: it doesn't impl `Send`.
1031// - `is_lint`: lints aren't relevant during codegen.
1032// - `emitted_at`: not used for codegen diagnostics.
1033struct Diagnostic {
1034    level: Level,
1035    messages: Vec<(DiagMessage, Style)>,
1036    code: Option<ErrCode>,
1037    children: Vec<Subdiagnostic>,
1038    args: DiagArgMap,
1039}
1040
1041// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's
1042// missing the following fields from `rustc_errors::Subdiag`.
1043// - `span`: it doesn't impl `Send`.
1044pub(crate) struct Subdiagnostic {
1045    level: Level,
1046    messages: Vec<(DiagMessage, Style)>,
1047}
1048
1049#[derive(PartialEq, Clone, Copy, Debug)]
1050enum MainThreadState {
1051    /// Doing nothing.
1052    Idle,
1053
1054    /// Doing codegen, i.e. MIR-to-LLVM-IR conversion.
1055    Codegenning,
1056
1057    /// Idle, but lending the compiler process's Token to an LLVM thread so it can do useful work.
1058    Lending,
1059}
1060
1061fn start_executing_work<B: ExtraBackendMethods>(
1062    backend: B,
1063    tcx: TyCtxt<'_>,
1064    crate_info: &CrateInfo,
1065    shared_emitter: SharedEmitter,
1066    codegen_worker_send: Sender<CguMessage>,
1067    coordinator_receive: Receiver<Message<B>>,
1068    regular_config: Arc<ModuleConfig>,
1069    allocator_config: Arc<ModuleConfig>,
1070    allocator_module: Option<ModuleCodegen<B::Module>>,
1071    tx_to_llvm_workers: Sender<Message<B>>,
1072) -> thread::JoinHandle<Result<CompiledModules, ()>> {
1073    let coordinator_send = tx_to_llvm_workers;
1074    let sess = tcx.sess;
1075
1076    let mut each_linked_rlib_for_lto = Vec::new();
1077    let mut each_linked_rlib_file_for_lto = Vec::new();
1078    drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
1079        if link::ignored_for_lto(sess, crate_info, cnum) {
1080            return;
1081        }
1082        each_linked_rlib_for_lto.push(cnum);
1083        each_linked_rlib_file_for_lto.push(path.to_path_buf());
1084    }));
1085
1086    // Compute the set of symbols we need to retain when doing LTO (if we need to)
1087    let exported_symbols_for_lto =
1088        Arc::new(lto::exported_symbols_for_lto(tcx, &each_linked_rlib_for_lto));
1089
1090    // First up, convert our jobserver into a helper thread so we can use normal
1091    // mpsc channels to manage our messages and such.
1092    // After we've requested tokens then we'll, when we can,
1093    // get tokens on `coordinator_receive` which will
1094    // get managed in the main loop below.
1095    let coordinator_send2 = coordinator_send.clone();
1096    let helper = jobserver::client()
1097        .into_helper_thread(move |token| {
1098            drop(coordinator_send2.send(Message::Token::<B>(token)));
1099        })
1100        .expect("failed to spawn helper thread");
1101
1102    let ol =
1103        if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
1104            // If we know that we won’t be doing codegen, create target machines without optimisation.
1105            config::OptLevel::No
1106        } else {
1107            tcx.backend_optimization_level(())
1108        };
1109    let backend_features = tcx.global_backend_features(());
1110
1111    let remark_dir = if let Some(ref dir) = sess.opts.unstable_opts.remark_dir {
1112        let result = fs::create_dir_all(dir).and_then(|_| dir.canonicalize());
1113        match result {
1114            Ok(dir) => Some(dir),
1115            Err(error) => sess.dcx().emit_fatal(ErrorCreatingRemarkDir { error }),
1116        }
1117    } else {
1118        None
1119    };
1120
1121    let cgcx = CodegenContext::<B> {
1122        crate_types: tcx.crate_types().to_vec(),
1123        lto: sess.lto(),
1124        fewer_names: sess.fewer_names(),
1125        save_temps: sess.opts.cg.save_temps,
1126        time_trace: sess.opts.unstable_opts.llvm_time_trace,
1127        opts: Arc::new(sess.opts.clone()),
1128        prof: sess.prof.clone(),
1129        remark: sess.opts.cg.remark.clone(),
1130        remark_dir,
1131        incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
1132        expanded_args: tcx.sess.expanded_args.clone(),
1133        diag_emitter: shared_emitter.clone(),
1134        output_filenames: Arc::clone(tcx.output_filenames(())),
1135        module_config: regular_config,
1136        tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features),
1137        msvc_imps_needed: msvc_imps_needed(tcx),
1138        is_pe_coff: tcx.sess.target.is_like_windows,
1139        target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(),
1140        target_arch: tcx.sess.target.arch.to_string(),
1141        target_is_like_darwin: tcx.sess.target.is_like_darwin,
1142        target_is_like_aix: tcx.sess.target.is_like_aix,
1143        split_debuginfo: tcx.sess.split_debuginfo(),
1144        split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
1145        parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
1146        pointer_size: tcx.data_layout.pointer_size(),
1147        invocation_temp: sess.invocation_temp.clone(),
1148    };
1149
1150    let compiled_allocator_module = allocator_module.map(|mut allocator_module| {
1151        B::optimize(&cgcx, tcx.sess.dcx(), &mut allocator_module, &allocator_config);
1152        B::codegen(&cgcx, allocator_module, &allocator_config)
1153    });
1154
1155    // This is the "main loop" of parallel work happening for parallel codegen.
1156    // It's here that we manage parallelism, schedule work, and work with
1157    // messages coming from clients.
1158    //
1159    // There are a few environmental pre-conditions that shape how the system
1160    // is set up:
1161    //
1162    // - Error reporting can only happen on the main thread because that's the
1163    //   only place where we have access to the compiler `Session`.
1164    // - LLVM work can be done on any thread.
1165    // - Codegen can only happen on the main thread.
1166    // - Each thread doing substantial work must be in possession of a `Token`
1167    //   from the `Jobserver`.
1168    // - The compiler process always holds one `Token`. Any additional `Tokens`
1169    //   have to be requested from the `Jobserver`.
1170    //
1171    // Error Reporting
1172    // ===============
1173    // The error reporting restriction is handled separately from the rest: We
1174    // set up a `SharedEmitter` that holds an open channel to the main thread.
1175    // When an error occurs on any thread, the shared emitter will send the
1176    // error message to the receiver main thread (`SharedEmitterMain`). The
1177    // main thread will periodically query this error message queue and emit
1178    // any error messages it has received. It might even abort compilation if
1179    // it has received a fatal error. In this case we rely on all other threads
1180    // being torn down automatically with the main thread.
1181    // Since the main thread will often be busy doing codegen work, error
1182    // reporting will be somewhat delayed, since the message queue can only be
1183    // checked in between two work packages.
1184    //
1185    // Work Processing Infrastructure
1186    // ==============================
1187    // The work processing infrastructure knows three major actors:
1188    //
1189    // - the coordinator thread,
1190    // - the main thread, and
1191    // - LLVM worker threads
1192    //
1193    // The coordinator thread is running a message loop. It instructs the main
1194    // thread about what work to do when, and it will spawn off LLVM worker
1195    // threads as open LLVM WorkItems become available.
1196    //
1197    // The job of the main thread is to codegen CGUs into LLVM work packages
1198    // (since the main thread is the only thread that can do this). The main
1199    // thread will block until it receives a message from the coordinator, upon
1200    // which it will codegen one CGU, send it to the coordinator and block
1201    // again. This way the coordinator can control what the main thread is
1202    // doing.
1203    //
1204    // The coordinator keeps a queue of LLVM WorkItems, and when a `Token` is
1205    // available, it will spawn off a new LLVM worker thread and let it process
1206    // a WorkItem. When a LLVM worker thread is done with its WorkItem,
1207    // it will just shut down, which also frees all resources associated with
1208    // the given LLVM module, and sends a message to the coordinator that the
1209    // WorkItem has been completed.
1210    //
1211    // Work Scheduling
1212    // ===============
1213    // The scheduler's goal is to minimize the time it takes to complete all
1214    // work there is, however, we also want to keep memory consumption low
1215    // if possible. These two goals are at odds with each other: If memory
1216    // consumption were not an issue, we could just let the main thread produce
1217    // LLVM WorkItems at full speed, assuring maximal utilization of
1218    // Tokens/LLVM worker threads. However, since codegen is usually faster
1219    // than LLVM processing, the queue of LLVM WorkItems would fill up and each
1220    // WorkItem potentially holds on to a substantial amount of memory.
1221    //
1222    // So the actual goal is to always produce just enough LLVM WorkItems as
1223    // not to starve our LLVM worker threads. That means, once we have enough
1224    // WorkItems in our queue, we can block the main thread, so it does not
1225    // produce more until we need them.
1226    //
1227    // Doing LLVM Work on the Main Thread
1228    // ----------------------------------
1229    // Since the main thread owns the compiler process's implicit `Token`, it is
1230    // wasteful to keep it blocked without doing any work. Therefore, what we do
1231    // in this case is: We spawn off an additional LLVM worker thread that helps
1232    // reduce the queue. The work it is doing corresponds to the implicit
1233    // `Token`. The coordinator will mark the main thread as being busy with
1234    // LLVM work. (The actual work happens on another OS thread but we just care
1235    // about `Tokens`, not actual threads).
1236    //
1237    // When any LLVM worker thread finishes while the main thread is marked as
1238    // "busy with LLVM work", we can do a little switcheroo: We give the Token
1239    // of the just finished thread to the LLVM worker thread that is working on
1240    // behalf of the main thread's implicit Token, thus freeing up the main
1241    // thread again. The coordinator can then again decide what the main thread
1242    // should do. This allows the coordinator to make decisions at more points
1243    // in time.
1244    //
1245    // Striking a Balance between Throughput and Memory Consumption
1246    // ------------------------------------------------------------
1247    // Since our two goals, (1) use as many Tokens as possible and (2) keep
1248    // memory consumption as low as possible, are in conflict with each other,
1249    // we have to find a trade off between them. Right now, the goal is to keep
1250    // all workers busy, which means that no worker should find the queue empty
1251    // when it is ready to start.
1252    // How do we do achieve this? Good question :) We actually never know how
1253    // many `Tokens` are potentially available so it's hard to say how much to
1254    // fill up the queue before switching the main thread to LLVM work. Also we
1255    // currently don't have a means to estimate how long a running LLVM worker
1256    // will still be busy with it's current WorkItem. However, we know the
1257    // maximal count of available Tokens that makes sense (=the number of CPU
1258    // cores), so we can take a conservative guess. The heuristic we use here
1259    // is implemented in the `queue_full_enough()` function.
1260    //
1261    // Some Background on Jobservers
1262    // -----------------------------
1263    // It's worth also touching on the management of parallelism here. We don't
1264    // want to just spawn a thread per work item because while that's optimal
1265    // parallelism it may overload a system with too many threads or violate our
1266    // configuration for the maximum amount of cpu to use for this process. To
1267    // manage this we use the `jobserver` crate.
1268    //
1269    // Job servers are an artifact of GNU make and are used to manage
1270    // parallelism between processes. A jobserver is a glorified IPC semaphore
1271    // basically. Whenever we want to run some work we acquire the semaphore,
1272    // and whenever we're done with that work we release the semaphore. In this
1273    // manner we can ensure that the maximum number of parallel workers is
1274    // capped at any one point in time.
1275    //
1276    // LTO and the coordinator thread
1277    // ------------------------------
1278    //
1279    // The final job the coordinator thread is responsible for is managing LTO
1280    // and how that works. When LTO is requested what we'll do is collect all
1281    // optimized LLVM modules into a local vector on the coordinator. Once all
1282    // modules have been codegened and optimized we hand this to the `lto`
1283    // module for further optimization. The `lto` module will return back a list
1284    // of more modules to work on, which the coordinator will continue to spawn
1285    // work for.
1286    //
1287    // Each LLVM module is automatically sent back to the coordinator for LTO if
1288    // necessary. There's already optimizations in place to avoid sending work
1289    // back to the coordinator if LTO isn't requested.
1290    return B::spawn_named_thread(cgcx.time_trace, "coordinator".to_string(), move || {
1291        // This is where we collect codegen units that have gone all the way
1292        // through codegen and LLVM.
1293        let mut compiled_modules = vec![];
1294        let mut needs_fat_lto = Vec::new();
1295        let mut needs_thin_lto = Vec::new();
1296        let mut lto_import_only_modules = Vec::new();
1297        let mut started_lto = false;
1298
1299        /// Possible state transitions:
1300        /// - Ongoing -> Completed
1301        /// - Ongoing -> Aborted
1302        /// - Completed -> Aborted
1303        #[derive(Debug, PartialEq)]
1304        enum CodegenState {
1305            Ongoing,
1306            Completed,
1307            Aborted,
1308        }
1309        use CodegenState::*;
1310        let mut codegen_state = Ongoing;
1311
1312        // This is the queue of LLVM work items that still need processing.
1313        let mut work_items = Vec::<(WorkItem<B>, u64)>::new();
1314
1315        // This are the Jobserver Tokens we currently hold. Does not include
1316        // the implicit Token the compiler process owns no matter what.
1317        let mut tokens = Vec::new();
1318
1319        let mut main_thread_state = MainThreadState::Idle;
1320
1321        // How many LLVM worker threads are running while holding a Token. This
1322        // *excludes* any that the main thread is lending a Token to.
1323        let mut running_with_own_token = 0;
1324
1325        // How many LLVM worker threads are running in total. This *includes*
1326        // any that the main thread is lending a Token to.
1327        let running_with_any_token = |main_thread_state, running_with_own_token| {
1328            running_with_own_token
1329                + if main_thread_state == MainThreadState::Lending { 1 } else { 0 }
1330        };
1331
1332        let mut llvm_start_time: Option<VerboseTimingGuard<'_>> = None;
1333
1334        // Run the message loop while there's still anything that needs message
1335        // processing. Note that as soon as codegen is aborted we simply want to
1336        // wait for all existing work to finish, so many of the conditions here
1337        // only apply if codegen hasn't been aborted as they represent pending
1338        // work to be done.
1339        loop {
1340            // While there are still CGUs to be codegened, the coordinator has
1341            // to decide how to utilize the compiler processes implicit Token:
1342            // For codegenning more CGU or for running them through LLVM.
1343            if codegen_state == Ongoing {
1344                if main_thread_state == MainThreadState::Idle {
1345                    // Compute the number of workers that will be running once we've taken as many
1346                    // items from the work queue as we can, plus one for the main thread. It's not
1347                    // critically important that we use this instead of just
1348                    // `running_with_own_token`, but it prevents the `queue_full_enough` heuristic
1349                    // from fluctuating just because a worker finished up and we decreased the
1350                    // `running_with_own_token` count, even though we're just going to increase it
1351                    // right after this when we put a new worker to work.
1352                    let extra_tokens = tokens.len().checked_sub(running_with_own_token).unwrap();
1353                    let additional_running = std::cmp::min(extra_tokens, work_items.len());
1354                    let anticipated_running = running_with_own_token + additional_running + 1;
1355
1356                    if !queue_full_enough(work_items.len(), anticipated_running) {
1357                        // The queue is not full enough, process more codegen units:
1358                        if codegen_worker_send.send(CguMessage).is_err() {
1359                            panic!("Could not send CguMessage to main thread")
1360                        }
1361                        main_thread_state = MainThreadState::Codegenning;
1362                    } else {
1363                        // The queue is full enough to not let the worker
1364                        // threads starve. Use the implicit Token to do some
1365                        // LLVM work too.
1366                        let (item, _) =
1367                            work_items.pop().expect("queue empty - queue_full_enough() broken?");
1368                        main_thread_state = MainThreadState::Lending;
1369                        spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item);
1370                    }
1371                }
1372            } else if codegen_state == Completed {
1373                if running_with_any_token(main_thread_state, running_with_own_token) == 0
1374                    && work_items.is_empty()
1375                {
1376                    // All codegen work is done. Do we have LTO work to do?
1377                    if needs_fat_lto.is_empty()
1378                        && needs_thin_lto.is_empty()
1379                        && lto_import_only_modules.is_empty()
1380                    {
1381                        // Nothing more to do!
1382                        break;
1383                    }
1384
1385                    // We have LTO work to do. Perform the serial work here of
1386                    // figuring out what we're going to LTO and then push a
1387                    // bunch of work items onto our queue to do LTO. This all
1388                    // happens on the coordinator thread but it's very quick so
1389                    // we don't worry about tokens.
1390                    assert!(!started_lto);
1391                    started_lto = true;
1392
1393                    let needs_fat_lto = mem::take(&mut needs_fat_lto);
1394                    let needs_thin_lto = mem::take(&mut needs_thin_lto);
1395                    let import_only_modules = mem::take(&mut lto_import_only_modules);
1396                    let each_linked_rlib_file_for_lto =
1397                        mem::take(&mut each_linked_rlib_file_for_lto);
1398
1399                    check_lto_allowed(&cgcx);
1400
1401                    if !needs_fat_lto.is_empty() {
1402                        assert!(needs_thin_lto.is_empty());
1403
1404                        work_items.push((
1405                            WorkItem::FatLto {
1406                                exported_symbols_for_lto: Arc::clone(&exported_symbols_for_lto),
1407                                each_linked_rlib_for_lto: each_linked_rlib_file_for_lto,
1408                                needs_fat_lto,
1409                                import_only_modules,
1410                            },
1411                            0,
1412                        ));
1413                        if cgcx.parallel {
1414                            helper.request_token();
1415                        }
1416                    } else {
1417                        for (work, cost) in generate_thin_lto_work(
1418                            &cgcx,
1419                            &exported_symbols_for_lto,
1420                            &each_linked_rlib_file_for_lto,
1421                            needs_thin_lto,
1422                            import_only_modules,
1423                        ) {
1424                            let insertion_index = work_items
1425                                .binary_search_by_key(&cost, |&(_, cost)| cost)
1426                                .unwrap_or_else(|e| e);
1427                            work_items.insert(insertion_index, (work, cost));
1428                            if cgcx.parallel {
1429                                helper.request_token();
1430                            }
1431                        }
1432                    }
1433                }
1434
1435                // In this branch, we know that everything has been codegened,
1436                // so it's just a matter of determining whether the implicit
1437                // Token is free to use for LLVM work.
1438                match main_thread_state {
1439                    MainThreadState::Idle => {
1440                        if let Some((item, _)) = work_items.pop() {
1441                            main_thread_state = MainThreadState::Lending;
1442                            spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item);
1443                        } else {
1444                            // There is no unstarted work, so let the main thread
1445                            // take over for a running worker. Otherwise the
1446                            // implicit token would just go to waste.
1447                            // We reduce the `running` counter by one. The
1448                            // `tokens.truncate()` below will take care of
1449                            // giving the Token back.
1450                            assert!(running_with_own_token > 0);
1451                            running_with_own_token -= 1;
1452                            main_thread_state = MainThreadState::Lending;
1453                        }
1454                    }
1455                    MainThreadState::Codegenning => bug!(
1456                        "codegen worker should not be codegenning after \
1457                              codegen was already completed"
1458                    ),
1459                    MainThreadState::Lending => {
1460                        // Already making good use of that token
1461                    }
1462                }
1463            } else {
1464                // Don't queue up any more work if codegen was aborted, we're
1465                // just waiting for our existing children to finish.
1466                assert!(codegen_state == Aborted);
1467                if running_with_any_token(main_thread_state, running_with_own_token) == 0 {
1468                    break;
1469                }
1470            }
1471
1472            // Spin up what work we can, only doing this while we've got available
1473            // parallelism slots and work left to spawn.
1474            if codegen_state != Aborted {
1475                while running_with_own_token < tokens.len()
1476                    && let Some((item, _)) = work_items.pop()
1477                {
1478                    spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item);
1479                    running_with_own_token += 1;
1480                }
1481            }
1482
1483            // Relinquish accidentally acquired extra tokens.
1484            tokens.truncate(running_with_own_token);
1485
1486            match coordinator_receive.recv().unwrap() {
1487                // Save the token locally and the next turn of the loop will use
1488                // this to spawn a new unit of work, or it may get dropped
1489                // immediately if we have no more work to spawn.
1490                Message::Token(token) => {
1491                    match token {
1492                        Ok(token) => {
1493                            tokens.push(token);
1494
1495                            if main_thread_state == MainThreadState::Lending {
1496                                // If the main thread token is used for LLVM work
1497                                // at the moment, we turn that thread into a regular
1498                                // LLVM worker thread, so the main thread is free
1499                                // to react to codegen demand.
1500                                main_thread_state = MainThreadState::Idle;
1501                                running_with_own_token += 1;
1502                            }
1503                        }
1504                        Err(e) => {
1505                            let msg = &format!("failed to acquire jobserver token: {e}");
1506                            shared_emitter.fatal(msg);
1507                            codegen_state = Aborted;
1508                        }
1509                    }
1510                }
1511
1512                Message::CodegenDone { llvm_work_item, cost } => {
1513                    // We keep the queue sorted by estimated processing cost,
1514                    // so that more expensive items are processed earlier. This
1515                    // is good for throughput as it gives the main thread more
1516                    // time to fill up the queue and it avoids scheduling
1517                    // expensive items to the end.
1518                    // Note, however, that this is not ideal for memory
1519                    // consumption, as LLVM module sizes are not evenly
1520                    // distributed.
1521                    let insertion_index = work_items.binary_search_by_key(&cost, |&(_, cost)| cost);
1522                    let insertion_index = match insertion_index {
1523                        Ok(idx) | Err(idx) => idx,
1524                    };
1525                    work_items.insert(insertion_index, (llvm_work_item, cost));
1526
1527                    if cgcx.parallel {
1528                        helper.request_token();
1529                    }
1530                    assert_eq!(main_thread_state, MainThreadState::Codegenning);
1531                    main_thread_state = MainThreadState::Idle;
1532                }
1533
1534                Message::CodegenComplete => {
1535                    if codegen_state != Aborted {
1536                        codegen_state = Completed;
1537                    }
1538                    assert_eq!(main_thread_state, MainThreadState::Codegenning);
1539                    main_thread_state = MainThreadState::Idle;
1540                }
1541
1542                // If codegen is aborted that means translation was aborted due
1543                // to some normal-ish compiler error. In this situation we want
1544                // to exit as soon as possible, but we want to make sure all
1545                // existing work has finished. Flag codegen as being done, and
1546                // then conditions above will ensure no more work is spawned but
1547                // we'll keep executing this loop until `running_with_own_token`
1548                // hits 0.
1549                Message::CodegenAborted => {
1550                    codegen_state = Aborted;
1551                }
1552
1553                Message::WorkItem { result } => {
1554                    // If a thread exits successfully then we drop a token associated
1555                    // with that worker and update our `running_with_own_token` count.
1556                    // We may later re-acquire a token to continue running more work.
1557                    // We may also not actually drop a token here if the worker was
1558                    // running with an "ephemeral token".
1559                    if main_thread_state == MainThreadState::Lending {
1560                        main_thread_state = MainThreadState::Idle;
1561                    } else {
1562                        running_with_own_token -= 1;
1563                    }
1564
1565                    match result {
1566                        Ok(WorkItemResult::Finished(compiled_module)) => {
1567                            compiled_modules.push(compiled_module);
1568                        }
1569                        Ok(WorkItemResult::NeedsFatLto(fat_lto_input)) => {
1570                            assert!(!started_lto);
1571                            assert!(needs_thin_lto.is_empty());
1572                            needs_fat_lto.push(fat_lto_input);
1573                        }
1574                        Ok(WorkItemResult::NeedsThinLto(name, thin_buffer)) => {
1575                            assert!(!started_lto);
1576                            assert!(needs_fat_lto.is_empty());
1577                            needs_thin_lto.push((name, thin_buffer));
1578                        }
1579                        Err(Some(WorkerFatalError)) => {
1580                            // Like `CodegenAborted`, wait for remaining work to finish.
1581                            codegen_state = Aborted;
1582                        }
1583                        Err(None) => {
1584                            // If the thread failed that means it panicked, so
1585                            // we abort immediately.
1586                            bug!("worker thread panicked");
1587                        }
1588                    }
1589                }
1590
1591                Message::AddImportOnlyModule { module_data, work_product } => {
1592                    assert!(!started_lto);
1593                    assert_eq!(codegen_state, Ongoing);
1594                    assert_eq!(main_thread_state, MainThreadState::Codegenning);
1595                    lto_import_only_modules.push((module_data, work_product));
1596                    main_thread_state = MainThreadState::Idle;
1597                }
1598            }
1599        }
1600
1601        if codegen_state == Aborted {
1602            return Err(());
1603        }
1604
1605        // Drop to print timings
1606        drop(llvm_start_time);
1607
1608        // Regardless of what order these modules completed in, report them to
1609        // the backend in the same order every time to ensure that we're handing
1610        // out deterministic results.
1611        compiled_modules.sort_by(|a, b| a.name.cmp(&b.name));
1612
1613        Ok(CompiledModules {
1614            modules: compiled_modules,
1615            allocator_module: compiled_allocator_module,
1616        })
1617    })
1618    .expect("failed to spawn coordinator thread");
1619
1620    // A heuristic that determines if we have enough LLVM WorkItems in the
1621    // queue so that the main thread can do LLVM work instead of codegen
1622    fn queue_full_enough(items_in_queue: usize, workers_running: usize) -> bool {
1623        // This heuristic scales ahead-of-time codegen according to available
1624        // concurrency, as measured by `workers_running`. The idea is that the
1625        // more concurrency we have available, the more demand there will be for
1626        // work items, and the fuller the queue should be kept to meet demand.
1627        // An important property of this approach is that we codegen ahead of
1628        // time only as much as necessary, so as to keep fewer LLVM modules in
1629        // memory at once, thereby reducing memory consumption.
1630        //
1631        // When the number of workers running is less than the max concurrency
1632        // available to us, this heuristic can cause us to instruct the main
1633        // thread to work on an LLVM item (that is, tell it to "LLVM") instead
1634        // of codegen, even though it seems like it *should* be codegenning so
1635        // that we can create more work items and spawn more LLVM workers.
1636        //
1637        // But this is not a problem. When the main thread is told to LLVM,
1638        // according to this heuristic and how work is scheduled, there is
1639        // always at least one item in the queue, and therefore at least one
1640        // pending jobserver token request. If there *is* more concurrency
1641        // available, we will immediately receive a token, which will upgrade
1642        // the main thread's LLVM worker to a real one (conceptually), and free
1643        // up the main thread to codegen if necessary. On the other hand, if
1644        // there isn't more concurrency, then the main thread working on an LLVM
1645        // item is appropriate, as long as the queue is full enough for demand.
1646        //
1647        // Speaking of which, how full should we keep the queue? Probably less
1648        // full than you'd think. A lot has to go wrong for the queue not to be
1649        // full enough and for that to have a negative effect on compile times.
1650        //
1651        // Workers are unlikely to finish at exactly the same time, so when one
1652        // finishes and takes another work item off the queue, we often have
1653        // ample time to codegen at that point before the next worker finishes.
1654        // But suppose that codegen takes so long that the workers exhaust the
1655        // queue, and we have one or more workers that have nothing to work on.
1656        // Well, it might not be so bad. Of all the LLVM modules we create and
1657        // optimize, one has to finish last. It's not necessarily the case that
1658        // by losing some concurrency for a moment, we delay the point at which
1659        // that last LLVM module is finished and the rest of compilation can
1660        // proceed. Also, when we can't take advantage of some concurrency, we
1661        // give tokens back to the job server. That enables some other rustc to
1662        // potentially make use of the available concurrency. That could even
1663        // *decrease* overall compile time if we're lucky. But yes, if no other
1664        // rustc can make use of the concurrency, then we've squandered it.
1665        //
1666        // However, keeping the queue full is also beneficial when we have a
1667        // surge in available concurrency. Then items can be taken from the
1668        // queue immediately, without having to wait for codegen.
1669        //
1670        // So, the heuristic below tries to keep one item in the queue for every
1671        // four running workers. Based on limited benchmarking, this appears to
1672        // be more than sufficient to avoid increasing compilation times.
1673        let quarter_of_workers = workers_running - 3 * workers_running / 4;
1674        items_in_queue > 0 && items_in_queue >= quarter_of_workers
1675    }
1676}
1677
1678/// `FatalError` is explicitly not `Send`.
1679#[must_use]
1680pub(crate) struct WorkerFatalError;
1681
1682fn spawn_work<'a, B: ExtraBackendMethods>(
1683    cgcx: &'a CodegenContext<B>,
1684    coordinator_send: Sender<Message<B>>,
1685    llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
1686    work: WorkItem<B>,
1687) {
1688    if llvm_start_time.is_none() {
1689        *llvm_start_time = Some(cgcx.prof.verbose_generic_activity("LLVM_passes"));
1690    }
1691
1692    let cgcx = cgcx.clone();
1693
1694    B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || {
1695        let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work {
1696            WorkItem::Optimize(m) => {
1697                let _timer =
1698                    cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name);
1699                execute_optimize_work_item(&cgcx, m)
1700            }
1701            WorkItem::CopyPostLtoArtifacts(m) => {
1702                let _timer = cgcx
1703                    .prof
1704                    .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*m.name);
1705                execute_copy_from_cache_work_item(&cgcx, m)
1706            }
1707            WorkItem::FatLto {
1708                exported_symbols_for_lto,
1709                each_linked_rlib_for_lto,
1710                needs_fat_lto,
1711                import_only_modules,
1712            } => {
1713                let _timer =
1714                    cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", "everything");
1715                execute_fat_lto_work_item(
1716                    &cgcx,
1717                    &exported_symbols_for_lto,
1718                    &each_linked_rlib_for_lto,
1719                    needs_fat_lto,
1720                    import_only_modules,
1721                )
1722            }
1723            WorkItem::ThinLto(m) => {
1724                let _timer =
1725                    cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
1726                execute_thin_lto_work_item(&cgcx, m)
1727            }
1728        }));
1729
1730        let msg = match result {
1731            Ok(result) => Message::WorkItem::<B> { result: Ok(result) },
1732
1733            // We ignore any `FatalError` coming out of `execute_work_item`, as a
1734            // diagnostic was already sent off to the main thread - just surface
1735            // that there was an error in this worker.
1736            Err(err) if err.is::<FatalErrorMarker>() => {
1737                Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)) }
1738            }
1739
1740            Err(_) => Message::WorkItem::<B> { result: Err(None) },
1741        };
1742        drop(coordinator_send.send(msg));
1743    })
1744    .expect("failed to spawn work thread");
1745}
1746
1747enum SharedEmitterMessage {
1748    Diagnostic(Diagnostic),
1749    InlineAsmError(SpanData, String, Level, Option<(String, Vec<InnerSpan>)>),
1750    Fatal(String),
1751}
1752
1753#[derive(Clone)]
1754pub struct SharedEmitter {
1755    sender: Sender<SharedEmitterMessage>,
1756}
1757
1758pub struct SharedEmitterMain {
1759    receiver: Receiver<SharedEmitterMessage>,
1760}
1761
1762impl SharedEmitter {
1763    fn new() -> (SharedEmitter, SharedEmitterMain) {
1764        let (sender, receiver) = channel();
1765
1766        (SharedEmitter { sender }, SharedEmitterMain { receiver })
1767    }
1768
1769    pub fn inline_asm_error(
1770        &self,
1771        span: SpanData,
1772        msg: String,
1773        level: Level,
1774        source: Option<(String, Vec<InnerSpan>)>,
1775    ) {
1776        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(span, msg, level, source)));
1777    }
1778
1779    fn fatal(&self, msg: &str) {
1780        drop(self.sender.send(SharedEmitterMessage::Fatal(msg.to_string())));
1781    }
1782}
1783
1784impl Emitter for SharedEmitter {
1785    fn emit_diagnostic(
1786        &mut self,
1787        mut diag: rustc_errors::DiagInner,
1788        _registry: &rustc_errors::registry::Registry,
1789    ) {
1790        // Check that we aren't missing anything interesting when converting to
1791        // the cut-down local `DiagInner`.
1792        assert_eq!(diag.span, MultiSpan::new());
1793        assert_eq!(diag.suggestions, Suggestions::Enabled(vec![]));
1794        assert_eq!(diag.sort_span, rustc_span::DUMMY_SP);
1795        assert_eq!(diag.is_lint, None);
1796        // No sensible check for `diag.emitted_at`.
1797
1798        let args = mem::replace(&mut diag.args, DiagArgMap::default());
1799        drop(
1800            self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1801                level: diag.level(),
1802                messages: diag.messages,
1803                code: diag.code,
1804                children: diag
1805                    .children
1806                    .into_iter()
1807                    .map(|child| Subdiagnostic { level: child.level, messages: child.messages })
1808                    .collect(),
1809                args,
1810            })),
1811        );
1812    }
1813
1814    fn source_map(&self) -> Option<&SourceMap> {
1815        None
1816    }
1817
1818    fn translator(&self) -> &Translator {
1819        panic!("shared emitter attempted to translate a diagnostic");
1820    }
1821}
1822
1823impl SharedEmitterMain {
1824    fn check(&self, sess: &Session, blocking: bool) {
1825        loop {
1826            let message = if blocking {
1827                match self.receiver.recv() {
1828                    Ok(message) => Ok(message),
1829                    Err(_) => Err(()),
1830                }
1831            } else {
1832                match self.receiver.try_recv() {
1833                    Ok(message) => Ok(message),
1834                    Err(_) => Err(()),
1835                }
1836            };
1837
1838            match message {
1839                Ok(SharedEmitterMessage::Diagnostic(diag)) => {
1840                    // The diagnostic has been received on the main thread.
1841                    // Convert it back to a full `Diagnostic` and emit.
1842                    let dcx = sess.dcx();
1843                    let mut d =
1844                        rustc_errors::DiagInner::new_with_messages(diag.level, diag.messages);
1845                    d.code = diag.code; // may be `None`, that's ok
1846                    d.children = diag
1847                        .children
1848                        .into_iter()
1849                        .map(|sub| rustc_errors::Subdiag {
1850                            level: sub.level,
1851                            messages: sub.messages,
1852                            span: MultiSpan::new(),
1853                        })
1854                        .collect();
1855                    d.args = diag.args;
1856                    dcx.emit_diagnostic(d);
1857                    sess.dcx().abort_if_errors();
1858                }
1859                Ok(SharedEmitterMessage::InlineAsmError(span, msg, level, source)) => {
1860                    assert_matches!(level, Level::Error | Level::Warning | Level::Note);
1861                    let mut err = Diag::<()>::new(sess.dcx(), level, msg);
1862                    if !span.is_dummy() {
1863                        err.span(span.span());
1864                    }
1865
1866                    // Point to the generated assembly if it is available.
1867                    if let Some((buffer, spans)) = source {
1868                        let source = sess
1869                            .source_map()
1870                            .new_source_file(FileName::inline_asm_source_code(&buffer), buffer);
1871                        let spans: Vec<_> = spans
1872                            .iter()
1873                            .map(|sp| {
1874                                Span::with_root_ctxt(
1875                                    source.normalized_byte_pos(sp.start as u32),
1876                                    source.normalized_byte_pos(sp.end as u32),
1877                                )
1878                            })
1879                            .collect();
1880                        err.span_note(spans, "instantiated into assembly here");
1881                    }
1882
1883                    err.emit();
1884                }
1885                Ok(SharedEmitterMessage::Fatal(msg)) => {
1886                    sess.dcx().fatal(msg);
1887                }
1888                Err(_) => {
1889                    break;
1890                }
1891            }
1892        }
1893    }
1894}
1895
1896pub struct Coordinator<B: ExtraBackendMethods> {
1897    sender: Sender<Message<B>>,
1898    future: Option<thread::JoinHandle<Result<CompiledModules, ()>>>,
1899    // Only used for the Message type.
1900    phantom: PhantomData<B>,
1901}
1902
1903impl<B: ExtraBackendMethods> Coordinator<B> {
1904    fn join(mut self) -> std::thread::Result<Result<CompiledModules, ()>> {
1905        self.future.take().unwrap().join()
1906    }
1907}
1908
1909impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
1910    fn drop(&mut self) {
1911        if let Some(future) = self.future.take() {
1912            // If we haven't joined yet, signal to the coordinator that it should spawn no more
1913            // work, and wait for worker threads to finish.
1914            drop(self.sender.send(Message::CodegenAborted::<B>));
1915            drop(future.join());
1916        }
1917    }
1918}
1919
1920pub struct OngoingCodegen<B: ExtraBackendMethods> {
1921    pub backend: B,
1922    pub crate_info: CrateInfo,
1923    pub output_filenames: Arc<OutputFilenames>,
1924    // Field order below is intended to terminate the coordinator thread before two fields below
1925    // drop and prematurely close channels used by coordinator thread. See `Coordinator`'s
1926    // `Drop` implementation for more info.
1927    pub coordinator: Coordinator<B>,
1928    pub codegen_worker_receive: Receiver<CguMessage>,
1929    pub shared_emitter_main: SharedEmitterMain,
1930}
1931
1932impl<B: ExtraBackendMethods> OngoingCodegen<B> {
1933    pub fn join(self, sess: &Session) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
1934        self.shared_emitter_main.check(sess, true);
1935        let compiled_modules = sess.time("join_worker_thread", || match self.coordinator.join() {
1936            Ok(Ok(compiled_modules)) => compiled_modules,
1937            Ok(Err(())) => {
1938                sess.dcx().abort_if_errors();
1939                panic!("expected abort due to worker thread errors")
1940            }
1941            Err(_) => {
1942                bug!("panic during codegen/LLVM phase");
1943            }
1944        });
1945
1946        sess.dcx().abort_if_errors();
1947
1948        let work_products =
1949            copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules);
1950        produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames);
1951
1952        // FIXME: time_llvm_passes support - does this use a global context or
1953        // something?
1954        if sess.codegen_units().as_usize() == 1 && sess.opts.unstable_opts.time_llvm_passes {
1955            self.backend.print_pass_timings()
1956        }
1957
1958        if sess.print_llvm_stats() {
1959            self.backend.print_statistics()
1960        }
1961
1962        (
1963            CodegenResults {
1964                crate_info: self.crate_info,
1965
1966                modules: compiled_modules.modules,
1967                allocator_module: compiled_modules.allocator_module,
1968            },
1969            work_products,
1970        )
1971    }
1972
1973    pub(crate) fn codegen_finished(&self, tcx: TyCtxt<'_>) {
1974        self.wait_for_signal_to_codegen_item();
1975        self.check_for_errors(tcx.sess);
1976        drop(self.coordinator.sender.send(Message::CodegenComplete::<B>));
1977    }
1978
1979    pub(crate) fn check_for_errors(&self, sess: &Session) {
1980        self.shared_emitter_main.check(sess, false);
1981    }
1982
1983    pub(crate) fn wait_for_signal_to_codegen_item(&self) {
1984        match self.codegen_worker_receive.recv() {
1985            Ok(CguMessage) => {
1986                // Ok to proceed.
1987            }
1988            Err(_) => {
1989                // One of the LLVM threads must have panicked, fall through so
1990                // error handling can be reached.
1991            }
1992        }
1993    }
1994}
1995
1996pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>(
1997    coordinator: &Coordinator<B>,
1998    module: ModuleCodegen<B::Module>,
1999    cost: u64,
2000) {
2001    let llvm_work_item = WorkItem::Optimize(module);
2002    drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost }));
2003}
2004
2005pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>(
2006    coordinator: &Coordinator<B>,
2007    module: CachedModuleCodegen,
2008) {
2009    let llvm_work_item = WorkItem::CopyPostLtoArtifacts(module);
2010    drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost: 0 }));
2011}
2012
2013pub(crate) fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>(
2014    tcx: TyCtxt<'_>,
2015    coordinator: &Coordinator<B>,
2016    module: CachedModuleCodegen,
2017) {
2018    let filename = pre_lto_bitcode_filename(&module.name);
2019    let bc_path = in_incr_comp_dir_sess(tcx.sess, &filename);
2020    let file = fs::File::open(&bc_path)
2021        .unwrap_or_else(|e| panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e));
2022
2023    let mmap = unsafe {
2024        Mmap::map(file).unwrap_or_else(|e| {
2025            panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e)
2026        })
2027    };
2028    // Schedule the module to be loaded
2029    drop(coordinator.sender.send(Message::AddImportOnlyModule::<B> {
2030        module_data: SerializedModule::FromUncompressedFile(mmap),
2031        work_product: module.source,
2032    }));
2033}
2034
2035fn pre_lto_bitcode_filename(module_name: &str) -> String {
2036    format!("{module_name}.{PRE_LTO_BC_EXT}")
2037}
2038
2039fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
2040    // This should never be true (because it's not supported). If it is true,
2041    // something is wrong with commandline arg validation.
2042    assert!(
2043        !(tcx.sess.opts.cg.linker_plugin_lto.enabled()
2044            && tcx.sess.target.is_like_windows
2045            && tcx.sess.opts.cg.prefer_dynamic)
2046    );
2047
2048    // We need to generate _imp__ symbol if we are generating an rlib or we include one
2049    // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve
2050    // these, but it currently does not do so.
2051    let can_have_static_objects =
2052        tcx.sess.lto() == Lto::Thin || tcx.crate_types().contains(&CrateType::Rlib);
2053
2054    tcx.sess.target.is_like_windows &&
2055    can_have_static_objects   &&
2056    // ThinLTO can't handle this workaround in all cases, so we don't
2057    // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
2058    // dynamic linking when linker plugin LTO is enabled.
2059    !tcx.sess.opts.cg.linker_plugin_lto.enabled()
2060}