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_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.join(saved_path);
        debug!(
            "copying preexisting module `{}` from {:?} to {}",
            module.name,
            source_file_in_incr_comp_dir,
            output_path.display()
        );
        match link_or_copy(&source_file_in_incr_comp_dir, &output_path) {
            Ok(_) => {
                links_from_incr_cache.push(source_file_in_incr_comp_dir);
                Some(output_path)
            }
            Err(error) => {
                dcx.emit_err(errors::CopyPathBuf {
                    source_file: source_file_in_incr_comp_dir,
                    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()
}
