use std::marker::PhantomData;
use std::panic::AssertUnwindSafe;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::{assert_matches, fs, io, mem, str, thread};

use rustc_abi::Size;
use rustc_data_structures::jobserver::{self, Acquired};
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
use rustc_errors::emitter::Emitter;
use rustc_errors::{
    Diag, DiagArgMap, DiagCtxt, DiagCtxtHandle, DiagMessage, ErrCode, FatalError, FatalErrorMarker,
    Level, MultiSpan, Style, Suggestions, catch_fatal_errors,
};
use rustc_fs_util::link_or_copy;
use rustc_hir::find_attr;
use rustc_incremental::{
    copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
};
use rustc_macros::{Decodable, Encodable};
use rustc_metadata::fs::copy_to_stdout;
use rustc_middle::bug;
use rustc_middle::dep_graph::{WorkProduct, WorkProductMap};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{
    self, CrateType, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, Passes,
    SwitchWithOptPath,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, InnerSpan, Span, SpanData};
use rustc_target::spec::{MergeFunctions, SanitizerSet};
use tracing::debug;

use crate::back::link::ensure_removed;
use crate::back::lto::{self, SerializedModule, check_lto_allowed};
use crate::errors::ErrorCreatingRemarkDir;
use crate::traits::*;
use crate::{
    CachedModuleCodegen, CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, ModuleKind,
    errors,
};

const PRE_LTO_BC_EXT: &str = "pre-lto.bc";

/// What kind of object file to emit.
#[derive(Clone, Copy, PartialEq, Encodable, Decodable)]
pub enum EmitObj {
    // No object file.
    None,

    // Just uncompressed llvm bitcode. Provides easy compatibility with
    // emscripten's ecc compiler, when used as the linker.
    Bitcode,

    // Object code, possibly augmented with a bitcode section.
    ObjectCode(BitcodeSection),
}

/// What kind of llvm bitcode section to embed in an object file.
#[derive(Clone, Copy, PartialEq, Encodable, Decodable)]
pub enum BitcodeSection {
    // No bitcode section.
    None,

    // A full, uncompressed bitcode section.
    Full,
}

/// Module-specific configuration for `optimize_and_codegen`.
#[derive(Encodable, Decodable)]
pub struct ModuleConfig {
    /// Names of additional optimization passes to run.
    pub passes: Vec<String>,
    /// Some(level) to optimize at a certain level, or None to run
    /// absolutely no optimizations (used for the allocator module).
    pub opt_level: Option<config::OptLevel>,

    pub pgo_gen: SwitchWithOptPath,
    pub pgo_use: Option<PathBuf>,
    pub pgo_sample_use: Option<PathBuf>,
    pub debug_info_for_profiling: bool,
    pub instrument_coverage: bool,

    pub sanitizer: SanitizerSet,
    pub sanitizer_recover: SanitizerSet,
    pub sanitizer_dataflow_abilist: Vec<String>,
    pub sanitizer_memory_track_origins: usize,

    // Flags indicating which outputs to produce.
    pub emit_pre_lto_bc: bool,
    pub emit_bc: bool,
    pub emit_ir: bool,
    pub emit_asm: bool,
    pub emit_obj: EmitObj,
    pub emit_thin_lto_summary: bool,

    // Miscellaneous flags. These are mostly copied from command-line
    // options.
    pub verify_llvm_ir: bool,
    pub lint_llvm_ir: bool,
    pub no_prepopulate_passes: bool,
    pub no_builtins: bool,
    pub vectorize_loop: bool,
    pub vectorize_slp: bool,
    pub merge_functions: bool,
    pub emit_lifetime_markers: bool,
    pub llvm_plugins: Vec<String>,
    pub autodiff: Vec<config::AutoDiff>,
    pub offload: Vec<config::Offload>,
}

impl ModuleConfig {
    fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
        // If it's a regular module, use `$regular`, otherwise use `$other`.
        // `$regular` and `$other` are evaluated lazily.
        macro_rules! if_regular {
            ($regular: expr, $other: expr) => {
                if let ModuleKind::Regular = kind { $regular } else { $other }
            };
        }

        let sess = tcx.sess;
        let opt_level_and_size = if_regular!(Some(sess.opts.optimize), None);

        let save_temps = sess.opts.cg.save_temps;

        let should_emit_obj = sess.opts.output_types.contains_key(&OutputType::Exe)
            || match kind {
                ModuleKind::Regular => sess.opts.output_types.contains_key(&OutputType::Object),
                ModuleKind::Allocator => false,
            };

        let emit_obj = if !should_emit_obj {
            EmitObj::None
        } else if sess.target.obj_is_bitcode
            || (sess.opts.cg.linker_plugin_lto.enabled()
                && (!no_builtins || tcx.sess.is_sanitizer_cfi_enabled()))
        {
            // This case is selected if the target uses objects as bitcode, or
            // if linker plugin LTO is enabled. In the linker plugin LTO case
            // the assumption is that the final link-step will read the bitcode
            // and convert it to object code. This may be done by either the
            // native linker or rustc itself.
            //
            // By default this branch is skipped for `#![no_builtins]` crates so
            // they emit native object files (machine code), not LLVM bitcode
            // objects for the linker (see rust-lang/rust#146133).
            //
            // However, when LLVM CFI is enabled (`-Zsanitizer=cfi`), this
            // breaks LLVM's expected pipeline: LLVM emits `llvm.type.test`
            // intrinsics and related metadata that must be lowered by LLVM's
            // `LowerTypeTests` pass before instruction selection during
            // link-time LTO. Otherwise, `llvm.type.test` intrinsics and related
            // metadata are not lowered by LLVM's `LowerTypeTests` pass before
            // reaching the target backend, and LLVM may abort during codegen
            // (for example in SelectionDAG type legalization) (see
            // rust-lang/rust#142284).
            //
            // Therefore, with `-Clinker-plugin-lto` and `-Zsanitizer=cfi`, a
            // `#![no_builtins]` crate must still use rustc's `EmitObj::Bitcode`
            // path (and emit LLVM bitcode in the `.o` for linker-based LTO).
            EmitObj::Bitcode
        } else if need_bitcode_in_object(tcx) || sess.target.requires_lto {
            EmitObj::ObjectCode(BitcodeSection::Full)
        } else {
            EmitObj::ObjectCode(BitcodeSection::None)
        };

        ModuleConfig {
            passes: if_regular!(sess.opts.cg.passes.clone(), vec![]),

            opt_level: opt_level_and_size,

            pgo_gen: if_regular!(
                sess.opts.cg.profile_generate.clone(),
                SwitchWithOptPath::Disabled
            ),
            pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None),
            pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None),
            debug_info_for_profiling: sess.opts.unstable_opts.debuginfo_for_profiling,
            instrument_coverage: if_regular!(sess.instrument_coverage(), false),

            sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()),
            sanitizer_dataflow_abilist: if_regular!(
                sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(),
                Vec::new()
            ),
            sanitizer_recover: if_regular!(
                sess.opts.unstable_opts.sanitizer_recover,
                SanitizerSet::empty()
            ),
            sanitizer_memory_track_origins: if_regular!(
                sess.opts.unstable_opts.sanitizer_memory_track_origins,
                0
            ),

            emit_pre_lto_bc: if_regular!(
                save_temps || need_pre_lto_bitcode_for_incr_comp(sess),
                false
            ),
            emit_bc: if_regular!(
                save_temps || sess.opts.output_types.contains_key(&OutputType::Bitcode),
                save_temps
            ),
            emit_ir: if_regular!(
                sess.opts.output_types.contains_key(&OutputType::LlvmAssembly),
                false
            ),
            emit_asm: if_regular!(
                sess.opts.output_types.contains_key(&OutputType::Assembly),
                false
            ),
            emit_obj,
            emit_thin_lto_summary: if_regular!(
                sess.opts.output_types.contains_key(&OutputType::ThinLinkBitcode),
                false
            ),

            verify_llvm_ir: sess.verify_llvm_ir(),
            lint_llvm_ir: sess.opts.unstable_opts.lint_llvm_ir,
            no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes,
            no_builtins: no_builtins || sess.target.no_builtins,

            // Copy what clang does by turning on loop vectorization at O2 and
            // slp vectorization at O3.
            vectorize_loop: !sess.opts.cg.no_vectorize_loops
                && (sess.opts.optimize == config::OptLevel::More
                    || sess.opts.optimize == config::OptLevel::Aggressive),
            vectorize_slp: !sess.opts.cg.no_vectorize_slp
                && sess.opts.optimize == config::OptLevel::Aggressive,

            // Some targets (namely, NVPTX) interact badly with the
            // MergeFunctions pass. This is because MergeFunctions can generate
            // new function calls which may interfere with the target calling
            // convention; e.g. for the NVPTX target, PTX kernels should not
            // call other PTX kernels. MergeFunctions can also be configured to
            // generate aliases instead, but aliases are not supported by some
            // backends (again, NVPTX). Therefore, allow targets to opt out of
            // the MergeFunctions pass, but otherwise keep the pass enabled (at
            // O2 and O3) since it can be useful for reducing code size.
            merge_functions: match sess
                .opts
                .unstable_opts
                .merge_functions
                .unwrap_or(sess.target.merge_functions)
            {
                MergeFunctions::Disabled => false,
                MergeFunctions::Trampolines | MergeFunctions::Aliases => {
                    use config::OptLevel::*;
                    match sess.opts.optimize {
                        Aggressive | More | SizeMin | Size => true,
                        Less | No => false,
                    }
                }
            },

            emit_lifetime_markers: sess.emit_lifetime_markers(),
            llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
            autodiff: if_regular!(sess.opts.unstable_opts.autodiff.clone(), vec![]),
            offload: if_regular!(sess.opts.unstable_opts.offload.clone(), vec![]),
        }
    }

    pub fn bitcode_needed(&self) -> bool {
        self.emit_bc
            || self.emit_thin_lto_summary
            || self.emit_obj == EmitObj::Bitcode
            || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
    }

    pub fn embed_bitcode(&self) -> bool {
        self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
    }
}

/// Configuration passed to the function returned by the `target_machine_factory`.
pub struct TargetMachineFactoryConfig {
    /// Split DWARF is enabled in LLVM by checking that `TM.MCOptions.SplitDwarfFile` isn't empty,
    /// so the path to the dwarf object has to be provided when we create the target machine.
    /// This can be ignored by backends which do not need it for their Split DWARF support.
    pub split_dwarf_file: Option<PathBuf>,

    /// The name of the output object file. Used for setting OutputFilenames in target options
    /// so that LLVM can emit the CodeView S_OBJNAME record in pdb files
    pub output_obj_file: Option<PathBuf>,
}

impl TargetMachineFactoryConfig {
    pub fn new(cgcx: &CodegenContext, module_name: &str) -> TargetMachineFactoryConfig {
        let split_dwarf_file = if cgcx.target_can_use_split_dwarf {
            cgcx.output_filenames.split_dwarf_path(
                cgcx.split_debuginfo,
                cgcx.split_dwarf_kind,
                module_name,
            )
        } else {
            None
        };

        let output_obj_file =
            Some(cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, module_name));
        TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
    }
}

pub type TargetMachineFactoryFn<B> = Arc<
    dyn Fn(
            DiagCtxtHandle<'_>,
            TargetMachineFactoryConfig,
        ) -> <B as WriteBackendMethods>::TargetMachine
        + Send
        + Sync,
>;

/// Additional resources used by optimize_and_codegen (not module specific)
#[derive(Clone, Encodable, Decodable)]
pub struct CodegenContext {
    // Resources needed when running LTO
    pub lto: Lto,
    pub use_linker_plugin_lto: bool,
    pub dylib_lto: bool,
    pub prefer_dynamic: bool,
    pub save_temps: bool,
    pub fewer_names: bool,
    pub time_trace: bool,
    pub crate_types: Vec<CrateType>,
    pub output_filenames: Arc<OutputFilenames>,
    pub module_config: Arc<ModuleConfig>,
    pub opt_level: OptLevel,
    pub backend_features: Vec<String>,
    pub msvc_imps_needed: bool,
    pub is_pe_coff: bool,
    pub target_can_use_split_dwarf: bool,
    pub target_arch: String,
    pub target_is_like_darwin: bool,
    pub target_is_like_aix: bool,
    pub target_is_like_gpu: bool,
    pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
    pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
    pub pointer_size: Size,

    /// LLVM optimizations for which we want to print remarks.
    pub remark: Passes,
    /// Directory into which should the LLVM optimization remarks be written.
    /// If `None`, they will be written to stderr.
    pub remark_dir: Option<PathBuf>,
    /// The incremental compilation session directory, or None if we are not
    /// compiling incrementally
    pub incr_comp_session_dir: Option<PathBuf>,
    /// `true` if the codegen should be run in parallel.
    ///
    /// Depends on [`WriteBackendMethods::supports_parallel()`] and `-Zno_parallel_backend`.
    pub parallel: bool,
}

fn generate_thin_lto_work<B: WriteBackendMethods>(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    dcx: DiagCtxtHandle<'_>,
    exported_symbols_for_lto: &[String],
    each_linked_rlib_for_lto: &[PathBuf],
    needs_thin_lto: Vec<ThinLtoInput<B>>,
) -> Vec<(ThinLtoWorkItem<B>, u64)> {
    let _prof_timer = prof.generic_activity("codegen_thin_generate_lto_work");

    let (lto_modules, copy_jobs) = B::run_thin_lto(
        cgcx,
        prof,
        dcx,
        exported_symbols_for_lto,
        each_linked_rlib_for_lto,
        needs_thin_lto,
    );
    lto_modules
        .into_iter()
        .map(|module| {
            let cost = module.cost();
            (ThinLtoWorkItem::ThinLto(module), cost)
        })
        .chain(copy_jobs.into_iter().map(|wp| {
            (
                ThinLtoWorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
                    name: wp.cgu_name.clone(),
                    source: wp,
                }),
                0, // copying is very cheap
            )
        }))
        .collect()
}

enum MaybeLtoModules<B: WriteBackendMethods> {
    NoLto(CompiledModules),
    FatLto { cgcx: CodegenContext, needs_fat_lto: Vec<FatLtoInput<B>> },
    ThinLto { cgcx: CodegenContext, needs_thin_lto: Vec<ThinLtoInput<B>> },
}

fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool {
    let sess = tcx.sess;
    sess.opts.cg.embed_bitcode
        && tcx.crate_types().contains(&CrateType::Rlib)
        && sess.opts.output_types.contains_key(&OutputType::Exe)
}

fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
    if sess.opts.incremental.is_none() {
        return false;
    }

    match sess.lto() {
        Lto::No => false,
        Lto::Fat | Lto::Thin | Lto::ThinLocal => true,
    }
}

pub(crate) fn start_async_codegen<B: WriteBackendMethods>(
    backend: B,
    tcx: TyCtxt<'_>,
    allocator_module: Option<ModuleCodegen<B::Module>>,
) -> OngoingCodegen<B> {
    let (coordinator_send, coordinator_receive) = channel();

    let no_builtins = find_attr!(tcx, crate, NoBuiltins);

    let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
    let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);

    let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
    let (codegen_worker_send, codegen_worker_receive) = channel();

    let coordinator_thread = start_executing_work(
        backend.clone(),
        tcx,
        shared_emitter,
        codegen_worker_send,
        coordinator_receive,
        Arc::new(regular_config),
        Arc::new(allocator_config),
        allocator_module,
        coordinator_send.clone(),
    );

    OngoingCodegen {
        backend,

        codegen_worker_receive,
        shared_emitter_main,
        coordinator: Coordinator {
            sender: coordinator_send,
            future: Some(coordinator_thread),
            phantom: PhantomData,
        },
        output_filenames: Arc::clone(tcx.output_filenames(())),
    }
}

fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
    sess: &Session,
    compiled_modules: &CompiledModules,
) -> WorkProductMap {
    let mut work_products = WorkProductMap::default();

    if sess.opts.incremental.is_none() || sess.opts.unstable_opts.disable_incr_comp_backend_caching
    {
        return work_products;
    }

    let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");

    for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
        let mut files = Vec::new();
        if let Some(object_file_path) = &module.object {
            files.push((OutputType::Object.extension(), object_file_path.as_path()));
        }
        if let Some(global_asm_object_file_path) = &module.global_asm_object {
            files.push(("asm.o", global_asm_object_file_path.as_path()));
        }
        if let Some(dwarf_object_file_path) = &module.dwarf_object {
            files.push(("dwo", dwarf_object_file_path.as_path()));
        }
        if let Some(path) = &module.assembly {
            files.push((OutputType::Assembly.extension(), path.as_path()));
        }
        if let Some(path) = &module.llvm_ir {
            files.push((OutputType::LlvmAssembly.extension(), path.as_path()));
        }
        if let Some(path) = &module.bytecode {
            files.push((OutputType::Bitcode.extension(), path.as_path()));
        }
        let (id, product) = copy_cgu_workproduct_to_incr_comp_cache_dir(
            sess,
            &module.name,
            files.as_slice(),
            &module.links_from_incr_cache,
        );
        work_products.insert(id, product);
    }

    work_products
}

pub fn produce_final_output_artifacts(
    sess: &Session,
    compiled_modules: &CompiledModules,
    crate_output: &OutputFilenames,
) {
    let mut user_wants_bitcode = false;
    let mut user_wants_objects = false;

    // Produce final compile outputs.
    let copy_gracefully = |from: &Path, to: &OutFileName| match to {
        OutFileName::Stdout if let Err(e) = copy_to_stdout(from) => {
            sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e));
        }
        OutFileName::Real(path) if let Err(e) = fs::copy(from, path) => {
            sess.dcx().emit_err(errors::CopyPath::new(from, path, e));
        }
        _ => {}
    };

    let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| {
        if let [module] = &compiled_modules.modules[..] {
            // 1) Only one codegen unit. In this case it's no difficulty
            //    to copy `foo.0.x` to `foo.x`.
            let path = crate_output.temp_path_for_cgu(output_type, &module.name);
            let output = crate_output.path(output_type);
            if !output_type.is_text_output() && output.is_tty() {
                sess.dcx()
                    .emit_err(errors::BinaryOutputToTty { shorthand: output_type.shorthand() });
            } else {
                copy_gracefully(&path, &output);
            }
            if !sess.opts.cg.save_temps && !keep_numbered {
                // The user just wants `foo.x`, not `foo.#module-name#.x`.
                ensure_removed(sess.dcx(), &path);
            }
        } else {
            if crate_output.outputs.contains_explicit_name(&output_type) {
                // 2) Multiple codegen units, with `--emit foo=some_name`. We have
                //    no good solution for this case, so warn the user.
                sess.dcx()
                    .emit_warn(errors::IgnoringEmitPath { extension: output_type.extension() });
            } else if crate_output.single_output_file.is_some() {
                // 3) Multiple codegen units, with `-o some_name`. We have
                //    no good solution for this case, so warn the user.
                sess.dcx().emit_warn(errors::IgnoringOutput { extension: output_type.extension() });
            } else {
                // 4) Multiple codegen units, but no explicit name. We
                //    just leave the `foo.0.x` files in place.
                // (We don't have to do any work in this case.)
            }
        }
    };

    // Flag to indicate whether the user explicitly requested bitcode.
    // Otherwise, we produced it only as a temporary output, and will need
    // to get rid of it.
    for output_type in crate_output.outputs.keys() {
        match *output_type {
            OutputType::Bitcode => {
                user_wants_bitcode = true;
                // Copy to .bc, but always keep the .0.bc. There is a later
                // check to figure out if we should delete .0.bc files, or keep
                // them for making an rlib.
                copy_if_one_unit(OutputType::Bitcode, true);
            }
            OutputType::ThinLinkBitcode => {
                copy_if_one_unit(OutputType::ThinLinkBitcode, false);
            }
            OutputType::LlvmAssembly => {
                copy_if_one_unit(OutputType::LlvmAssembly, false);
            }
            OutputType::Assembly => {
                copy_if_one_unit(OutputType::Assembly, false);
            }
            OutputType::Object => {
                user_wants_objects = true;
                copy_if_one_unit(OutputType::Object, true);
            }
            OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {}
        }
    }

    // Clean up unwanted temporary files.

    // We create the following files by default:
    //  - #crate#.#module-name#.rcgu.bc
    //  - #crate#.#module-name#.rcgu.o
    //  - #crate#.o (linked from crate.##.rcgu.o)
    //  - #crate#.bc (copied from crate.##.rcgu.bc)
    // We may create additional files if requested by the user (through
    // `-C save-temps` or `--emit=` flags).

    if !sess.opts.cg.save_temps {
        // Remove the temporary .#module-name#.rcgu.o objects. If the user didn't
        // explicitly request bitcode (with --emit=bc), and the bitcode is not
        // needed for building an rlib, then we must remove .#module-name#.bc as
        // well.

        // Specific rules for keeping .#module-name#.rcgu.bc:
        //  - If the user requested bitcode (`user_wants_bitcode`), and
        //    codegen_units > 1, then keep it.
        //  - If the user requested bitcode but codegen_units == 1, then we
        //    can toss .#module-name#.rcgu.bc because we copied it to .bc earlier.
        //  - If we're not building an rlib and the user didn't request
        //    bitcode, then delete .#module-name#.rcgu.bc.
        // If you change how this works, also update back::link::link_rlib,
        // where .#module-name#.rcgu.bc files are (maybe) deleted after making an
        // rlib.
        let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);

        let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units().as_usize() > 1;

        let keep_numbered_objects =
            needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1);

        for module in compiled_modules.modules.iter() {
            if !keep_numbered_objects {
                if let Some(ref path) = module.object {
                    ensure_removed(sess.dcx(), path);
                }

                if let Some(ref path) = module.global_asm_object {
                    ensure_removed(sess.dcx(), path);
                }

                if let Some(ref path) = module.dwarf_object {
                    ensure_removed(sess.dcx(), path);
                }
            }

            if let Some(ref path) = module.bytecode {
                if !keep_numbered_bitcode {
                    ensure_removed(sess.dcx(), path);
                }
            }
        }

        if !user_wants_bitcode
            && let Some(ref allocator_module) = compiled_modules.allocator_module
            && let Some(ref path) = allocator_module.bytecode
        {
            ensure_removed(sess.dcx(), path);
        }
    }

    if sess.opts.json_artifact_notifications {
        if let [module] = &compiled_modules.modules[..] {
            module.for_each_output(|_path, ty| {
                if sess.opts.output_types.contains_key(&ty) {
                    let descr = ty.shorthand();
                    // for single cgu file is renamed to drop cgu specific suffix
                    // so we regenerate it the same way
                    let path = crate_output.path(ty);
                    sess.dcx().emit_artifact_notification(path.as_path(), descr);
                }
            });
        } else {
            for module in &compiled_modules.modules {
                module.for_each_output(|path, ty| {
                    if sess.opts.output_types.contains_key(&ty) {
                        let descr = ty.shorthand();
                        sess.dcx().emit_artifact_notification(&path, descr);
                    }
                });
            }
        }
    }

    // We leave the following files around by default:
    //  - #crate#.o
    //  - #crate#.bc
    // These are used in linking steps and will be cleaned up afterward.
}

pub(crate) enum WorkItem<B: WriteBackendMethods> {
    /// Optimize a newly codegened, totally unoptimized module.
    Optimize(ModuleCodegen<B::Module>),
    /// Copy the post-LTO artifacts from the incremental cache to the output
    /// directory.
    CopyPostLtoArtifacts(CachedModuleCodegen),
}

enum ThinLtoWorkItem<B: WriteBackendMethods> {
    /// Copy the post-LTO artifacts from the incremental cache to the output
    /// directory.
    CopyPostLtoArtifacts(CachedModuleCodegen),
    /// Performs thin-LTO on the given module.
    ThinLto(lto::ThinModule<B>),
}

// `pthread_setname()` on *nix ignores anything beyond the first 15
// bytes. Use short descriptions to maximize the space available for
// the module name.
#[cfg(not(windows))]
fn desc(short: &str, _long: &str, name: &str) -> String {
    // The short label is three bytes, and is followed by a space. That
    // leaves 11 bytes for the CGU name. How we obtain those 11 bytes
    // depends on the CGU name form.
    //
    // - Non-incremental, e.g. `regex.f10ba03eb5ec7975-cgu.0`: the part
    //   before the `-cgu.0` is the same for every CGU, so use the
    //   `cgu.0` part. The number suffix will be different for each
    //   CGU.
    //
    // - Incremental (normal), e.g. `2i52vvl2hco29us0`: use the whole
    //   name because each CGU will have a unique ASCII hash, and the
    //   first 11 bytes will be enough to identify it.
    //
    // - Incremental (with `-Zhuman-readable-cgu-names`), e.g.
    //   `regex.f10ba03eb5ec7975-re_builder.volatile`: use the whole
    //   name. The first 11 bytes won't be enough to uniquely identify
    //   it, but no obvious substring will, and this is a rarely used
    //   option so it doesn't matter much.
    //
    assert_eq!(short.len(), 3);
    let name = if let Some(index) = name.find("-cgu.") {
        &name[index + 1..] // +1 skips the leading '-'.
    } else {
        name
    };
    format!("{short} {name}")
}

// Windows has no thread name length limit, so use more descriptive names.
#[cfg(windows)]
fn desc(_short: &str, long: &str, name: &str) -> String {
    format!("{long} {name}")
}

impl<B: WriteBackendMethods> WorkItem<B> {
    /// Generate a short description of this work item suitable for use as a thread name.
    fn short_description(&self) -> String {
        match self {
            WorkItem::Optimize(m) => desc("opt", "optimize module", &m.name),
            WorkItem::CopyPostLtoArtifacts(m) => desc("cpy", "copy LTO artifacts for", &m.name),
        }
    }
}

impl<B: WriteBackendMethods> ThinLtoWorkItem<B> {
    /// Generate a short description of this work item suitable for use as a thread name.
    fn short_description(&self) -> String {
        match self {
            ThinLtoWorkItem::CopyPostLtoArtifacts(m) => {
                desc("cpy", "copy LTO artifacts for", &m.name)
            }
            ThinLtoWorkItem::ThinLto(m) => desc("lto", "thin-LTO module", m.name()),
        }
    }
}

/// A result produced by the backend.
pub(crate) enum WorkItemResult<B: WriteBackendMethods> {
    /// The backend has finished compiling a CGU, nothing more required.
    Finished(CompiledModule),

    /// The backend has finished compiling a CGU, which now needs to go through
    /// fat LTO.
    NeedsFatLto(FatLtoInput<B>),

    /// The backend has finished compiling a CGU, which now needs to go through
    /// thin LTO.
    NeedsThinLto(String, B::ModuleBuffer),
}

pub enum FatLtoInput<B: WriteBackendMethods> {
    Serialized { name: String, bitcode_path: PathBuf },
    InMemory(ModuleCodegen<B::Module>),
}

pub enum ThinLtoInput<B: WriteBackendMethods> {
    Red { name: String, buffer: SerializedModule<B::ModuleBuffer> },
    Green { wp: WorkProduct, bitcode_path: PathBuf },
}

/// Actual LTO type we end up choosing based on multiple factors.
pub(crate) enum ComputedLtoType {
    No,
    Thin,
    Fat,
}

pub(crate) fn compute_per_cgu_lto_type(
    sess_lto: &Lto,
    linker_does_lto: bool,
    sess_crate_types: &[CrateType],
) -> ComputedLtoType {
    // If the linker does LTO, we don't have to do it. Note that we
    // keep doing full LTO, if it is requested, as not to break the
    // assumption that the output will be a single module.

    // We ignore a request for full crate graph LTO if the crate type
    // is only an rlib, as there is no full crate graph to process,
    // that'll happen later.
    //
    // This use case currently comes up primarily for targets that
    // require LTO so the request for LTO is always unconditionally
    // passed down to the backend, but we don't actually want to do
    // anything about it yet until we've got a final product.
    let is_rlib = matches!(sess_crate_types, [CrateType::Rlib]);

    match sess_lto {
        Lto::ThinLocal if !linker_does_lto => ComputedLtoType::Thin,
        Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin,
        Lto::Fat if !is_rlib => ComputedLtoType::Fat,
        _ => ComputedLtoType::No,
    }
}

fn execute_optimize_work_item<B: WriteBackendMethods>(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: SharedEmitter,
    mut module: ModuleCodegen<B::Module>,
) -> WorkItemResult<B> {
    let _timer = prof.generic_activity_with_arg("codegen_module_optimize", &*module.name);

    B::optimize(cgcx, prof, &shared_emitter, &mut module, &cgcx.module_config);

    // After we've done the initial round of optimizations we need to
    // decide whether to synchronously codegen this module or ship it
    // back to the coordinator thread for further LTO processing (which
    // has to wait for all the initial modules to be optimized).

    let lto_type =
        compute_per_cgu_lto_type(&cgcx.lto, cgcx.use_linker_plugin_lto, &cgcx.crate_types);

    // If we're doing some form of incremental LTO then we need to be sure to
    // save our module to disk first.
    let bitcode = if cgcx.module_config.emit_pre_lto_bc {
        let filename = pre_lto_bitcode_filename(&module.name);
        cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename))
    } else {
        None
    };

    match lto_type {
        ComputedLtoType::No => {
            let module = B::codegen(cgcx, &prof, &shared_emitter, module, &cgcx.module_config);
            WorkItemResult::Finished(module)
        }
        ComputedLtoType::Thin => {
            let thin_buffer = B::serialize_module(module.module_llvm, true);
            if let Some(path) = bitcode {
                fs::write(&path, thin_buffer.data()).unwrap_or_else(|e| {
                    panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
                });
            }
            WorkItemResult::NeedsThinLto(module.name, thin_buffer)
        }
        ComputedLtoType::Fat => match bitcode {
            Some(path) => {
                let buffer = B::serialize_module(module.module_llvm, false);
                fs::write(&path, buffer.data()).unwrap_or_else(|e| {
                    panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
                });
                WorkItemResult::NeedsFatLto(FatLtoInput::Serialized {
                    name: module.name,
                    bitcode_path: path,
                })
            }
            None => WorkItemResult::NeedsFatLto(FatLtoInput::InMemory(module)),
        },
    }
}

fn execute_copy_from_cache_work_item(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: SharedEmitter,
    module: CachedModuleCodegen,
) -> CompiledModule {
    let _timer =
        prof.generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*module.name);

    let dcx = DiagCtxt::new(Box::new(shared_emitter));
    let dcx = dcx.handle();

    let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();

    let mut links_from_incr_cache = Vec::new();

    let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
        let source_file = in_incr_comp_dir(incr_comp_session_dir, saved_path);
        debug!(
            "copying preexisting module `{}` from {:?} to {}",
            module.name,
            source_file,
            output_path.display()
        );
        match link_or_copy(&source_file, &output_path) {
            Ok(_) => {
                links_from_incr_cache.push(source_file);
                Some(output_path)
            }
            Err(error) => {
                dcx.emit_err(errors::CopyPathBuf { source_file, output_path, error });
                None
            }
        }
    };

    let dwarf_object =
        module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
            let dwarf_obj_out = cgcx
                .output_filenames
                .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, &module.name)
                .expect(
                    "saved dwarf object in work product but `split_dwarf_path` returned `None`",
                );
            load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file)
        });

    let mut load_from_incr_cache = |perform, output_type: OutputType| {
        if perform {
            let saved_file = module.source.saved_files.get(output_type.extension())?;
            let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name);
            load_from_incr_comp_dir(output_path, &saved_file)
        } else {
            None
        }
    };

    let module_config = &cgcx.module_config;
    let should_emit_obj = module_config.emit_obj != EmitObj::None;
    let assembly = load_from_incr_cache(module_config.emit_asm, OutputType::Assembly);
    let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly);
    let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode);
    let object = load_from_incr_cache(should_emit_obj, OutputType::Object);
    let global_asm_object =
        if should_emit_obj && let Some(saved_file) = module.source.saved_files.get("asm.o") {
            let output_path = cgcx.output_filenames.temp_path_ext_for_cgu("asm.o", &module.name);
            load_from_incr_comp_dir(output_path, &saved_file)
        } else {
            None
        };
    if should_emit_obj && object.is_none() {
        dcx.emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
    }

    CompiledModule {
        links_from_incr_cache,
        kind: ModuleKind::Regular,
        name: module.name,
        object,
        global_asm_object,
        dwarf_object,
        bytecode,
        assembly,
        llvm_ir,
    }
}

fn do_fat_lto<B: WriteBackendMethods>(
    sess: &Session,
    cgcx: &CodegenContext,
    shared_emitter: SharedEmitter,
    tm_factory: TargetMachineFactoryFn<B>,
    exported_symbols_for_lto: &[String],
    each_linked_rlib_for_lto: &[PathBuf],
    needs_fat_lto: Vec<FatLtoInput<B>>,
) -> CompiledModule {
    let _timer = sess.prof.verbose_generic_activity("LLVM_fatlto");

    let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
    let dcx = dcx.handle();

    check_lto_allowed(&cgcx, dcx);

    B::optimize_and_codegen_fat_lto(
        sess,
        cgcx,
        &shared_emitter,
        tm_factory,
        exported_symbols_for_lto,
        each_linked_rlib_for_lto,
        needs_fat_lto,
    )
}

fn do_thin_lto<B: WriteBackendMethods>(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: SharedEmitter,
    tm_factory: TargetMachineFactoryFn<B>,
    exported_symbols_for_lto: &[String],
    each_linked_rlib_for_lto: &[PathBuf],
    needs_thin_lto: Vec<ThinLtoInput<B>>,
) -> Vec<CompiledModule> {
    let _timer = prof.verbose_generic_activity("LLVM_thinlto");

    let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
    let dcx = dcx.handle();

    check_lto_allowed(&cgcx, dcx);

    let (coordinator_send, coordinator_receive) = channel();

    // First up, convert our jobserver into a helper thread so we can use normal
    // mpsc channels to manage our messages and such.
    // After we've requested tokens then we'll, when we can,
    // get tokens on `coordinator_receive` which will
    // get managed in the main loop below.
    let coordinator_send2 = coordinator_send.clone();
    let helper = jobserver::client()
        .into_helper_thread(move |token| {
            drop(coordinator_send2.send(ThinLtoMessage::Token(token)));
        })
        .expect("failed to spawn helper thread");

    let mut work_items = vec![];

    // We have LTO work to do. Perform the serial work here of
    // figuring out what we're going to LTO and then push a
    // bunch of work items onto our queue to do LTO. This all
    // happens on the coordinator thread but it's very quick so
    // we don't worry about tokens.
    for (work, cost) in generate_thin_lto_work::<B>(
        cgcx,
        prof,
        dcx,
        &exported_symbols_for_lto,
        &each_linked_rlib_for_lto,
        needs_thin_lto,
    ) {
        let insertion_index =
            work_items.binary_search_by_key(&cost, |&(_, cost)| cost).unwrap_or_else(|e| e);
        work_items.insert(insertion_index, (work, cost));
        if cgcx.parallel {
            helper.request_token();
        }
    }

    let mut codegen_aborted = None;

    // These are the Jobserver Tokens we currently hold. Does not include
    // the implicit Token the compiler process owns no matter what.
    let mut tokens = vec![];

    // Amount of tokens that are used (including the implicit token).
    let mut used_token_count = 0;

    let mut compiled_modules = vec![];

    // Run the message loop while there's still anything that needs message
    // processing. Note that as soon as codegen is aborted we simply want to
    // wait for all existing work to finish, so many of the conditions here
    // only apply if codegen hasn't been aborted as they represent pending
    // work to be done.
    loop {
        if codegen_aborted.is_none() {
            if used_token_count == 0 && work_items.is_empty() {
                // All codegen work is done.
                break;
            }

            // Spin up what work we can, only doing this while we've got available
            // parallelism slots and work left to spawn.
            while used_token_count < tokens.len() + 1
                && let Some((item, _)) = work_items.pop()
            {
                spawn_thin_lto_work(
                    &cgcx,
                    prof,
                    shared_emitter.clone(),
                    Arc::clone(&tm_factory),
                    coordinator_send.clone(),
                    item,
                );
                used_token_count += 1;
            }
        } else {
            // Don't queue up any more work if codegen was aborted, we're
            // just waiting for our existing children to finish.
            if used_token_count == 0 {
                break;
            }
        }

        // Relinquish accidentally acquired extra tokens. Subtract 1 for the implicit token.
        tokens.truncate(used_token_count.saturating_sub(1));

        match coordinator_receive.recv().unwrap() {
            // Save the token locally and the next turn of the loop will use
            // this to spawn a new unit of work, or it may get dropped
            // immediately if we have no more work to spawn.
            ThinLtoMessage::Token(token) => match token {
                Ok(token) => {
                    tokens.push(token);
                }
                Err(e) => {
                    let msg = &format!("failed to acquire jobserver token: {e}");
                    shared_emitter.fatal(msg);
                    codegen_aborted = Some(FatalError);
                }
            },

            ThinLtoMessage::WorkItem { result } => {
                // If a thread exits successfully then we drop a token associated
                // with that worker and update our `used_token_count` count.
                // We may later re-acquire a token to continue running more work.
                // We may also not actually drop a token here if the worker was
                // running with an "ephemeral token".
                used_token_count -= 1;

                match result {
                    Ok(compiled_module) => compiled_modules.push(compiled_module),
                    Err(Some(WorkerFatalError)) => {
                        // Like `CodegenAborted`, wait for remaining work to finish.
                        codegen_aborted = Some(FatalError);
                    }
                    Err(None) => {
                        // If the thread failed that means it panicked, so
                        // we abort immediately.
                        bug!("worker thread panicked");
                    }
                }
            }
        }
    }

    if let Some(codegen_aborted) = codegen_aborted {
        codegen_aborted.raise();
    }

    compiled_modules
}

/// Messages sent to the coordinator.
pub(crate) enum Message<B: WriteBackendMethods> {
    /// A jobserver token has become available. Sent from the jobserver helper
    /// thread.
    Token(io::Result<Acquired>),

    /// The backend has finished processing a work item for a codegen unit.
    /// Sent from a backend worker thread.
    WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>> },

    /// The frontend has finished generating something (backend IR or a
    /// post-LTO artifact) for a codegen unit, and it should be passed to the
    /// backend. Sent from the main thread.
    CodegenDone { llvm_work_item: WorkItem<B>, cost: u64 },

    /// Similar to `CodegenDone`, but for reusing a pre-LTO artifact
    /// Sent from the main thread.
    AddImportOnlyModule { bitcode_path: PathBuf, work_product: WorkProduct },

    /// The frontend has finished generating everything for all codegen units.
    /// Sent from the main thread.
    CodegenComplete,

    /// Some normal-ish compiler error occurred, and codegen should be wound
    /// down. Sent from the main thread.
    CodegenAborted,
}

/// Messages sent to the coordinator.
pub(crate) enum ThinLtoMessage {
    /// A jobserver token has become available. Sent from the jobserver helper
    /// thread.
    Token(io::Result<Acquired>),

    /// The backend has finished processing a work item for a codegen unit.
    /// Sent from a backend worker thread.
    WorkItem { result: Result<CompiledModule, Option<WorkerFatalError>> },
}

/// A message sent from the coordinator thread to the main thread telling it to
/// process another codegen unit.
pub struct CguMessage;

// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which
// can be used to send diagnostics from codegen threads to the main thread.
// It's missing the following fields from `rustc_errors::DiagInner`.
// - `span`: it doesn't impl `Send`.
// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen
//   diagnostics.
// - `sort_span`: it doesn't impl `Send`.
// - `is_lint`: lints aren't relevant during codegen.
// - `emitted_at`: not used for codegen diagnostics.
struct Diagnostic {
    span: Vec<SpanData>,
    level: Level,
    messages: Vec<(DiagMessage, Style)>,
    code: Option<ErrCode>,
    children: Vec<Subdiagnostic>,
    args: DiagArgMap,
}

// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's
// missing the following fields from `rustc_errors::Subdiag`.
// - `span`: it doesn't impl `Send`.
struct Subdiagnostic {
    level: Level,
    messages: Vec<(DiagMessage, Style)>,
}

#[derive(PartialEq, Clone, Copy, Debug)]
enum MainThreadState {
    /// Doing nothing.
    Idle,

    /// Doing codegen, i.e. MIR-to-LLVM-IR conversion.
    Codegenning,

    /// Idle, but lending the compiler process's Token to an LLVM thread so it can do useful work.
    Lending,
}

fn start_executing_work<B: WriteBackendMethods>(
    backend: B,
    tcx: TyCtxt<'_>,
    shared_emitter: SharedEmitter,
    codegen_worker_send: Sender<CguMessage>,
    coordinator_receive: Receiver<Message<B>>,
    regular_config: Arc<ModuleConfig>,
    allocator_config: Arc<ModuleConfig>,
    mut allocator_module: Option<ModuleCodegen<B::Module>>,
    coordinator_send: Sender<Message<B>>,
) -> thread::JoinHandle<Result<MaybeLtoModules<B>, ()>> {
    let sess = tcx.sess;
    let prof = sess.prof.clone();

    // Compute the set of symbols we need to retain when doing thin local LTO (if we need to)
    let exported_symbols_for_lto =
        if sess.lto() == Lto::ThinLocal { lto::exported_symbols_for_lto(tcx, &[]) } else { vec![] };

    // First up, convert our jobserver into a helper thread so we can use normal
    // mpsc channels to manage our messages and such.
    // After we've requested tokens then we'll, when we can,
    // get tokens on `coordinator_receive` which will
    // get managed in the main loop below.
    let coordinator_send2 = coordinator_send.clone();
    let helper = jobserver::client()
        .into_helper_thread(move |token| {
            drop(coordinator_send2.send(Message::Token::<B>(token)));
        })
        .expect("failed to spawn helper thread");

    let opt_level = tcx.backend_optimization_level(());
    let backend_features = tcx.global_backend_features(()).clone();
    let tm_factory = backend.target_machine_factory(tcx.sess, opt_level, &backend_features);

    let remark_dir = if let Some(ref dir) = sess.opts.unstable_opts.remark_dir {
        let result = fs::create_dir_all(dir).and_then(|_| dir.canonicalize());
        match result {
            Ok(dir) => Some(dir),
            Err(error) => sess.dcx().emit_fatal(ErrorCreatingRemarkDir { error }),
        }
    } else {
        None
    };

    let cgcx = CodegenContext {
        crate_types: tcx.crate_types().to_vec(),
        lto: sess.lto(),
        use_linker_plugin_lto: sess.opts.cg.linker_plugin_lto.enabled(),
        dylib_lto: sess.opts.unstable_opts.dylib_lto,
        prefer_dynamic: sess.opts.cg.prefer_dynamic,
        fewer_names: sess.fewer_names(),
        save_temps: sess.opts.cg.save_temps,
        time_trace: sess.opts.unstable_opts.llvm_time_trace,
        remark: sess.opts.cg.remark.clone(),
        remark_dir,
        incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
        output_filenames: Arc::clone(tcx.output_filenames(())),
        module_config: regular_config,
        opt_level,
        backend_features,
        msvc_imps_needed: msvc_imps_needed(tcx),
        is_pe_coff: tcx.sess.target.is_like_windows,
        target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(),
        target_arch: tcx.sess.target.arch.to_string(),
        target_is_like_darwin: tcx.sess.target.is_like_darwin,
        target_is_like_aix: tcx.sess.target.is_like_aix,
        target_is_like_gpu: tcx.sess.target.is_like_gpu,
        split_debuginfo: tcx.sess.split_debuginfo(),
        split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
        parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
        pointer_size: tcx.data_layout.pointer_size(),
    };

    // This is the "main loop" of parallel work happening for parallel codegen.
    // It's here that we manage parallelism, schedule work, and work with
    // messages coming from clients.
    //
    // There are a few environmental pre-conditions that shape how the system
    // is set up:
    //
    // - Error reporting can only happen on the main thread because that's the
    //   only place where we have access to the compiler `Session`.
    // - LLVM work can be done on any thread.
    // - Codegen can only happen on the main thread.
    // - Each thread doing substantial work must be in possession of a `Token`
    //   from the `Jobserver`.
    // - The compiler process always holds one `Token`. Any additional `Tokens`
    //   have to be requested from the `Jobserver`.
    //
    // Error Reporting
    // ===============
    // The error reporting restriction is handled separately from the rest: We
    // set up a `SharedEmitter` that holds an open channel to the main thread.
    // When an error occurs on any thread, the shared emitter will send the
    // error message to the receiver main thread (`SharedEmitterMain`). The
    // main thread will periodically query this error message queue and emit
    // any error messages it has received. It might even abort compilation if
    // it has received a fatal error. In this case we rely on all other threads
    // being torn down automatically with the main thread.
    // Since the main thread will often be busy doing codegen work, error
    // reporting will be somewhat delayed, since the message queue can only be
    // checked in between two work packages.
    //
    // Work Processing Infrastructure
    // ==============================
    // The work processing infrastructure knows three major actors:
    //
    // - the coordinator thread,
    // - the main thread, and
    // - LLVM worker threads
    //
    // The coordinator thread is running a message loop. It instructs the main
    // thread about what work to do when, and it will spawn off LLVM worker
    // threads as open LLVM WorkItems become available.
    //
    // The job of the main thread is to codegen CGUs into LLVM work packages
    // (since the main thread is the only thread that can do this). The main
    // thread will block until it receives a message from the coordinator, upon
    // which it will codegen one CGU, send it to the coordinator and block
    // again. This way the coordinator can control what the main thread is
    // doing.
    //
    // The coordinator keeps a queue of LLVM WorkItems, and when a `Token` is
    // available, it will spawn off a new LLVM worker thread and let it process
    // a WorkItem. When a LLVM worker thread is done with its WorkItem,
    // it will just shut down, which also frees all resources associated with
    // the given LLVM module, and sends a message to the coordinator that the
    // WorkItem has been completed.
    //
    // Work Scheduling
    // ===============
    // The scheduler's goal is to minimize the time it takes to complete all
    // work there is, however, we also want to keep memory consumption low
    // if possible. These two goals are at odds with each other: If memory
    // consumption were not an issue, we could just let the main thread produce
    // LLVM WorkItems at full speed, assuring maximal utilization of
    // Tokens/LLVM worker threads. However, since codegen is usually faster
    // than LLVM processing, the queue of LLVM WorkItems would fill up and each
    // WorkItem potentially holds on to a substantial amount of memory.
    //
    // So the actual goal is to always produce just enough LLVM WorkItems as
    // not to starve our LLVM worker threads. That means, once we have enough
    // WorkItems in our queue, we can block the main thread, so it does not
    // produce more until we need them.
    //
    // Doing LLVM Work on the Main Thread
    // ----------------------------------
    // Since the main thread owns the compiler process's implicit `Token`, it is
    // wasteful to keep it blocked without doing any work. Therefore, what we do
    // in this case is: We spawn off an additional LLVM worker thread that helps
    // reduce the queue. The work it is doing corresponds to the implicit
    // `Token`. The coordinator will mark the main thread as being busy with
    // LLVM work. (The actual work happens on another OS thread but we just care
    // about `Tokens`, not actual threads).
    //
    // When any LLVM worker thread finishes while the main thread is marked as
    // "busy with LLVM work", we can do a little switcheroo: We give the Token
    // of the just finished thread to the LLVM worker thread that is working on
    // behalf of the main thread's implicit Token, thus freeing up the main
    // thread again. The coordinator can then again decide what the main thread
    // should do. This allows the coordinator to make decisions at more points
    // in time.
    //
    // Striking a Balance between Throughput and Memory Consumption
    // ------------------------------------------------------------
    // Since our two goals, (1) use as many Tokens as possible and (2) keep
    // memory consumption as low as possible, are in conflict with each other,
    // we have to find a trade off between them. Right now, the goal is to keep
    // all workers busy, which means that no worker should find the queue empty
    // when it is ready to start.
    // How do we do achieve this? Good question :) We actually never know how
    // many `Tokens` are potentially available so it's hard to say how much to
    // fill up the queue before switching the main thread to LLVM work. Also we
    // currently don't have a means to estimate how long a running LLVM worker
    // will still be busy with it's current WorkItem. However, we know the
    // maximal count of available Tokens that makes sense (=the number of CPU
    // cores), so we can take a conservative guess. The heuristic we use here
    // is implemented in the `queue_full_enough()` function.
    //
    // Some Background on Jobservers
    // -----------------------------
    // It's worth also touching on the management of parallelism here. We don't
    // want to just spawn a thread per work item because while that's optimal
    // parallelism it may overload a system with too many threads or violate our
    // configuration for the maximum amount of cpu to use for this process. To
    // manage this we use the `jobserver` crate.
    //
    // Job servers are an artifact of GNU make and are used to manage
    // parallelism between processes. A jobserver is a glorified IPC semaphore
    // basically. Whenever we want to run some work we acquire the semaphore,
    // and whenever we're done with that work we release the semaphore. In this
    // manner we can ensure that the maximum number of parallel workers is
    // capped at any one point in time.
    //
    // LTO and the coordinator thread
    // ------------------------------
    //
    // The final job the coordinator thread is responsible for is managing LTO
    // and how that works. When LTO is requested what we'll do is collect all
    // optimized LLVM modules into a local vector on the coordinator. Once all
    // modules have been codegened and optimized we hand this to the `lto`
    // module for further optimization. The `lto` module will return back a list
    // of more modules to work on, which the coordinator will continue to spawn
    // work for.
    //
    // Each LLVM module is automatically sent back to the coordinator for LTO if
    // necessary. There's already optimizations in place to avoid sending work
    // back to the coordinator if LTO isn't requested.
    let f = move || {
        let _profiler = if cgcx.time_trace { B::thread_profiler() } else { Box::new(()) };

        // This is where we collect codegen units that have gone all the way
        // through codegen and LLVM.
        let mut compiled_modules = vec![];
        let mut needs_fat_lto = Vec::new();
        let mut needs_thin_lto = Vec::new();
        let mut lto_import_only_modules = Vec::new();

        /// Possible state transitions:
        /// - Ongoing -> Completed
        /// - Ongoing -> Aborted
        /// - Completed -> Aborted
        #[derive(Debug, PartialEq)]
        enum CodegenState {
            Ongoing,
            Completed,
            Aborted,
        }
        use CodegenState::*;
        let mut codegen_state = Ongoing;

        // This is the queue of LLVM work items that still need processing.
        let mut work_items = Vec::<(WorkItem<B>, u64)>::new();

        // This are the Jobserver Tokens we currently hold. Does not include
        // the implicit Token the compiler process owns no matter what.
        let mut tokens = Vec::new();

        let mut main_thread_state = MainThreadState::Idle;

        // How many LLVM worker threads are running while holding a Token. This
        // *excludes* any that the main thread is lending a Token to.
        let mut running_with_own_token = 0;

        // How many LLVM worker threads are running in total. This *includes*
        // any that the main thread is lending a Token to.
        let running_with_any_token = |main_thread_state, running_with_own_token| {
            running_with_own_token
                + if main_thread_state == MainThreadState::Lending { 1 } else { 0 }
        };

        let mut llvm_start_time: Option<VerboseTimingGuard<'_>> = None;

        if let Some(allocator_module) = &mut allocator_module {
            B::optimize(&cgcx, &prof, &shared_emitter, allocator_module, &allocator_config);
        }

        // Run the message loop while there's still anything that needs message
        // processing. Note that as soon as codegen is aborted we simply want to
        // wait for all existing work to finish, so many of the conditions here
        // only apply if codegen hasn't been aborted as they represent pending
        // work to be done.
        loop {
            // While there are still CGUs to be codegened, the coordinator has
            // to decide how to utilize the compiler processes implicit Token:
            // For codegenning more CGU or for running them through LLVM.
            if codegen_state == Ongoing {
                if main_thread_state == MainThreadState::Idle {
                    // Compute the number of workers that will be running once we've taken as many
                    // items from the work queue as we can, plus one for the main thread. It's not
                    // critically important that we use this instead of just
                    // `running_with_own_token`, but it prevents the `queue_full_enough` heuristic
                    // from fluctuating just because a worker finished up and we decreased the
                    // `running_with_own_token` count, even though we're just going to increase it
                    // right after this when we put a new worker to work.
                    let extra_tokens = tokens.len().checked_sub(running_with_own_token).unwrap();
                    let additional_running = std::cmp::min(extra_tokens, work_items.len());
                    let anticipated_running = running_with_own_token + additional_running + 1;

                    if !queue_full_enough(work_items.len(), anticipated_running) {
                        // The queue is not full enough, process more codegen units:
                        if codegen_worker_send.send(CguMessage).is_err() {
                            panic!("Could not send CguMessage to main thread")
                        }
                        main_thread_state = MainThreadState::Codegenning;
                    } else {
                        // The queue is full enough to not let the worker
                        // threads starve. Use the implicit Token to do some
                        // LLVM work too.
                        let (item, _) =
                            work_items.pop().expect("queue empty - queue_full_enough() broken?");
                        main_thread_state = MainThreadState::Lending;
                        spawn_work(
                            &cgcx,
                            &prof,
                            shared_emitter.clone(),
                            coordinator_send.clone(),
                            &mut llvm_start_time,
                            item,
                        );
                    }
                }
            } else if codegen_state == Completed {
                if running_with_any_token(main_thread_state, running_with_own_token) == 0
                    && work_items.is_empty()
                {
                    // All codegen work is done.
                    break;
                }

                // In this branch, we know that everything has been codegened,
                // so it's just a matter of determining whether the implicit
                // Token is free to use for LLVM work.
                match main_thread_state {
                    MainThreadState::Idle => {
                        if let Some((item, _)) = work_items.pop() {
                            main_thread_state = MainThreadState::Lending;
                            spawn_work(
                                &cgcx,
                                &prof,
                                shared_emitter.clone(),
                                coordinator_send.clone(),
                                &mut llvm_start_time,
                                item,
                            );
                        } else {
                            // There is no unstarted work, so let the main thread
                            // take over for a running worker. Otherwise the
                            // implicit token would just go to waste.
                            // We reduce the `running` counter by one. The
                            // `tokens.truncate()` below will take care of
                            // giving the Token back.
                            assert!(running_with_own_token > 0);
                            running_with_own_token -= 1;
                            main_thread_state = MainThreadState::Lending;
                        }
                    }
                    MainThreadState::Codegenning => bug!(
                        "codegen worker should not be codegenning after \
                              codegen was already completed"
                    ),
                    MainThreadState::Lending => {
                        // Already making good use of that token
                    }
                }
            } else {
                // Don't queue up any more work if codegen was aborted, we're
                // just waiting for our existing children to finish.
                assert!(codegen_state == Aborted);
                if running_with_any_token(main_thread_state, running_with_own_token) == 0 {
                    break;
                }
            }

            // Spin up what work we can, only doing this while we've got available
            // parallelism slots and work left to spawn.
            if codegen_state != Aborted {
                while running_with_own_token < tokens.len()
                    && let Some((item, _)) = work_items.pop()
                {
                    spawn_work(
                        &cgcx,
                        &prof,
                        shared_emitter.clone(),
                        coordinator_send.clone(),
                        &mut llvm_start_time,
                        item,
                    );
                    running_with_own_token += 1;
                }
            }

            // Relinquish accidentally acquired extra tokens.
            tokens.truncate(running_with_own_token);

            match coordinator_receive.recv().unwrap() {
                // Save the token locally and the next turn of the loop will use
                // this to spawn a new unit of work, or it may get dropped
                // immediately if we have no more work to spawn.
                Message::Token(token) => {
                    match token {
                        Ok(token) => {
                            tokens.push(token);

                            if main_thread_state == MainThreadState::Lending {
                                // If the main thread token is used for LLVM work
                                // at the moment, we turn that thread into a regular
                                // LLVM worker thread, so the main thread is free
                                // to react to codegen demand.
                                main_thread_state = MainThreadState::Idle;
                                running_with_own_token += 1;
                            }
                        }
                        Err(e) => {
                            let msg = &format!("failed to acquire jobserver token: {e}");
                            shared_emitter.fatal(msg);
                            codegen_state = Aborted;
                        }
                    }
                }

                Message::CodegenDone { llvm_work_item, cost } => {
                    // We keep the queue sorted by estimated processing cost,
                    // so that more expensive items are processed earlier. This
                    // is good for throughput as it gives the main thread more
                    // time to fill up the queue and it avoids scheduling
                    // expensive items to the end.
                    // Note, however, that this is not ideal for memory
                    // consumption, as LLVM module sizes are not evenly
                    // distributed.
                    let insertion_index = work_items.binary_search_by_key(&cost, |&(_, cost)| cost);
                    let insertion_index = match insertion_index {
                        Ok(idx) | Err(idx) => idx,
                    };
                    work_items.insert(insertion_index, (llvm_work_item, cost));

                    if cgcx.parallel {
                        helper.request_token();
                    }
                    assert_eq!(main_thread_state, MainThreadState::Codegenning);
                    main_thread_state = MainThreadState::Idle;
                }

                Message::CodegenComplete => {
                    if codegen_state != Aborted {
                        codegen_state = Completed;
                    }
                    assert_eq!(main_thread_state, MainThreadState::Codegenning);
                    main_thread_state = MainThreadState::Idle;
                }

                // If codegen is aborted that means translation was aborted due
                // to some normal-ish compiler error. In this situation we want
                // to exit as soon as possible, but we want to make sure all
                // existing work has finished. Flag codegen as being done, and
                // then conditions above will ensure no more work is spawned but
                // we'll keep executing this loop until `running_with_own_token`
                // hits 0.
                Message::CodegenAborted => {
                    codegen_state = Aborted;
                }

                Message::WorkItem { result } => {
                    // If a thread exits successfully then we drop a token associated
                    // with that worker and update our `running_with_own_token` count.
                    // We may later re-acquire a token to continue running more work.
                    // We may also not actually drop a token here if the worker was
                    // running with an "ephemeral token".
                    if main_thread_state == MainThreadState::Lending {
                        main_thread_state = MainThreadState::Idle;
                    } else {
                        running_with_own_token -= 1;
                    }

                    match result {
                        Ok(WorkItemResult::Finished(compiled_module)) => {
                            compiled_modules.push(compiled_module);
                        }
                        Ok(WorkItemResult::NeedsFatLto(fat_lto_input)) => {
                            assert!(needs_thin_lto.is_empty());
                            needs_fat_lto.push(fat_lto_input);
                        }
                        Ok(WorkItemResult::NeedsThinLto(name, thin_buffer)) => {
                            assert!(needs_fat_lto.is_empty());
                            needs_thin_lto.push(ThinLtoInput::Red {
                                name,
                                buffer: SerializedModule::Local(thin_buffer),
                            });
                        }
                        Err(Some(WorkerFatalError)) => {
                            // Like `CodegenAborted`, wait for remaining work to finish.
                            codegen_state = Aborted;
                        }
                        Err(None) => {
                            // If the thread failed that means it panicked, so
                            // we abort immediately.
                            bug!("worker thread panicked");
                        }
                    }
                }

                Message::AddImportOnlyModule { bitcode_path, work_product } => {
                    assert_eq!(codegen_state, Ongoing);
                    assert_eq!(main_thread_state, MainThreadState::Codegenning);
                    lto_import_only_modules.push((bitcode_path, work_product));
                    main_thread_state = MainThreadState::Idle;
                }
            }
        }

        // Drop to print timings
        drop(llvm_start_time);

        if codegen_state == Aborted {
            return Err(());
        }

        drop(codegen_state);
        drop(tokens);
        drop(helper);
        assert!(work_items.is_empty());

        if !needs_fat_lto.is_empty() {
            assert!(compiled_modules.is_empty());
            assert!(needs_thin_lto.is_empty());

            if let Some(allocator_module) = allocator_module.take() {
                needs_fat_lto.push(FatLtoInput::InMemory(allocator_module));
            }

            for (bitcode_path, wp) in lto_import_only_modules {
                needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, bitcode_path })
            }

            return Ok(MaybeLtoModules::FatLto { cgcx, needs_fat_lto });
        } else if !needs_thin_lto.is_empty() || !lto_import_only_modules.is_empty() {
            assert!(compiled_modules.is_empty());
            assert!(needs_fat_lto.is_empty());

            for (bitcode_path, wp) in lto_import_only_modules {
                needs_thin_lto.push(ThinLtoInput::Green { wp, bitcode_path })
            }

            if cgcx.lto == Lto::ThinLocal {
                compiled_modules.extend(do_thin_lto::<B>(
                    &cgcx,
                    &prof,
                    shared_emitter.clone(),
                    tm_factory,
                    &exported_symbols_for_lto,
                    &[],
                    needs_thin_lto,
                ));
            } else {
                if let Some(allocator_module) = allocator_module.take() {
                    let thin_buffer = B::serialize_module(allocator_module.module_llvm, true);
                    needs_thin_lto.push(ThinLtoInput::Red {
                        name: allocator_module.name,
                        buffer: SerializedModule::Local(thin_buffer),
                    });
                }

                return Ok(MaybeLtoModules::ThinLto { cgcx, needs_thin_lto });
            }
        }

        Ok(MaybeLtoModules::NoLto(CompiledModules {
            modules: compiled_modules,
            allocator_module: allocator_module.map(|allocator_module| {
                B::codegen(&cgcx, &prof, &shared_emitter, allocator_module, &allocator_config)
            }),
        }))
    };
    return std::thread::Builder::new()
        .name("coordinator".to_owned())
        .spawn(f)
        .expect("failed to spawn coordinator thread");

    // A heuristic that determines if we have enough LLVM WorkItems in the
    // queue so that the main thread can do LLVM work instead of codegen
    fn queue_full_enough(items_in_queue: usize, workers_running: usize) -> bool {
        // This heuristic scales ahead-of-time codegen according to available
        // concurrency, as measured by `workers_running`. The idea is that the
        // more concurrency we have available, the more demand there will be for
        // work items, and the fuller the queue should be kept to meet demand.
        // An important property of this approach is that we codegen ahead of
        // time only as much as necessary, so as to keep fewer LLVM modules in
        // memory at once, thereby reducing memory consumption.
        //
        // When the number of workers running is less than the max concurrency
        // available to us, this heuristic can cause us to instruct the main
        // thread to work on an LLVM item (that is, tell it to "LLVM") instead
        // of codegen, even though it seems like it *should* be codegenning so
        // that we can create more work items and spawn more LLVM workers.
        //
        // But this is not a problem. When the main thread is told to LLVM,
        // according to this heuristic and how work is scheduled, there is
        // always at least one item in the queue, and therefore at least one
        // pending jobserver token request. If there *is* more concurrency
        // available, we will immediately receive a token, which will upgrade
        // the main thread's LLVM worker to a real one (conceptually), and free
        // up the main thread to codegen if necessary. On the other hand, if
        // there isn't more concurrency, then the main thread working on an LLVM
        // item is appropriate, as long as the queue is full enough for demand.
        //
        // Speaking of which, how full should we keep the queue? Probably less
        // full than you'd think. A lot has to go wrong for the queue not to be
        // full enough and for that to have a negative effect on compile times.
        //
        // Workers are unlikely to finish at exactly the same time, so when one
        // finishes and takes another work item off the queue, we often have
        // ample time to codegen at that point before the next worker finishes.
        // But suppose that codegen takes so long that the workers exhaust the
        // queue, and we have one or more workers that have nothing to work on.
        // Well, it might not be so bad. Of all the LLVM modules we create and
        // optimize, one has to finish last. It's not necessarily the case that
        // by losing some concurrency for a moment, we delay the point at which
        // that last LLVM module is finished and the rest of compilation can
        // proceed. Also, when we can't take advantage of some concurrency, we
        // give tokens back to the job server. That enables some other rustc to
        // potentially make use of the available concurrency. That could even
        // *decrease* overall compile time if we're lucky. But yes, if no other
        // rustc can make use of the concurrency, then we've squandered it.
        //
        // However, keeping the queue full is also beneficial when we have a
        // surge in available concurrency. Then items can be taken from the
        // queue immediately, without having to wait for codegen.
        //
        // So, the heuristic below tries to keep one item in the queue for every
        // four running workers. Based on limited benchmarking, this appears to
        // be more than sufficient to avoid increasing compilation times.
        let quarter_of_workers = workers_running - 3 * workers_running / 4;
        items_in_queue > 0 && items_in_queue >= quarter_of_workers
    }
}

/// `FatalError` is explicitly not `Send`.
#[must_use]
pub(crate) struct WorkerFatalError;

fn spawn_work<'a, B: WriteBackendMethods>(
    cgcx: &CodegenContext,
    prof: &'a SelfProfilerRef,
    shared_emitter: SharedEmitter,
    coordinator_send: Sender<Message<B>>,
    llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
    work: WorkItem<B>,
) {
    if llvm_start_time.is_none() {
        *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes"));
    }

    let cgcx = cgcx.clone();
    let prof = prof.clone();

    let name = work.short_description();
    let f = move || {
        let _profiler = if cgcx.time_trace { B::thread_profiler() } else { Box::new(()) };

        let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work {
            WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, &prof, shared_emitter, m),
            WorkItem::CopyPostLtoArtifacts(m) => WorkItemResult::Finished(
                execute_copy_from_cache_work_item(&cgcx, &prof, shared_emitter, m),
            ),
        }));

        let msg = match result {
            Ok(result) => Message::WorkItem::<B> { result: Ok(result) },

            // We ignore any `FatalError` coming out of `execute_work_item`, as a
            // diagnostic was already sent off to the main thread - just surface
            // that there was an error in this worker.
            Err(err) if err.is::<FatalErrorMarker>() => {
                Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)) }
            }

            Err(_) => Message::WorkItem::<B> { result: Err(None) },
        };
        drop(coordinator_send.send(msg));
    };
    std::thread::Builder::new().name(name).spawn(f).expect("failed to spawn work thread");
}

fn spawn_thin_lto_work<B: WriteBackendMethods>(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: SharedEmitter,
    tm_factory: TargetMachineFactoryFn<B>,
    coordinator_send: Sender<ThinLtoMessage>,
    work: ThinLtoWorkItem<B>,
) {
    let cgcx = cgcx.clone();
    let prof = prof.clone();

    let name = work.short_description();
    let f = move || {
        let _profiler = if cgcx.time_trace { B::thread_profiler() } else { Box::new(()) };

        let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work {
            ThinLtoWorkItem::CopyPostLtoArtifacts(m) => {
                execute_copy_from_cache_work_item(&cgcx, &prof, shared_emitter, m)
            }
            ThinLtoWorkItem::ThinLto(m) => {
                let _timer = prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
                B::optimize_and_codegen_thin(&cgcx, &prof, &shared_emitter, tm_factory, m)
            }
        }));

        let msg = match result {
            Ok(result) => ThinLtoMessage::WorkItem { result: Ok(result) },

            // We ignore any `FatalError` coming out of `execute_work_item`, as a
            // diagnostic was already sent off to the main thread - just surface
            // that there was an error in this worker.
            Err(err) if err.is::<FatalErrorMarker>() => {
                ThinLtoMessage::WorkItem { result: Err(Some(WorkerFatalError)) }
            }

            Err(_) => ThinLtoMessage::WorkItem { result: Err(None) },
        };
        drop(coordinator_send.send(msg));
    };
    std::thread::Builder::new().name(name).spawn(f).expect("failed to spawn work thread");
}

enum SharedEmitterMessage {
    Diagnostic(Diagnostic),
    InlineAsmError(InlineAsmError),
    Fatal(String),
}

pub struct InlineAsmError {
    pub span: SpanData,
    pub msg: String,
    pub level: Level,
    pub source: Option<(String, Vec<InnerSpan>)>,
}

#[derive(Clone)]
pub struct SharedEmitter {
    sender: Sender<SharedEmitterMessage>,
}

pub struct SharedEmitterMain {
    receiver: Receiver<SharedEmitterMessage>,
}

impl SharedEmitter {
    fn new() -> (SharedEmitter, SharedEmitterMain) {
        let (sender, receiver) = channel();

        (SharedEmitter { sender }, SharedEmitterMain { receiver })
    }

    pub fn inline_asm_error(&self, err: InlineAsmError) {
        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(err)));
    }

    fn fatal(&self, msg: &str) {
        drop(self.sender.send(SharedEmitterMessage::Fatal(msg.to_string())));
    }
}

impl Emitter for SharedEmitter {
    fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) {
        // Check that we aren't missing anything interesting when converting to
        // the cut-down local `DiagInner`.
        assert!(!diag.span.has_span_labels());
        assert_eq!(diag.suggestions, Suggestions::Enabled(vec![]));
        assert_eq!(diag.sort_span, rustc_span::DUMMY_SP);
        assert_eq!(diag.is_lint, None);
        // No sensible check for `diag.emitted_at`.

        let args = mem::take(&mut diag.args);
        drop(
            self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
                span: diag.span.primary_spans().iter().map(|span| span.data()).collect::<Vec<_>>(),
                level: diag.level(),
                messages: diag.messages,
                code: diag.code,
                children: diag
                    .children
                    .into_iter()
                    .map(|child| Subdiagnostic { level: child.level, messages: child.messages })
                    .collect(),
                args,
            })),
        );
    }

    fn source_map(&self) -> Option<&SourceMap> {
        None
    }
}

impl SharedEmitterMain {
    fn check(&self, sess: &Session, blocking: bool) {
        loop {
            let message = if blocking {
                match self.receiver.recv() {
                    Ok(message) => Ok(message),
                    Err(_) => Err(()),
                }
            } else {
                match self.receiver.try_recv() {
                    Ok(message) => Ok(message),
                    Err(_) => Err(()),
                }
            };

            match message {
                Ok(SharedEmitterMessage::Diagnostic(diag)) => {
                    // The diagnostic has been received on the main thread.
                    // Convert it back to a full `Diagnostic` and emit.
                    let dcx = sess.dcx();
                    let mut d =
                        rustc_errors::DiagInner::new_with_messages(diag.level, diag.messages);
                    d.span = MultiSpan::from_spans(
                        diag.span.into_iter().map(|span| span.span()).collect(),
                    );
                    d.code = diag.code; // may be `None`, that's ok
                    d.children = diag
                        .children
                        .into_iter()
                        .map(|sub| rustc_errors::Subdiag {
                            level: sub.level,
                            messages: sub.messages,
                            span: MultiSpan::new(),
                        })
                        .collect();
                    d.args = diag.args;
                    dcx.emit_diagnostic(d);
                    sess.dcx().abort_if_errors();
                }
                Ok(SharedEmitterMessage::InlineAsmError(inner)) => {
                    assert_matches!(inner.level, Level::Error | Level::Warning | Level::Note);
                    let mut err = Diag::<()>::new(sess.dcx(), inner.level, inner.msg);
                    if !inner.span.is_dummy() {
                        err.span(inner.span.span());
                    }

                    // Point to the generated assembly if it is available.
                    if let Some((buffer, spans)) = inner.source {
                        let source = sess
                            .source_map()
                            .new_source_file(FileName::inline_asm_source_code(&buffer), buffer);
                        let spans: Vec<_> = spans
                            .iter()
                            .map(|sp| {
                                Span::with_root_ctxt(
                                    source.normalized_byte_pos(sp.start as u32),
                                    source.normalized_byte_pos(sp.end as u32),
                                )
                            })
                            .collect();
                        err.span_note(spans, "instantiated into assembly here");
                    }

                    err.emit();
                }
                Ok(SharedEmitterMessage::Fatal(msg)) => {
                    sess.dcx().fatal(msg);
                }
                Err(_) => {
                    break;
                }
            }
        }
    }
}

pub struct Coordinator<B: WriteBackendMethods> {
    sender: Sender<Message<B>>,
    future: Option<thread::JoinHandle<Result<MaybeLtoModules<B>, ()>>>,
    // Only used for the Message type.
    phantom: PhantomData<B>,
}

impl<B: WriteBackendMethods> Coordinator<B> {
    fn join(mut self) -> std::thread::Result<Result<MaybeLtoModules<B>, ()>> {
        self.future.take().unwrap().join()
    }
}

impl<B: WriteBackendMethods> Drop for Coordinator<B> {
    fn drop(&mut self) {
        if let Some(future) = self.future.take() {
            // If we haven't joined yet, signal to the coordinator that it should spawn no more
            // work, and wait for worker threads to finish.
            drop(self.sender.send(Message::CodegenAborted::<B>));
            drop(future.join());
        }
    }
}

pub struct OngoingCodegen<B: WriteBackendMethods> {
    backend: B,
    output_filenames: Arc<OutputFilenames>,
    // Field order below is intended to terminate the coordinator thread before two fields below
    // drop and prematurely close channels used by coordinator thread. See `Coordinator`'s
    // `Drop` implementation for more info.
    pub(crate) coordinator: Coordinator<B>,
    codegen_worker_receive: Receiver<CguMessage>,
    shared_emitter_main: SharedEmitterMain,
}

impl<B: WriteBackendMethods> OngoingCodegen<B> {
    pub fn join(self, sess: &Session, crate_info: &CrateInfo) -> (CompiledModules, WorkProductMap) {
        self.shared_emitter_main.check(sess, true);

        let maybe_lto_modules = sess.time("join_worker_thread", || match self.coordinator.join() {
            Ok(Ok(maybe_lto_modules)) => maybe_lto_modules,
            Ok(Err(())) => {
                sess.dcx().abort_if_errors();
                panic!("expected abort due to worker thread errors")
            }
            Err(_) => {
                bug!("panic during codegen/LLVM phase");
            }
        });

        sess.dcx().abort_if_errors();

        let (shared_emitter, shared_emitter_main) = SharedEmitter::new();

        // Catch fatal errors to ensure shared_emitter_main.check() can emit the actual diagnostics
        let compiled_modules = catch_fatal_errors(|| match maybe_lto_modules {
            MaybeLtoModules::NoLto(compiled_modules) => {
                drop(shared_emitter);
                compiled_modules
            }
            MaybeLtoModules::FatLto { cgcx, needs_fat_lto } => {
                let tm_factory = self.backend.target_machine_factory(
                    sess,
                    cgcx.opt_level,
                    &cgcx.backend_features,
                );

                CompiledModules {
                    modules: vec![do_fat_lto(
                        sess,
                        &cgcx,
                        shared_emitter,
                        tm_factory,
                        &crate_info.exported_symbols_for_lto,
                        &crate_info.each_linked_rlib_file_for_lto,
                        needs_fat_lto,
                    )],
                    allocator_module: None,
                }
            }
            MaybeLtoModules::ThinLto { cgcx, needs_thin_lto } => {
                let tm_factory = self.backend.target_machine_factory(
                    sess,
                    cgcx.opt_level,
                    &cgcx.backend_features,
                );

                CompiledModules {
                    modules: do_thin_lto::<B>(
                        &cgcx,
                        &sess.prof,
                        shared_emitter,
                        tm_factory,
                        &crate_info.exported_symbols_for_lto,
                        &crate_info.each_linked_rlib_file_for_lto,
                        needs_thin_lto,
                    ),
                    allocator_module: None,
                }
            }
        });

        shared_emitter_main.check(sess, true);

        sess.dcx().abort_if_errors();

        let mut compiled_modules =
            compiled_modules.expect("fatal error emitted but not sent to SharedEmitter");

        // Regardless of what order these modules completed in, report them to
        // the backend in the same order every time to ensure that we're handing
        // out deterministic results.
        compiled_modules.modules.sort_by(|a, b| a.name.cmp(&b.name));

        let work_products =
            copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules);
        produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames);

        (compiled_modules, work_products)
    }

    pub(crate) fn codegen_finished(&self, tcx: TyCtxt<'_>) {
        self.wait_for_signal_to_codegen_item();
        self.check_for_errors(tcx.sess);
        drop(self.coordinator.sender.send(Message::CodegenComplete::<B>));
    }

    pub(crate) fn check_for_errors(&self, sess: &Session) {
        self.shared_emitter_main.check(sess, false);
    }

    pub(crate) fn wait_for_signal_to_codegen_item(&self) {
        match self.codegen_worker_receive.recv() {
            Ok(CguMessage) => {
                // Ok to proceed.
            }
            Err(_) => {
                // One of the LLVM threads must have panicked, fall through so
                // error handling can be reached.
            }
        }
    }
}

pub(crate) fn submit_codegened_module_to_llvm<B: WriteBackendMethods>(
    coordinator: &Coordinator<B>,
    module: ModuleCodegen<B::Module>,
    cost: u64,
) {
    let llvm_work_item = WorkItem::Optimize(module);
    drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost }));
}

pub(crate) fn submit_post_lto_module_to_llvm<B: WriteBackendMethods>(
    coordinator: &Coordinator<B>,
    module: CachedModuleCodegen,
) {
    let llvm_work_item = WorkItem::CopyPostLtoArtifacts(module);
    drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost: 0 }));
}

pub(crate) fn submit_pre_lto_module_to_llvm<B: WriteBackendMethods>(
    tcx: TyCtxt<'_>,
    coordinator: &Coordinator<B>,
    module: CachedModuleCodegen,
) {
    let filename = pre_lto_bitcode_filename(&module.name);
    let bitcode_path = in_incr_comp_dir_sess(tcx.sess, &filename);
    // Schedule the module to be loaded
    drop(
        coordinator
            .sender
            .send(Message::AddImportOnlyModule::<B> { bitcode_path, work_product: module.source }),
    );
}

fn pre_lto_bitcode_filename(module_name: &str) -> String {
    format!("{module_name}.{PRE_LTO_BC_EXT}")
}

fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
    // This should never be true (because it's not supported). If it is true,
    // something is wrong with commandline arg validation.
    assert!(
        !(tcx.sess.opts.cg.linker_plugin_lto.enabled()
            && tcx.sess.target.is_like_windows
            && tcx.sess.opts.cg.prefer_dynamic)
    );

    // We need to generate _imp__ symbol if we are generating an rlib or we include one
    // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve
    // these, but it currently does not do so.
    let can_have_static_objects =
        tcx.sess.lto() == Lto::Thin || tcx.crate_types().contains(&CrateType::Rlib);

    tcx.sess.target.is_like_windows &&
    can_have_static_objects   &&
    // ThinLTO can't handle this workaround in all cases, so we don't
    // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
    // dynamic linking when linker plugin LTO is enabled.
    !tcx.sess.opts.cg.linker_plugin_lto.enabled()
}
