use std::collections::BTreeMap;
use std::ffi::{CStr, CString};
use std::fs::File;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{io, iter, slice};

use object::read::archive::ArchiveFile;
use object::{Object, ObjectSection};
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::write::{
    CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn, ThinLtoInput,
};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_errors::{DiagCtxt, DiagCtxtHandle};
use rustc_hir::attrs::SanitizerSet;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_session::config;
use tracing::{debug, info};

use crate::back::write::{
    self, CodegenDiagnosticsStage, DiagnosticHandlers, bitcode_section_name, codegen,
    save_temp_bitcode,
};
use crate::errors::{LlvmError, LtoBitcodeFromRlib};
use crate::llvm::{self, build_string};
use crate::{LlvmCodegenBackend, ModuleLlvm};

/// We keep track of the computed LTO cache keys from the previous
/// session to determine which CGUs we can reuse.
const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";

fn prepare_lto(
    cgcx: &CodegenContext,
    exported_symbols_for_lto: &[String],
    each_linked_rlib_for_lto: &[PathBuf],
    dcx: DiagCtxtHandle<'_>,
) -> (Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>) {
    let mut symbols_below_threshold = exported_symbols_for_lto
        .iter()
        .map(|symbol| CString::new(symbol.to_owned()).unwrap())
        .collect::<Vec<CString>>();

    if cgcx.module_config.instrument_coverage || cgcx.module_config.pgo_gen.enabled() {
        // These are weak symbols that point to the profile version and the
        // profile name, which need to be treated as exported so LTO doesn't nix
        // them.
        const PROFILER_WEAK_SYMBOLS: [&CStr; 2] =
            [c"__llvm_profile_raw_version", c"__llvm_profile_filename"];

        symbols_below_threshold.extend(PROFILER_WEAK_SYMBOLS.iter().map(|&sym| sym.to_owned()));
    }

    if cgcx.module_config.sanitizer.contains(SanitizerSet::MEMORY) {
        let mut msan_weak_symbols = Vec::new();

        // Similar to profiling, preserve weak msan symbol during LTO.
        if cgcx.module_config.sanitizer_recover.contains(SanitizerSet::MEMORY) {
            msan_weak_symbols.push(c"__msan_keep_going");
        }

        if cgcx.module_config.sanitizer_memory_track_origins != 0 {
            msan_weak_symbols.push(c"__msan_track_origins");
        }

        symbols_below_threshold.extend(msan_weak_symbols.into_iter().map(|sym| sym.to_owned()));
    }

    // Preserve LLVM-injected, ASAN-related symbols.
    // See also https://github.com/rust-lang/rust/issues/113404.
    symbols_below_threshold.push(c"___asan_globals_registered".to_owned());

    // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
    // __llvm_profile_runtime, therefore we won't know until link time if this symbol
    // should have default visibility.
    symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());

    // LTO seems to discard this otherwise under certain circumstances.
    symbols_below_threshold.push(c"rust_eh_personality".to_owned());

    // If we're performing LTO for the entire crate graph, then for each of our
    // upstream dependencies, find the corresponding rlib and load the bitcode
    // from the archive.
    //
    // We save off all the bytecode and LLVM module ids for later processing
    // with either fat or thin LTO
    let mut upstream_modules = Vec::new();
    for path in each_linked_rlib_for_lto {
        let archive_data = unsafe {
            Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib"))
                .expect("couldn't map rlib")
        };
        let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib");
        let obj_files = archive
            .members()
            .filter_map(|child| {
                child
                    .ok()
                    .and_then(|c| std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c)))
            })
            .filter(|&(name, _)| looks_like_rust_object_file(name));
        for (name, child) in obj_files {
            info!("adding bitcode from {}", name);
            match get_bitcode_slice_from_object_data(
                child.data(&*archive_data).expect("corrupt rlib"),
                cgcx,
            ) {
                Ok(data) => {
                    let module = SerializedModule::FromRlib(data.to_vec());
                    upstream_modules.push((module, CString::new(name).unwrap()));
                }
                Err(e) => dcx.emit_fatal(e),
            }
        }
    }

    (symbols_below_threshold, upstream_modules)
}

fn get_bitcode_slice_from_object_data<'a>(
    obj: &'a [u8],
    cgcx: &CodegenContext,
) -> Result<&'a [u8], LtoBitcodeFromRlib> {
    // We're about to assume the data here is an object file with sections, but if it's raw LLVM IR
    // that won't work. Fortunately, if that's what we have we can just return the object directly,
    // so we sniff the relevant magic strings here and return.
    if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") {
        return Ok(obj);
    }
    // We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment
    // name" which in the public API for sections gets treated as part of the section name, but
    // internally in MachOObjectFile.cpp gets treated separately.
    let section_name = bitcode_section_name(cgcx).to_str().unwrap().trim_start_matches("__LLVM,");

    let obj =
        object::File::parse(obj).map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })?;

    let section = obj
        .section_by_name(section_name)
        .ok_or_else(|| LtoBitcodeFromRlib { err: format!("Can't find section {section_name}") })?;

    section.data().map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })
}

/// Performs fat LTO by merging all modules into a single one and returning it
/// for further optimization.
pub(crate) fn run_fat(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: &SharedEmitter,
    tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
    exported_symbols_for_lto: &[String],
    each_linked_rlib_for_lto: &[PathBuf],
    modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
) -> ModuleCodegen<ModuleLlvm> {
    let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
    let dcx = dcx.handle();
    let (symbols_below_threshold, upstream_modules) =
        prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
    let symbols_below_threshold =
        symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
    fat_lto(
        cgcx,
        prof,
        dcx,
        shared_emitter,
        tm_factory,
        modules,
        upstream_modules,
        &symbols_below_threshold,
    )
}

/// Performs thin LTO by performing necessary global analysis and returning two
/// lists, one of the modules that need optimization and another for modules that
/// can simply be copied over from the incr. comp. cache.
pub(crate) fn run_thin(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    dcx: DiagCtxtHandle<'_>,
    exported_symbols_for_lto: &[String],
    each_linked_rlib_for_lto: &[PathBuf],
    modules: Vec<ThinLtoInput<LlvmCodegenBackend>>,
) -> (Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>) {
    let (symbols_below_threshold, upstream_modules) =
        prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
    let symbols_below_threshold =
        symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
    if cgcx.use_linker_plugin_lto {
        unreachable!(
            "We should never reach this case if the LTO step \
                      is deferred to the linker"
        );
    }
    thin_lto(cgcx, prof, dcx, modules, upstream_modules, &symbols_below_threshold)
}

fn fat_lto(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    dcx: DiagCtxtHandle<'_>,
    shared_emitter: &SharedEmitter,
    tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
    modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
    mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
    symbols_below_threshold: &[*const libc::c_char],
) -> ModuleCodegen<ModuleLlvm> {
    let _timer = prof.generic_activity("LLVM_fat_lto_build_monolithic_module");
    info!("going for a fat lto");

    // Sort out all our lists of incoming modules into two lists.
    //
    // * `serialized_modules` (also and argument to this function) contains all
    //   modules that are serialized in-memory.
    // * `in_memory` contains modules which are already parsed and in-memory,
    //   such as from multi-CGU builds.
    let mut in_memory = Vec::new();
    for module in modules {
        match module {
            FatLtoInput::InMemory(m) => in_memory.push(m),
            FatLtoInput::Serialized { name, buffer } => {
                info!("pushing serialized module {:?}", name);
                serialized_modules.push((buffer, CString::new(name).unwrap()));
            }
        }
    }

    // Find the "costliest" module and merge everything into that codegen unit.
    // All the other modules will be serialized and reparsed into the new
    // context, so this hopefully avoids serializing and parsing the largest
    // codegen unit.
    //
    // Additionally use a regular module as the base here to ensure that various
    // file copy operations in the backend work correctly. The only other kind
    // of module here should be an allocator one, and if your crate is smaller
    // than the allocator module then the size doesn't really matter anyway.
    let costliest_module = in_memory
        .iter()
        .enumerate()
        .filter(|&(_, module)| module.kind == ModuleKind::Regular)
        .map(|(i, module)| {
            let cost = unsafe { llvm::LLVMRustModuleCost(module.module_llvm.llmod()) };
            (cost, i)
        })
        .max();

    // If we found a costliest module, we're good to go. Otherwise all our
    // inputs were serialized which could happen in the case, for example, that
    // all our inputs were incrementally reread from the cache and we're just
    // re-executing the LTO passes. If that's the case deserialize the first
    // module and create a linker with it.
    let module: ModuleCodegen<ModuleLlvm> = match costliest_module {
        Some((_cost, i)) => in_memory.remove(i),
        None => {
            assert!(!serialized_modules.is_empty(), "must have at least one serialized module");
            let (buffer, name) = serialized_modules.remove(0);
            info!("no in-memory regular modules to choose from, parsing {:?}", name);
            let llvm_module = ModuleLlvm::parse(cgcx, tm_factory, &name, buffer.data(), dcx);
            ModuleCodegen::new_regular(name.into_string().unwrap(), llvm_module)
        }
    };
    {
        let (llcx, llmod) = {
            let llvm = &module.module_llvm;
            (&llvm.llcx, llvm.llmod())
        };
        info!("using {:?} as a base module", module.name);

        // The linking steps below may produce errors and diagnostics within LLVM
        // which we'd like to handle and print, so set up our diagnostic handlers
        // (which get unregistered when they go out of scope below).
        let _handler = DiagnosticHandlers::new(
            cgcx,
            shared_emitter,
            llcx,
            &module,
            CodegenDiagnosticsStage::LTO,
        );

        // For all other modules we codegened we'll need to link them into our own
        // bitcode. All modules were codegened in their own LLVM context, however,
        // and we want to move everything to the same LLVM context. Currently the
        // way we know of to do that is to serialize them to a string and them parse
        // them later. Not great but hey, that's why it's "fat" LTO, right?
        for module in in_memory {
            let buffer = ModuleBuffer::new(module.module_llvm.llmod(), false);
            let llmod_id = CString::new(&module.name[..]).unwrap();
            serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
        }
        // Sort the modules to ensure we produce deterministic results.
        serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));

        // For all serialized bitcode files we parse them and link them in as we did
        // above, this is all mostly handled in C++.
        let linker = unsafe { llvm::LLVMRustLinkerNew(llmod) };
        for (bc_decoded, name) in serialized_modules {
            let _timer = prof
                .generic_activity_with_arg_recorder("LLVM_fat_lto_link_module", |recorder| {
                    recorder.record_arg(format!("{name:?}"))
                });
            info!("linking {:?}", name);
            let data = bc_decoded.data();

            unsafe {
                if !llvm::LLVMRustLinkerAdd(
                    linker,
                    data.as_ptr() as *const libc::c_char,
                    data.len(),
                ) {
                    llvm::LLVMRustLinkerFree(linker);
                    write::llvm_err(dcx, LlvmError::LoadBitcode { name })
                }
            }
        }
        unsafe { llvm::LLVMRustLinkerFree(linker) };
        save_temp_bitcode(cgcx, &module, "lto.input");

        // Internalize everything below threshold to help strip out more modules and such.
        unsafe {
            let ptr = symbols_below_threshold.as_ptr();
            llvm::LLVMRustRunRestrictionPass(
                llmod,
                ptr as *const *const libc::c_char,
                symbols_below_threshold.len() as libc::size_t,
            );
        }
        save_temp_bitcode(cgcx, &module, "lto.after-restriction");
    }

    module
}

/// Prepare "thin" LTO to get run on these modules.
///
/// The general structure of ThinLTO is quite different from the structure of
/// "fat" LTO above. With "fat" LTO all LLVM modules in question are merged into
/// one giant LLVM module, and then we run more optimization passes over this
/// big module after internalizing most symbols. Thin LTO, on the other hand,
/// avoid this large bottleneck through more targeted optimization.
///
/// At a high level Thin LTO looks like:
///
///    1. Prepare a "summary" of each LLVM module in question which describes
///       the values inside, cost of the values, etc.
///    2. Merge the summaries of all modules in question into one "index"
///    3. Perform some global analysis on this index
///    4. For each module, use the index and analysis calculated previously to
///       perform local transformations on the module, for example inlining
///       small functions from other modules.
///    5. Run thin-specific optimization passes over each module, and then code
///       generate everything at the end.
///
/// The summary for each module is intended to be quite cheap, and the global
/// index is relatively quite cheap to create as well. As a result, the goal of
/// ThinLTO is to reduce the bottleneck on LTO and enable LTO to be used in more
/// situations. For example one cheap optimization is that we can parallelize
/// all codegen modules, easily making use of all the cores on a machine.
///
/// With all that in mind, the function here is designed at specifically just
/// calculating the *index* for ThinLTO. This index will then be shared amongst
/// all of the `LtoModuleCodegen` units returned below and destroyed once
/// they all go out of scope.
fn thin_lto(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    dcx: DiagCtxtHandle<'_>,
    modules: Vec<ThinLtoInput<LlvmCodegenBackend>>,
    serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
    symbols_below_threshold: &[*const libc::c_char],
) -> (Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>) {
    let _timer = prof.generic_activity("LLVM_thin_lto_global_analysis");
    unsafe {
        info!("going for that thin, thin LTO");

        let green_modules: FxHashMap<_, _> = modules
            .iter()
            .filter_map(|module| {
                if let ThinLtoInput::Green { wp, .. } = module {
                    Some((wp.cgu_name.clone(), wp.clone()))
                } else {
                    None
                }
            })
            .collect();

        let full_scope_len = modules.len();
        let mut thin_buffers = Vec::with_capacity(modules.len());
        let mut module_names = Vec::with_capacity(full_scope_len);
        let mut thin_modules = Vec::with_capacity(full_scope_len);

        for (i, module) in modules.into_iter().enumerate() {
            let (name, buffer) = match module {
                ThinLtoInput::Red { name, buffer } => (name, buffer),
                ThinLtoInput::Green { wp, buffer } => (wp.cgu_name, buffer),
            };
            info!("local module: {} - {}", i, name);
            let cname = CString::new(name.as_bytes()).unwrap();
            thin_modules.push(llvm::ThinLTOModule {
                identifier: cname.as_ptr(),
                data: buffer.data().as_ptr(),
                len: buffer.data().len(),
            });
            thin_buffers.push(buffer);
            module_names.push(cname);
        }

        // FIXME: All upstream crates are deserialized internally in the
        //        function below to extract their summary and modules. Note that
        //        unlike the loop above we *must* decode and/or read something
        //        here as these are all just serialized files on disk. An
        //        improvement, however, to make here would be to store the
        //        module summary separately from the actual module itself. Right
        //        now this is store in one large bitcode file, and the entire
        //        file is deflate-compressed. We could try to bypass some of the
        //        decompression by storing the index uncompressed and only
        //        lazily decompressing the bytecode if necessary.
        //
        //        Note that truly taking advantage of this optimization will
        //        likely be further down the road. We'd have to implement
        //        incremental ThinLTO first where we could actually avoid
        //        looking at upstream modules entirely sometimes (the contents,
        //        we must always unconditionally look at the index).

        for (module, name) in serialized_modules {
            info!("upstream module {:?}", name);
            thin_modules.push(llvm::ThinLTOModule {
                identifier: name.as_ptr(),
                data: module.data().as_ptr(),
                len: module.data().len(),
            });
            thin_buffers.push(module);
            module_names.push(name);
        }

        // Sanity check
        assert_eq!(thin_modules.len(), module_names.len());

        // Delegate to the C++ bindings to create some data here. Once this is a
        // tried-and-true interface we may wish to try to upstream some of this
        // to LLVM itself, right now we reimplement a lot of what they do
        // upstream...
        let data = llvm::LLVMRustCreateThinLTOData(
            thin_modules.as_ptr(),
            thin_modules.len(),
            symbols_below_threshold.as_ptr(),
            symbols_below_threshold.len(),
        )
        .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext));

        let data = ThinData(data);

        info!("thin LTO data created");

        let (key_map_path, prev_key_map, curr_key_map) = if let Some(ref incr_comp_session_dir) =
            cgcx.incr_comp_session_dir
        {
            let path = incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME);
            // If the previous file was deleted, or we get an IO error
            // reading the file, then we'll just use `None` as the
            // prev_key_map, which will force the code to be recompiled.
            let prev =
                if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None };
            let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names);
            (Some(path), prev, curr)
        } else {
            // If we don't compile incrementally, we don't need to load the
            // import data from LLVM.
            assert!(green_modules.is_empty());
            let curr = ThinLTOKeysMap::default();
            (None, None, curr)
        };
        info!("thin LTO cache key map loaded");
        info!("prev_key_map: {:#?}", prev_key_map);
        info!("curr_key_map: {:#?}", curr_key_map);

        // Throw our data in an `Arc` as we'll be sharing it across threads. We
        // also put all memory referenced by the C++ data (buffers, ids, etc)
        // into the arc as well. After this we'll create a thin module
        // codegen per module in this data.
        let shared = Arc::new(ThinShared { data, modules: thin_buffers, module_names });

        let mut copy_jobs = vec![];
        let mut opt_jobs = vec![];

        info!("checking which modules can be-reused and which have to be re-optimized.");
        for (module_index, module_name) in shared.module_names.iter().enumerate() {
            let module_name = module_name_to_str(module_name);
            if let (Some(prev_key_map), true) =
                (prev_key_map.as_ref(), green_modules.contains_key(module_name))
            {
                assert!(cgcx.incr_comp_session_dir.is_some());

                // If a module exists in both the current and the previous session,
                // and has the same LTO cache key in both sessions, then we can re-use it
                if prev_key_map.keys.get(module_name) == curr_key_map.keys.get(module_name) {
                    let work_product = green_modules[module_name].clone();
                    copy_jobs.push(work_product);
                    info!(" - {}: re-used", module_name);
                    assert!(cgcx.incr_comp_session_dir.is_some());
                    continue;
                }
            }

            info!(" - {}: re-compiled", module_name);
            opt_jobs.push(ThinModule { shared: Arc::clone(&shared), idx: module_index });
        }

        // Save the current ThinLTO import information for the next compilation
        // session, overwriting the previous serialized data (if any).
        if let Some(path) = key_map_path
            && let Err(err) = curr_key_map.save_to_file(&path)
        {
            write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err });
        }

        (opt_jobs, copy_jobs)
    }
}

pub(crate) fn enable_autodiff_settings(ad: &[config::AutoDiff]) {
    let mut enzyme = llvm::EnzymeWrapper::get_instance();

    for val in ad {
        // We intentionally don't use a wildcard, to not forget handling anything new.
        match val {
            config::AutoDiff::PrintPerf => {
                enzyme.set_print_perf(true);
            }
            config::AutoDiff::PrintAA => {
                enzyme.set_print_activity(true);
            }
            config::AutoDiff::PrintTA => {
                enzyme.set_print_type(true);
            }
            config::AutoDiff::PrintTAFn(fun) => {
                enzyme.set_print_type(true); // Enable general type printing
                enzyme.set_print_type_fun(&fun); // Set specific function to analyze
            }
            config::AutoDiff::Inline => {
                enzyme.set_inline(true);
            }
            config::AutoDiff::LooseTypes => {
                enzyme.set_loose_types(true);
            }
            config::AutoDiff::PrintSteps => {
                enzyme.set_print(true);
            }
            // We handle this in the PassWrapper.cpp
            config::AutoDiff::PrintPasses => {}
            // We handle this in the PassWrapper.cpp
            config::AutoDiff::PrintModBefore => {}
            // We handle this in the PassWrapper.cpp
            config::AutoDiff::PrintModAfter => {}
            // We handle this in the PassWrapper.cpp
            config::AutoDiff::PrintModFinal => {}
            // This is required and already checked
            config::AutoDiff::Enable => {}
            // We handle this below
            config::AutoDiff::NoPostopt => {}
            // Disables TypeTree generation
            config::AutoDiff::NoTT => {}
        }
    }
    // This helps with handling enums for now.
    enzyme.set_strict_aliasing(false);
    // FIXME(ZuseZ4): Test this, since it was added a long time ago.
    enzyme.set_rust_rules(true);
}

pub(crate) fn run_pass_manager(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    dcx: DiagCtxtHandle<'_>,
    module: &mut ModuleCodegen<ModuleLlvm>,
    thin: bool,
) {
    let _timer = prof.generic_activity_with_arg("LLVM_lto_optimize", &*module.name);
    let config = &cgcx.module_config;

    // Now we have one massive module inside of llmod. Time to run the
    // LTO-specific optimization passes that LLVM provides.
    //
    // This code is based off the code found in llvm's LTO code generator:
    //      llvm/lib/LTO/LTOCodeGenerator.cpp
    debug!("running the pass manager");
    let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
    let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);

    // The PostAD behavior is the same that we would have if no autodiff was used.
    // It will run the default optimization pipeline. If AD is enabled we select
    // the DuringAD stage, which will disable vectorization and loop unrolling, and
    // schedule two autodiff optimization + differentiation passes.
    // We then run the llvm_optimize function a second time, to optimize the code which we generated
    // in the enzyme differentiation pass.
    let enable_ad = config.autodiff.contains(&config::AutoDiff::Enable);
    let stage = if thin {
        write::AutodiffStage::PreAD
    } else {
        if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD }
    };

    unsafe {
        write::llvm_optimize(
            cgcx, prof, dcx, module, None, None, config, opt_level, opt_stage, stage,
        );
    }

    if cfg!(feature = "llvm_enzyme") && enable_ad && !thin {
        let opt_stage = llvm::OptStage::FatLTO;
        let stage = write::AutodiffStage::PostAD;
        if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
            unsafe {
                write::llvm_optimize(
                    cgcx, prof, dcx, module, None, None, config, opt_level, opt_stage, stage,
                );
            }
        }

        // This is the final IR, so people should be able to inspect the optimized autodiff output,
        // for manual inspection.
        if config.autodiff.contains(&config::AutoDiff::PrintModFinal) {
            unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
        }
    }

    debug!("lto done");
}

#[repr(transparent)]
pub(crate) struct Buffer(&'static mut llvm::Buffer);

unsafe impl Send for Buffer {}
unsafe impl Sync for Buffer {}

impl Buffer {
    pub(crate) fn data(&self) -> &[u8] {
        unsafe {
            let ptr = llvm::LLVMRustBufferPtr(self.0);
            let len = llvm::LLVMRustBufferLen(self.0);
            slice::from_raw_parts(ptr, len)
        }
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMRustBufferFree(&mut *(self.0 as *mut _));
        }
    }
}

pub struct ThinData(&'static mut llvm::ThinLTOData);

unsafe impl Send for ThinData {}
unsafe impl Sync for ThinData {}

impl Drop for ThinData {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _));
        }
    }
}

pub struct ModuleBuffer {
    data: Buffer,
}

impl ModuleBuffer {
    pub(crate) fn new(m: &llvm::Module, is_thin: bool) -> ModuleBuffer {
        unsafe {
            let buffer = llvm::LLVMRustModuleSerialize(m, is_thin);
            ModuleBuffer { data: Buffer(buffer) }
        }
    }
}

impl ModuleBufferMethods for ModuleBuffer {
    fn data(&self) -> &[u8] {
        self.data.data()
    }
}

pub(crate) fn optimize_and_codegen_thin_module(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: &SharedEmitter,
    tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
    thin_module: ThinModule<LlvmCodegenBackend>,
) -> CompiledModule {
    let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
    let dcx = dcx.handle();

    let module_name = &thin_module.shared.module_names[thin_module.idx];

    // Right now the implementation we've got only works over serialized
    // modules, so we create a fresh new LLVM context and parse the module
    // into that context. One day, however, we may do this for upstream
    // crates but for locally codegened modules we may be able to reuse
    // that LLVM Context and Module.
    let module_llvm = ModuleLlvm::parse(cgcx, tm_factory, module_name, thin_module.data(), dcx);
    let mut module = ModuleCodegen::new_regular(thin_module.name(), module_llvm);
    // Given that the newly created module lacks a thinlto buffer for embedding, we need to re-add it here.
    if cgcx.module_config.embed_bitcode() {
        module.thin_lto_buffer = Some(thin_module.data().to_vec());
    }
    {
        let target = &*module.module_llvm.tm;
        let llmod = module.module_llvm.llmod();
        save_temp_bitcode(cgcx, &module, "thin-lto-input");

        // Up next comes the per-module local analyses that we do for Thin LTO.
        // Each of these functions is basically copied from the LLVM
        // implementation and then tailored to suit this implementation. Ideally
        // each of these would be supported by upstream LLVM but that's perhaps
        // a patch for another day!
        //
        // You can find some more comments about these functions in the LLVM
        // bindings we've got (currently `PassWrapper.cpp`)
        {
            let _timer = prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
            unsafe {
                llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target.raw())
            };
            save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
        }

        {
            let _timer =
                prof.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
            if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) }
            {
                write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
            }
            save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
        }

        {
            let _timer =
                prof.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
            if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) }
            {
                write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
            }
            save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
        }

        {
            let _timer = prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
            if unsafe {
                !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target.raw())
            } {
                write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
            }
            save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
        }

        // Alright now that we've done everything related to the ThinLTO
        // analysis it's time to run some optimizations! Here we use the same
        // `run_pass_manager` as the "fat" LTO above except that we tell it to
        // populate a thin-specific pass manager, which presumably LLVM treats a
        // little differently.
        {
            info!("running thin lto passes over {}", module.name);
            run_pass_manager(cgcx, prof, dcx, &mut module, true);
            save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
        }
    }
    codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config)
}

/// Maps LLVM module identifiers to their corresponding LLVM LTO cache keys
#[derive(Debug, Default)]
struct ThinLTOKeysMap {
    // key = llvm name of importing module, value = LLVM cache key
    keys: BTreeMap<String, String>,
}

impl ThinLTOKeysMap {
    fn save_to_file(&self, path: &Path) -> io::Result<()> {
        use std::io::Write;
        let mut writer = File::create_buffered(path)?;
        // The entries are loaded back into a hash map in `load_from_file()`, so
        // the order in which we write them to file here does not matter.
        for (module, key) in &self.keys {
            writeln!(writer, "{module} {key}")?;
        }
        Ok(())
    }

    fn load_from_file(path: &Path) -> io::Result<Self> {
        use std::io::BufRead;
        let mut keys = BTreeMap::default();
        let file = File::open_buffered(path)?;
        for line in file.lines() {
            let line = line?;
            let mut split = line.split(' ');
            let module = split.next().unwrap();
            let key = split.next().unwrap();
            assert_eq!(split.next(), None, "Expected two space-separated values, found {line:?}");
            keys.insert(module.to_string(), key.to_string());
        }
        Ok(Self { keys })
    }

    fn from_thin_lto_modules(
        data: &ThinData,
        modules: &[llvm::ThinLTOModule],
        names: &[CString],
    ) -> Self {
        let keys = iter::zip(modules, names)
            .map(|(module, name)| {
                let key = build_string(|rust_str| unsafe {
                    llvm::LLVMRustComputeLTOCacheKey(rust_str, module.identifier, data.0);
                })
                .expect("Invalid ThinLTO module key");
                (module_name_to_str(name).to_string(), key)
            })
            .collect();
        Self { keys }
    }
}

fn module_name_to_str(c_str: &CStr) -> &str {
    c_str.to_str().unwrap_or_else(|e| {
        bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e)
    })
}

pub(crate) fn parse_module<'a>(
    cx: &'a llvm::Context,
    name: &CStr,
    data: &[u8],
    dcx: DiagCtxtHandle<'_>,
) -> &'a llvm::Module {
    unsafe {
        llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr())
            .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::ParseBitcode))
    }
}
