use std::ffi::{CStr, CString};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{fs, slice, str};

use libc::{c_char, c_int, c_void, size_t};
use rustc_codegen_ssa::back::link::ensure_removed;
use rustc_codegen_ssa::back::versioned_llvm_target;
use rustc_codegen_ssa::back::write::{
    BitcodeSection, CodegenContext, EmitObj, InlineAsmError, ModuleConfig, SharedEmitter,
    TargetMachineFactoryConfig, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_errors::{DiagCtxt, DiagCtxtHandle, Level};
use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext, sym};
use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
use tracing::{debug, trace};

use crate::back::lto::{Buffer, ModuleBuffer};
use crate::back::owned_target_machine::OwnedTargetMachine;
use crate::back::profiling::{
    LlvmSelfProfiler, selfprofile_after_pass_callback, selfprofile_before_pass_callback,
};
use crate::builder::SBuilder;
use crate::builder::gpu_offload::scalar_width;
use crate::common::AsCCharPtr;
use crate::errors::{
    CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, ParseTargetMachineConfig,
    UnknownCompression, WithLlvmError, WriteBytecode,
};
use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
use crate::llvm::{self, DiagnosticInfo};
use crate::type_::llvm_type_ptr;
use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx, attributes, base, common, llvm_util};

pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> ! {
    match llvm::last_error() {
        Some(llvm_err) => dcx.emit_fatal(WithLlvmError(err, llvm_err)),
        None => dcx.emit_fatal(err),
    }
}

fn write_output_file<'ll>(
    dcx: DiagCtxtHandle<'_>,
    target: &'ll llvm::TargetMachine,
    no_builtins: bool,
    m: &'ll llvm::Module,
    output: &Path,
    dwo_output: Option<&Path>,
    file_type: llvm::FileType,
    self_profiler_ref: &SelfProfilerRef,
    verify_llvm_ir: bool,
) {
    debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output);
    let output_c = path_to_c_string(output);
    let dwo_output_c;
    let dwo_output_ptr = if let Some(dwo_output) = dwo_output {
        dwo_output_c = path_to_c_string(dwo_output);
        dwo_output_c.as_ptr()
    } else {
        std::ptr::null()
    };
    let result = unsafe {
        let pm = llvm::LLVMCreatePassManager();
        llvm::LLVMAddAnalysisPasses(target, pm);
        llvm::LLVMRustAddLibraryInfo(target, pm, m, no_builtins);
        llvm::LLVMRustWriteOutputFile(
            target,
            pm,
            m,
            output_c.as_ptr(),
            dwo_output_ptr,
            file_type,
            verify_llvm_ir,
        )
    };

    // Record artifact sizes for self-profiling
    if result == llvm::LLVMRustResult::Success {
        let artifact_kind = match file_type {
            llvm::FileType::ObjectFile => "object_file",
            llvm::FileType::AssemblyFile => "assembly_file",
        };
        record_artifact_size(self_profiler_ref, artifact_kind, output);
        if let Some(dwo_file) = dwo_output {
            record_artifact_size(self_profiler_ref, "dwo_file", dwo_file);
        }
    }

    result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
}

pub(crate) fn create_informational_target_machine(
    sess: &Session,
    only_base_features: bool,
) -> OwnedTargetMachine {
    let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
    // Can't use query system here quite yet because this function is invoked before the query
    // system/tcx is set up.
    let features = llvm_util::global_llvm_features(sess, only_base_features);
    target_machine_factory(sess, config::OptLevel::No, &features)(sess.dcx(), config)
}

pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine {
    let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() {
        tcx.output_filenames(()).split_dwarf_path(
            tcx.sess.split_debuginfo(),
            tcx.sess.opts.unstable_opts.split_dwarf_kind,
            mod_name,
            tcx.sess.invocation_temp.as_deref(),
        )
    } else {
        None
    };

    let output_obj_file = Some(tcx.output_filenames(()).temp_path_for_cgu(
        OutputType::Object,
        mod_name,
        tcx.sess.invocation_temp.as_deref(),
    ));
    let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file };

    target_machine_factory(
        tcx.sess,
        tcx.backend_optimization_level(()),
        tcx.global_backend_features(()),
    )(tcx.dcx(), config)
}

fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) {
    use self::config::OptLevel::*;
    match cfg {
        No => (llvm::CodeGenOptLevel::None, llvm::CodeGenOptSizeNone),
        Less => (llvm::CodeGenOptLevel::Less, llvm::CodeGenOptSizeNone),
        More => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeNone),
        Aggressive => (llvm::CodeGenOptLevel::Aggressive, llvm::CodeGenOptSizeNone),
        Size => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeDefault),
        SizeMin => (llvm::CodeGenOptLevel::Default, llvm::CodeGenOptSizeAggressive),
    }
}

fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel {
    use config::OptLevel::*;
    match cfg {
        No => llvm::PassBuilderOptLevel::O0,
        Less => llvm::PassBuilderOptLevel::O1,
        More => llvm::PassBuilderOptLevel::O2,
        Aggressive => llvm::PassBuilderOptLevel::O3,
        Size => llvm::PassBuilderOptLevel::Os,
        SizeMin => llvm::PassBuilderOptLevel::Oz,
    }
}

fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
    match relocation_model {
        RelocModel::Static => llvm::RelocModel::Static,
        // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra
        // attribute.
        RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC,
        RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
        RelocModel::Ropi => llvm::RelocModel::ROPI,
        RelocModel::Rwpi => llvm::RelocModel::RWPI,
        RelocModel::RopiRwpi => llvm::RelocModel::ROPI_RWPI,
    }
}

pub(crate) fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeModel {
    match code_model {
        Some(CodeModel::Tiny) => llvm::CodeModel::Tiny,
        Some(CodeModel::Small) => llvm::CodeModel::Small,
        Some(CodeModel::Kernel) => llvm::CodeModel::Kernel,
        Some(CodeModel::Medium) => llvm::CodeModel::Medium,
        Some(CodeModel::Large) => llvm::CodeModel::Large,
        None => llvm::CodeModel::None,
    }
}

fn to_llvm_float_abi(float_abi: Option<FloatAbi>) -> llvm::FloatAbi {
    match float_abi {
        None => llvm::FloatAbi::Default,
        Some(FloatAbi::Soft) => llvm::FloatAbi::Soft,
        Some(FloatAbi::Hard) => llvm::FloatAbi::Hard,
    }
}

pub(crate) fn target_machine_factory(
    sess: &Session,
    optlvl: config::OptLevel,
    target_features: &[String],
) -> TargetMachineFactoryFn<LlvmCodegenBackend> {
    // Self-profile timer for creating a _factory_.
    let _prof_timer = sess.prof.generic_activity("target_machine_factory");

    let reloc_model = to_llvm_relocation_model(sess.relocation_model());

    let (opt_level, _) = to_llvm_opt_settings(optlvl);
    let float_abi = to_llvm_float_abi(sess.target.llvm_floatabi);

    let ffunction_sections =
        sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections);
    let fdata_sections = ffunction_sections;
    let funique_section_names = !sess.opts.unstable_opts.no_unique_section_names;

    let code_model = to_llvm_code_model(sess.code_model());

    let mut singlethread = sess.target.singlethread;

    // On the wasm target once the `atomics` feature is enabled that means that
    // we're no longer single-threaded, or otherwise we don't want LLVM to
    // lower atomic operations to single-threaded operations.
    if singlethread && sess.target.is_like_wasm && sess.target_features.contains(&sym::atomics) {
        singlethread = false;
    }

    let triple = SmallCStr::new(&versioned_llvm_target(sess));
    let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
    let features = CString::new(target_features.join(",")).unwrap();
    let abi = SmallCStr::new(&sess.target.llvm_abiname);
    let trap_unreachable =
        sess.opts.unstable_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable);
    let emit_stack_size_section = sess.opts.unstable_opts.emit_stack_sizes;

    let verbose_asm = sess.opts.unstable_opts.verbose_asm;
    let relax_elf_relocations =
        sess.opts.unstable_opts.relax_elf_relocations.unwrap_or(sess.target.relax_elf_relocations);

    let use_init_array =
        !sess.opts.unstable_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section);

    let path_mapping = sess.source_map().path_mapping().clone();
    let working_dir = sess.source_map().working_dir().clone();

    let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);

    let debuginfo_compression = match sess.opts.unstable_opts.debuginfo_compression {
        config::DebugInfoCompression::None => llvm::CompressionKind::None,
        config::DebugInfoCompression::Zlib => {
            if llvm::LLVMRustLLVMHasZlibCompression() {
                llvm::CompressionKind::Zlib
            } else {
                sess.dcx().emit_warn(UnknownCompression { algorithm: "zlib" });
                llvm::CompressionKind::None
            }
        }
        config::DebugInfoCompression::Zstd => {
            if llvm::LLVMRustLLVMHasZstdCompression() {
                llvm::CompressionKind::Zstd
            } else {
                sess.dcx().emit_warn(UnknownCompression { algorithm: "zstd" });
                llvm::CompressionKind::None
            }
        }
    };

    let use_wasm_eh = wants_wasm_eh(sess);

    let large_data_threshold = sess.opts.unstable_opts.large_data_threshold.unwrap_or(0);

    let prof = SelfProfilerRef::clone(&sess.prof);
    Arc::new(move |dcx: DiagCtxtHandle<'_>, config: TargetMachineFactoryConfig| {
        // Self-profile timer for invoking a factory to create a target machine.
        let _prof_timer = prof.generic_activity("target_machine_factory_inner");

        let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
            let path = path.unwrap_or_default();
            let path = path_mapping
                .to_real_filename(&working_dir, path)
                .path(RemapPathScopeComponents::DEBUGINFO)
                .to_string_lossy()
                .into_owned();
            CString::new(path).unwrap()
        };

        let split_dwarf_file = path_to_cstring_helper(config.split_dwarf_file);
        let output_obj_file = path_to_cstring_helper(config.output_obj_file);

        OwnedTargetMachine::new(
            &triple,
            &cpu,
            &features,
            &abi,
            code_model,
            reloc_model,
            opt_level,
            float_abi,
            ffunction_sections,
            fdata_sections,
            funique_section_names,
            trap_unreachable,
            singlethread,
            verbose_asm,
            emit_stack_size_section,
            relax_elf_relocations,
            use_init_array,
            &split_dwarf_file,
            &output_obj_file,
            debuginfo_compression,
            use_emulated_tls,
            use_wasm_eh,
            large_data_threshold,
        )
        .unwrap_or_else(|err| dcx.emit_fatal(ParseTargetMachineConfig(err)))
    })
}

pub(crate) fn save_temp_bitcode(
    cgcx: &CodegenContext,
    module: &ModuleCodegen<ModuleLlvm>,
    name: &str,
) {
    if !cgcx.save_temps {
        return;
    }
    let ext = format!("{name}.bc");
    let path = cgcx.output_filenames.temp_path_ext_for_cgu(
        &ext,
        &module.name,
        cgcx.invocation_temp.as_deref(),
    );
    write_bitcode_to_file(&module.module_llvm, &path)
}

fn write_bitcode_to_file(module: &ModuleLlvm, path: &Path) {
    unsafe {
        let path = path_to_c_string(&path);
        let llmod = module.llmod();
        llvm::LLVMWriteBitcodeToFile(llmod, path.as_ptr());
    }
}

/// In what context is a diagnostic handler being attached to a codegen unit?
pub(crate) enum CodegenDiagnosticsStage {
    /// Prelink optimization stage.
    Opt,
    /// LTO/ThinLTO postlink optimization stage.
    LTO,
    /// Code generation.
    Codegen,
}

pub(crate) struct DiagnosticHandlers<'a> {
    data: *mut (&'a CodegenContext, &'a SharedEmitter),
    llcx: &'a llvm::Context,
    old_handler: Option<&'a llvm::DiagnosticHandler>,
}

impl<'a> DiagnosticHandlers<'a> {
    pub(crate) fn new(
        cgcx: &'a CodegenContext,
        shared_emitter: &'a SharedEmitter,
        llcx: &'a llvm::Context,
        module: &ModuleCodegen<ModuleLlvm>,
        stage: CodegenDiagnosticsStage,
    ) -> Self {
        let remark_passes_all: bool;
        let remark_passes: Vec<CString>;
        match &cgcx.remark {
            Passes::All => {
                remark_passes_all = true;
                remark_passes = Vec::new();
            }
            Passes::Some(passes) => {
                remark_passes_all = false;
                remark_passes =
                    passes.iter().map(|name| CString::new(name.as_str()).unwrap()).collect();
            }
        };
        let remark_passes: Vec<*const c_char> =
            remark_passes.iter().map(|name: &CString| name.as_ptr()).collect();
        let remark_file = cgcx
            .remark_dir
            .as_ref()
            // Use the .opt.yaml file suffix, which is supported by LLVM's opt-viewer.
            .map(|dir| {
                let stage_suffix = match stage {
                    CodegenDiagnosticsStage::Codegen => "codegen",
                    CodegenDiagnosticsStage::Opt => "opt",
                    CodegenDiagnosticsStage::LTO => "lto",
                };
                dir.join(format!("{}.{stage_suffix}.opt.yaml", module.name))
            })
            .and_then(|dir| dir.to_str().and_then(|p| CString::new(p).ok()));

        let pgo_available = cgcx.module_config.pgo_use.is_some();
        let data = Box::into_raw(Box::new((cgcx, shared_emitter)));
        unsafe {
            let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx);
            llvm::LLVMRustContextConfigureDiagnosticHandler(
                llcx,
                diagnostic_handler,
                data.cast(),
                remark_passes_all,
                remark_passes.as_ptr(),
                remark_passes.len(),
                // The `as_ref()` is important here, otherwise the `CString` will be dropped
                // too soon!
                remark_file.as_ref().map(|dir| dir.as_ptr()).unwrap_or(std::ptr::null()),
                pgo_available,
            );
            DiagnosticHandlers { data, llcx, old_handler }
        }
    }
}

impl<'a> Drop for DiagnosticHandlers<'a> {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler);
            drop(Box::from_raw(self.data));
        }
    }
}

fn report_inline_asm(
    cgcx: &CodegenContext,
    msg: String,
    level: llvm::DiagnosticLevel,
    cookie: u64,
    source: Option<(String, Vec<InnerSpan>)>,
) -> InlineAsmError {
    // In LTO build we may get srcloc values from other crates which are invalid
    // since they use a different source map. To be safe we just suppress these
    // in LTO builds.
    let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
        SpanData::default()
    } else {
        SpanData {
            lo: BytePos::from_u32(cookie as u32),
            hi: BytePos::from_u32((cookie >> 32) as u32),
            ctxt: SyntaxContext::root(),
            parent: None,
        }
    };
    let level = match level {
        llvm::DiagnosticLevel::Error => Level::Error,
        llvm::DiagnosticLevel::Warning => Level::Warning,
        llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
    };
    let msg = msg.trim_prefix("error: ").to_string();
    InlineAsmError { span, msg, level, source }
}

unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
    if user.is_null() {
        return;
    }
    let (cgcx, shared_emitter) = unsafe { *(user as *const (&CodegenContext, &SharedEmitter)) };

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

    match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } {
        llvm::diagnostic::InlineAsm(inline) => {
            // FIXME use dcx
            shared_emitter.inline_asm_error(report_inline_asm(
                cgcx,
                inline.message,
                inline.level,
                inline.cookie,
                inline.source,
            ));
        }

        llvm::diagnostic::Optimization(opt) => {
            dcx.emit_note(FromLlvmOptimizationDiag {
                filename: &opt.filename,
                line: opt.line,
                column: opt.column,
                pass_name: &opt.pass_name,
                kind: match opt.kind {
                    OptimizationRemark => "success",
                    OptimizationMissed | OptimizationFailure => "missed",
                    OptimizationAnalysis
                    | OptimizationAnalysisFPCommute
                    | OptimizationAnalysisAliasing => "analysis",
                    OptimizationRemarkOther => "other",
                },
                message: &opt.message,
            });
        }
        llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
            let message = llvm::build_string(|s| unsafe {
                llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
            })
            .expect("non-UTF8 diagnostic");
            dcx.emit_warn(FromLlvmDiag { message });
        }
        llvm::diagnostic::Unsupported(diagnostic_ref) => {
            let message = llvm::build_string(|s| unsafe {
                llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
            })
            .expect("non-UTF8 diagnostic");
            dcx.emit_err(FromLlvmDiag { message });
        }
        llvm::diagnostic::UnknownDiagnostic(..) => {}
    }
}

fn get_pgo_gen_path(config: &ModuleConfig) -> Option<CString> {
    match config.pgo_gen {
        SwitchWithOptPath::Enabled(ref opt_dir_path) => {
            let path = if let Some(dir_path) = opt_dir_path {
                dir_path.join("default_%m.profraw")
            } else {
                PathBuf::from("default_%m.profraw")
            };

            Some(CString::new(format!("{}", path.display())).unwrap())
        }
        SwitchWithOptPath::Disabled => None,
    }
}

fn get_pgo_use_path(config: &ModuleConfig) -> Option<CString> {
    config
        .pgo_use
        .as_ref()
        .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap())
}

fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
    config
        .pgo_sample_use
        .as_ref()
        .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap())
}

fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
    config.instrument_coverage.then(|| c"default_%m_%p.profraw".to_owned())
}

// PreAD will run llvm opts but disable size increasing opts (vectorization, loop unrolling)
// DuringAD is the same as above, but also runs the enzyme opt and autodiff passes.
// PostAD will run all opts, including size increasing opts.
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum AutodiffStage {
    PreAD,
    DuringAD,
    PostAD,
}

pub(crate) unsafe fn llvm_optimize(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    dcx: DiagCtxtHandle<'_>,
    module: &ModuleCodegen<ModuleLlvm>,
    thin_lto_buffer: Option<&mut Option<Buffer>>,
    thin_lto_summary_buffer: Option<&mut Option<Buffer>>,
    config: &ModuleConfig,
    opt_level: config::OptLevel,
    opt_stage: llvm::OptStage,
    autodiff_stage: AutodiffStage,
) {
    // Enzyme:
    // The whole point of compiler based AD is to differentiate optimized IR instead of unoptimized
    // source code. However, benchmarks show that optimizations increasing the code size
    // tend to reduce AD performance. Therefore deactivate them before AD, then differentiate the code
    // and finally re-optimize the module, now with all optimizations available.
    // FIXME(ZuseZ4): In a future update we could figure out how to only optimize individual functions getting
    // differentiated.

    let consider_ad = config.autodiff.contains(&config::AutoDiff::Enable);
    let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
    let print_before_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModBefore);
    let print_after_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModAfter);
    let print_passes = config.autodiff.contains(&config::AutoDiff::PrintPasses);
    let merge_functions;
    let unroll_loops;
    let vectorize_slp;
    let vectorize_loop;

    // When we build rustc with enzyme/autodiff support, we want to postpone size-increasing
    // optimizations until after differentiation. Our pipeline is thus: (opt + enzyme), (full opt).
    // We therefore have two calls to llvm_optimize, if autodiff is used.
    //
    // We also must disable merge_functions, since autodiff placeholder/dummy bodies tend to be
    // identical. We run opts before AD, so there is a chance that LLVM will merge our dummies.
    // In that case, we lack some dummy bodies and can't replace them with the real AD code anymore.
    // We then would need to abort compilation. This was especially common in test cases.
    if consider_ad && autodiff_stage != AutodiffStage::PostAD {
        merge_functions = false;
        unroll_loops = false;
        vectorize_slp = false;
        vectorize_loop = false;
    } else {
        unroll_loops =
            opt_level != config::OptLevel::Size && opt_level != config::OptLevel::SizeMin;
        merge_functions = config.merge_functions;
        vectorize_slp = config.vectorize_slp;
        vectorize_loop = config.vectorize_loop;
    }
    trace!(?unroll_loops, ?vectorize_slp, ?vectorize_loop, ?run_enzyme);
    if thin_lto_buffer.is_some() {
        assert!(
            matches!(
                opt_stage,
                llvm::OptStage::PreLinkNoLTO
                    | llvm::OptStage::PreLinkFatLTO
                    | llvm::OptStage::PreLinkThinLTO
            ),
            "the bitcode for LTO can only be obtained at the pre-link stage"
        );
    }
    let pgo_gen_path = get_pgo_gen_path(config);
    let pgo_use_path = get_pgo_use_path(config);
    let pgo_sample_use_path = get_pgo_sample_use_path(config);
    let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO;
    let instr_profile_output_path = get_instr_profile_output_path(config);
    let sanitize_dataflow_abilist: Vec<_> = config
        .sanitizer_dataflow_abilist
        .iter()
        .map(|file| CString::new(file.as_str()).unwrap())
        .collect();
    let sanitize_dataflow_abilist_ptrs: Vec<_> =
        sanitize_dataflow_abilist.iter().map(|file| file.as_ptr()).collect();
    // Sanitizer instrumentation is only inserted during the pre-link optimization stage.
    let sanitizer_options = if !is_lto {
        Some(llvm::SanitizerOptions {
            sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
            sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
            sanitize_cfi: config.sanitizer.contains(SanitizerSet::CFI),
            sanitize_dataflow: config.sanitizer.contains(SanitizerSet::DATAFLOW),
            sanitize_dataflow_abilist: sanitize_dataflow_abilist_ptrs.as_ptr(),
            sanitize_dataflow_abilist_len: sanitize_dataflow_abilist_ptrs.len(),
            sanitize_kcfi: config.sanitizer.contains(SanitizerSet::KCFI),
            sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
            sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
            sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int,
            sanitize_realtime: config.sanitizer.contains(SanitizerSet::REALTIME),
            sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD),
            sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS),
            sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS),
            sanitize_kernel_address: config.sanitizer.contains(SanitizerSet::KERNELADDRESS),
            sanitize_kernel_address_recover: config
                .sanitizer_recover
                .contains(SanitizerSet::KERNELADDRESS),
        })
    } else {
        None
    };

    fn handle_offload<'ll>(cx: &'ll SimpleCx<'_>, old_fn: &llvm::Value) {
        let old_fn_ty = cx.get_type_of_global(old_fn);
        let old_param_types = cx.func_params_types(old_fn_ty);
        let old_param_count = old_param_types.len();
        if old_param_count == 0 {
            return;
        }

        let first_param = llvm::get_param(old_fn, 0);
        let c_name = llvm::get_value_name(first_param);
        let first_arg_name = str::from_utf8(&c_name).unwrap();
        // We might call llvm_optimize (and thus this code) multiple times on the same IR,
        // but we shouldn't add this helper ptr multiple times.
        // FIXME(offload): This could break if the user calls his first argument `dyn_ptr`.
        if first_arg_name == "dyn_ptr" {
            return;
        }

        // Create the new parameter list, with ptr as the first argument
        let mut new_param_types = Vec::with_capacity(old_param_count as usize + 1);
        new_param_types.push(cx.type_ptr());

        // This relies on undocumented LLVM knowledge that scalars must be passed as i64
        for &old_ty in &old_param_types {
            let new_ty = match cx.type_kind(old_ty) {
                TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::Integer => {
                    cx.type_i64()
                }
                _ => old_ty,
            };
            new_param_types.push(new_ty);
        }

        // Create the new function type
        let ret_ty = unsafe { llvm::LLVMGetReturnType(old_fn_ty) };
        let new_fn_ty = cx.type_func(&new_param_types, ret_ty);

        // Create the new function, with a temporary .offload name to avoid a name collision.
        let old_fn_name = String::from_utf8(llvm::get_value_name(old_fn)).unwrap();
        let new_fn_name = format!("{}.offload", &old_fn_name);
        let new_fn = cx.add_func(&new_fn_name, new_fn_ty);
        let a0 = llvm::get_param(new_fn, 0);
        llvm::set_value_name(a0, CString::new("dyn_ptr").unwrap().as_bytes());

        let bb = SBuilder::append_block(cx, new_fn, "entry");
        let mut builder = SBuilder::build(cx, bb);

        let mut old_args_rebuilt = Vec::with_capacity(old_param_types.len());

        for (i, &old_ty) in old_param_types.iter().enumerate() {
            let new_arg = llvm::get_param(new_fn, (i + 1) as u32);

            let rebuilt = match cx.type_kind(old_ty) {
                TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::Integer => {
                    let num_bits = scalar_width(cx, old_ty);

                    let trunc = builder.trunc(new_arg, cx.type_ix(num_bits));
                    builder.bitcast(trunc, old_ty)
                }
                _ => new_arg,
            };

            old_args_rebuilt.push(rebuilt);
        }

        builder.ret_void();

        // Here we map the old arguments to the new arguments, with an offset of 1 to make sure
        // that we don't use the newly added `%dyn_ptr`.
        unsafe {
            llvm::LLVMRustOffloadMapper(old_fn, new_fn, old_args_rebuilt.as_ptr());
        }

        llvm::set_linkage(new_fn, llvm::get_linkage(old_fn));
        llvm::set_visibility(new_fn, llvm::get_visibility(old_fn));

        // Replace all uses of old_fn with new_fn (RAUW)
        unsafe {
            llvm::LLVMReplaceAllUsesWith(old_fn, new_fn);
        }
        let name = llvm::get_value_name(old_fn);
        unsafe {
            llvm::LLVMDeleteFunction(old_fn);
        }
        // Now we can re-use the old name, without name collision.
        llvm::set_value_name(new_fn, &name);
    }

    if cgcx.target_is_like_gpu && config.offload.contains(&config::Offload::Device) {
        let cx =
            SimpleCx::new(module.module_llvm.llmod(), module.module_llvm.llcx, cgcx.pointer_size);
        for func in cx.get_functions() {
            let offload_kernel = "offload-kernel";
            if attributes::has_string_attr(func, offload_kernel) {
                handle_offload(&cx, func);
            }
            attributes::remove_string_attr_from_llfn(func, offload_kernel);
        }
    }

    let mut llvm_profiler = prof
        .llvm_recording_enabled()
        .then(|| LlvmSelfProfiler::new(prof.get_self_profiler().unwrap()));

    let llvm_selfprofiler =
        llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut());

    let extra_passes = if !is_lto { config.passes.join(",") } else { "".to_string() };

    let llvm_plugins = config.llvm_plugins.join(",");

    let enzyme_fn = if consider_ad {
        let wrapper = llvm::EnzymeWrapper::get_instance();
        wrapper.registerEnzymeAndPassPipeline
    } else {
        std::ptr::null()
    };

    let result = unsafe {
        llvm::LLVMRustOptimize(
            module.module_llvm.llmod(),
            &*module.module_llvm.tm.raw(),
            to_pass_builder_opt_level(opt_level),
            opt_stage,
            cgcx.use_linker_plugin_lto,
            config.no_prepopulate_passes,
            config.verify_llvm_ir,
            config.lint_llvm_ir,
            thin_lto_buffer,
            thin_lto_summary_buffer,
            merge_functions,
            unroll_loops,
            vectorize_slp,
            vectorize_loop,
            config.no_builtins,
            config.emit_lifetime_markers,
            enzyme_fn,
            print_before_enzyme,
            print_after_enzyme,
            print_passes,
            sanitizer_options.as_ref(),
            pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
            pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
            config.instrument_coverage,
            instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
            pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
            config.debug_info_for_profiling,
            llvm_selfprofiler,
            selfprofile_before_pass_callback,
            selfprofile_after_pass_callback,
            extra_passes.as_c_char_ptr(),
            extra_passes.len(),
            llvm_plugins.as_c_char_ptr(),
            llvm_plugins.len(),
        )
    };

    if cgcx.target_is_like_gpu && config.offload.contains(&config::Offload::Device) {
        let device_path = cgcx.output_filenames.path(OutputType::Object);
        let device_dir = device_path.parent().unwrap();
        let device_out = device_dir.join("host.out");
        let device_out_c = path_to_c_string(device_out.as_path());
        unsafe {
            // 1) Bundle device module into offload image host.out (device TM)
            let ok = llvm::LLVMRustBundleImages(
                module.module_llvm.llmod(),
                module.module_llvm.tm.raw(),
                device_out_c.as_ptr(),
            );
            if !ok || !device_out.exists() {
                dcx.emit_err(crate::errors::OffloadBundleImagesFailed);
            }
        }
    }

    // This assumes that we previously compiled our kernels for a gpu target, which created a
    // `host.out` artifact. The user is supposed to provide us with a path to this artifact, we
    // don't need any other artifacts from the previous run. We will embed this artifact into our
    // LLVM-IR host module, to create a `host.o` ObjectFile, which we will write to disk.
    // The last, not yet automated steps uses the `clang-linker-wrapper` to process `host.o`.
    if !cgcx.target_is_like_gpu {
        if let Some(device_path) = config
            .offload
            .iter()
            .find_map(|o| if let config::Offload::Host(path) = o { Some(path) } else { None })
        {
            let device_pathbuf = PathBuf::from(device_path);
            if device_pathbuf.is_relative() {
                dcx.emit_err(crate::errors::OffloadWithoutAbsPath);
            } else if device_pathbuf
                .file_name()
                .and_then(|n| n.to_str())
                .is_some_and(|n| n != "host.out")
            {
                dcx.emit_err(crate::errors::OffloadWrongFileName);
            } else if !device_pathbuf.exists() {
                dcx.emit_err(crate::errors::OffloadNonexistingPath);
            }
            let host_path = cgcx.output_filenames.path(OutputType::Object);
            let host_dir = host_path.parent().unwrap();
            let out_obj = host_dir.join("host.o");
            let host_out_c = path_to_c_string(device_pathbuf.as_path());

            // 2) Finalize host: lib.bc + host.out -> host.o (host TM)
            // We create a full clone of our LLVM host module, since we will embed the device IR
            // into it, and this might break caching or incremental compilation otherwise.
            let llmod2 = llvm::LLVMCloneModule(module.module_llvm.llmod());
            let ok =
                unsafe { llvm::LLVMRustOffloadEmbedBufferInModule(llmod2, host_out_c.as_ptr()) };
            if !ok {
                dcx.emit_err(crate::errors::OffloadEmbedFailed);
            }
            write_output_file(
                dcx,
                module.module_llvm.tm.raw(),
                config.no_builtins,
                llmod2,
                &out_obj,
                None,
                llvm::FileType::ObjectFile,
                prof,
                true,
            );
            // We ignore cgcx.save_temps here and unconditionally always keep our `host.out` artifact.
            // Otherwise, recompiling the host code would fail since we deleted that device artifact
            // in the previous host compilation, which would be confusing at best.
        }
    }
    result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
}

// Unsafe due to LLVM calls.
pub(crate) fn optimize(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: &SharedEmitter,
    module: &mut ModuleCodegen<ModuleLlvm>,
    config: &ModuleConfig,
) {
    let _timer = prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name);

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

    let llcx = &*module.module_llvm.llcx;
    let _handlers =
        DiagnosticHandlers::new(cgcx, shared_emitter, llcx, module, CodegenDiagnosticsStage::Opt);

    if module.kind == ModuleKind::Regular {
        save_temp_bitcode(cgcx, module, "no-opt");
    }

    // FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts

    if let Some(opt_level) = config.opt_level {
        let opt_stage = match cgcx.lto {
            Lto::Fat => llvm::OptStage::PreLinkFatLTO,
            Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO,
            _ if cgcx.use_linker_plugin_lto => llvm::OptStage::PreLinkThinLTO,
            _ => llvm::OptStage::PreLinkNoLTO,
        };

        // If we know that we will later run AD, then we disable vectorization and loop unrolling.
        // Otherwise we pretend AD is already done and run the normal opt pipeline (=PostAD).
        let consider_ad = config.autodiff.contains(&config::AutoDiff::Enable);
        let autodiff_stage = if consider_ad { AutodiffStage::PreAD } else { AutodiffStage::PostAD };
        // The embedded bitcode is used to run LTO/ThinLTO.
        // The bitcode obtained during the `codegen` phase is no longer suitable for performing LTO.
        // It may have undergone LTO due to ThinLocal, so we need to obtain the embedded bitcode at
        // this point.
        let (mut thin_lto_buffer, mut thin_lto_summary_buffer) = if (module.kind
            == ModuleKind::Regular
            && config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full))
            || config.emit_thin_lto_summary
        {
            (Some(None), config.emit_thin_lto_summary.then_some(None))
        } else {
            (None, None)
        };
        unsafe {
            llvm_optimize(
                cgcx,
                prof,
                dcx,
                module,
                thin_lto_buffer.as_mut(),
                thin_lto_summary_buffer.as_mut(),
                config,
                opt_level,
                opt_stage,
                autodiff_stage,
            )
        };
        if let Some(thin_lto_buffer) = thin_lto_buffer {
            let thin_lto_buffer = thin_lto_buffer.unwrap();
            module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec());
            let bc_summary_out = cgcx.output_filenames.temp_path_for_cgu(
                OutputType::ThinLinkBitcode,
                &module.name,
                cgcx.invocation_temp.as_deref(),
            );
            if let Some(thin_lto_summary_buffer) = thin_lto_summary_buffer
                && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
            {
                let thin_lto_summary_buffer = thin_lto_summary_buffer.unwrap();
                let summary_data = thin_lto_summary_buffer.data();
                prof.artifact_size(
                    "llvm_bitcode_summary",
                    thin_link_bitcode_filename.to_string_lossy(),
                    summary_data.len() as u64,
                );
                let _timer = prof.generic_activity_with_arg(
                    "LLVM_module_codegen_emit_bitcode_summary",
                    &*module.name,
                );
                if let Err(err) = fs::write(&bc_summary_out, summary_data) {
                    dcx.emit_err(WriteBytecode { path: &bc_summary_out, err });
                }
            }
        }
    }
}

pub(crate) fn codegen(
    cgcx: &CodegenContext,
    prof: &SelfProfilerRef,
    shared_emitter: &SharedEmitter,
    module: ModuleCodegen<ModuleLlvm>,
    config: &ModuleConfig,
) -> CompiledModule {
    let _timer = prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name);

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

    {
        let llmod = module.module_llvm.llmod();
        let llcx = &*module.module_llvm.llcx;
        let tm = &*module.module_llvm.tm;
        let _handlers = DiagnosticHandlers::new(
            cgcx,
            shared_emitter,
            llcx,
            &module,
            CodegenDiagnosticsStage::Codegen,
        );

        if cgcx.msvc_imps_needed {
            create_msvc_imps(cgcx, llcx, llmod);
        }

        // Note that if object files are just LLVM bitcode we write bitcode,
        // copy it to the .o file, and delete the bitcode if it wasn't
        // otherwise requested.

        let bc_out = cgcx.output_filenames.temp_path_for_cgu(
            OutputType::Bitcode,
            &module.name,
            cgcx.invocation_temp.as_deref(),
        );
        let obj_out = cgcx.output_filenames.temp_path_for_cgu(
            OutputType::Object,
            &module.name,
            cgcx.invocation_temp.as_deref(),
        );

        if config.bitcode_needed() {
            if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
                let thin = {
                    let _timer = prof.generic_activity_with_arg(
                        "LLVM_module_codegen_make_bitcode",
                        &*module.name,
                    );
                    ModuleBuffer::new(llmod, cgcx.lto != Lto::Fat)
                };
                let data = thin.data();
                let _timer = prof
                    .generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name);
                if let Some(bitcode_filename) = bc_out.file_name() {
                    prof.artifact_size(
                        "llvm_bitcode",
                        bitcode_filename.to_string_lossy(),
                        data.len() as u64,
                    );
                }
                if let Err(err) = fs::write(&bc_out, data) {
                    dcx.emit_err(WriteBytecode { path: &bc_out, err });
                }
            }

            if config.embed_bitcode() && module.kind == ModuleKind::Regular {
                let _timer = prof
                    .generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name);
                let thin_bc =
                    module.thin_lto_buffer.as_deref().expect("cannot find embedded bitcode");
                embed_bitcode(cgcx, llcx, llmod, &thin_bc);
            }
        }

        if config.emit_ir {
            let _timer =
                prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name);
            let out = cgcx.output_filenames.temp_path_for_cgu(
                OutputType::LlvmAssembly,
                &module.name,
                cgcx.invocation_temp.as_deref(),
            );
            let out_c = path_to_c_string(&out);

            extern "C" fn demangle_callback(
                input_ptr: *const c_char,
                input_len: size_t,
                output_ptr: *mut c_char,
                output_len: size_t,
            ) -> size_t {
                let input =
                    unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };

                let Ok(input) = str::from_utf8(input) else { return 0 };

                let output = unsafe {
                    slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
                };
                let mut cursor = io::Cursor::new(output);

                let Ok(demangled) = rustc_demangle::try_demangle(input) else { return 0 };

                if write!(cursor, "{demangled:#}").is_err() {
                    // Possible only if provided buffer is not big enough
                    return 0;
                }

                cursor.position() as size_t
            }

            let result =
                unsafe { llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback) };

            if result == llvm::LLVMRustResult::Success {
                record_artifact_size(prof, "llvm_ir", &out);
            }

            result
                .into_result()
                .unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteIr { path: &out }));
        }

        if config.emit_asm {
            let _timer =
                prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name);
            let path = cgcx.output_filenames.temp_path_for_cgu(
                OutputType::Assembly,
                &module.name,
                cgcx.invocation_temp.as_deref(),
            );

            // We can't use the same module for asm and object code output,
            // because that triggers various errors like invalid IR or broken
            // binaries. So we must clone the module to produce the asm output
            // if we are also producing object code.
            let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj {
                llvm::LLVMCloneModule(llmod)
            } else {
                llmod
            };
            write_output_file(
                dcx,
                tm.raw(),
                config.no_builtins,
                llmod,
                &path,
                None,
                llvm::FileType::AssemblyFile,
                prof,
                config.verify_llvm_ir,
            );
        }

        match config.emit_obj {
            EmitObj::ObjectCode(_) => {
                let _timer =
                    prof.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name);

                let dwo_out = cgcx
                    .output_filenames
                    .temp_path_dwo_for_cgu(&module.name, cgcx.invocation_temp.as_deref());
                let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) {
                    // Don't change how DWARF is emitted when disabled.
                    (SplitDebuginfo::Off, _) => None,
                    // Don't provide a DWARF object path if split debuginfo is enabled but this is
                    // a platform that doesn't support Split DWARF.
                    _ if !cgcx.target_can_use_split_dwarf => None,
                    // Don't provide a DWARF object path in single mode, sections will be written
                    // into the object as normal but ignored by linker.
                    (_, SplitDwarfKind::Single) => None,
                    // Emit (a subset of the) DWARF into a separate dwarf object file in split
                    // mode.
                    (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
                };

                write_output_file(
                    dcx,
                    tm.raw(),
                    config.no_builtins,
                    llmod,
                    &obj_out,
                    dwo_out,
                    llvm::FileType::ObjectFile,
                    prof,
                    config.verify_llvm_ir,
                );
            }

            EmitObj::Bitcode => {
                debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
                if let Err(err) = link_or_copy(&bc_out, &obj_out) {
                    dcx.emit_err(CopyBitcode { err });
                }

                if !config.emit_bc {
                    debug!("removing_bitcode {:?}", bc_out);
                    ensure_removed(dcx, &bc_out);
                }
            }

            EmitObj::None => {}
        }

        record_llvm_cgu_instructions_stats(prof, &module.name, llmod);
    }

    // `.dwo` files are only emitted if:
    //
    // - Object files are being emitted (i.e. bitcode only or metadata only compilations will not
    //   produce dwarf objects, even if otherwise enabled)
    // - Target supports Split DWARF
    // - Split debuginfo is enabled
    // - Split DWARF kind is `split` (i.e. debuginfo is split into `.dwo` files, not different
    //   sections in the `.o` files).
    let dwarf_object_emitted = matches!(config.emit_obj, EmitObj::ObjectCode(_))
        && cgcx.target_can_use_split_dwarf
        && cgcx.split_debuginfo != SplitDebuginfo::Off
        && cgcx.split_dwarf_kind == SplitDwarfKind::Split;
    module.into_compiled_module(
        config.emit_obj != EmitObj::None,
        dwarf_object_emitted,
        config.emit_bc,
        config.emit_asm,
        config.emit_ir,
        &cgcx.output_filenames,
        cgcx.invocation_temp.as_deref(),
    )
}

fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: &[u8]) -> Vec<u8> {
    let mut asm = format!(".section {section_name},\"{section_flags}\"\n").into_bytes();
    asm.extend_from_slice(b".ascii \"");
    asm.reserve(data.len());
    for &byte in data {
        if byte == b'\\' || byte == b'"' {
            asm.push(b'\\');
            asm.push(byte);
        } else if byte < 0x20 || byte >= 0x80 {
            // Avoid non UTF-8 inline assembly. Use octal escape sequence, because it is fixed
            // width, while hex escapes will consume following characters.
            asm.push(b'\\');
            asm.push(b'0' + ((byte >> 6) & 0x7));
            asm.push(b'0' + ((byte >> 3) & 0x7));
            asm.push(b'0' + ((byte >> 0) & 0x7));
        } else {
            asm.push(byte);
        }
    }
    asm.extend_from_slice(b"\"\n");
    asm
}

pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr {
    if cgcx.target_is_like_darwin {
        c"__LLVM,__bitcode"
    } else if cgcx.target_is_like_aix {
        c".ipa"
    } else {
        c".llvmbc"
    }
}

/// Embed the bitcode of an LLVM module for LTO in the LLVM module itself.
fn embed_bitcode(
    cgcx: &CodegenContext,
    llcx: &llvm::Context,
    llmod: &llvm::Module,
    bitcode: &[u8],
) {
    // We're adding custom sections to the output object file, but we definitely
    // do not want these custom sections to make their way into the final linked
    // executable. The purpose of these custom sections is for tooling
    // surrounding object files to work with the LLVM IR, if necessary. For
    // example rustc's own LTO will look for LLVM IR inside of the object file
    // in these sections by default.
    //
    // To handle this is a bit different depending on the object file format
    // used by the backend, broken down into a few different categories:
    //
    // * Mach-O - this is for macOS. Inspecting the source code for the native
    //   linker here shows that the `.llvmbc` and `.llvmcmd` sections are
    //   automatically skipped by the linker. In that case there's nothing extra
    //   that we need to do here. We do need to make sure that the
    //   `__LLVM,__cmdline` section exists even though it is empty as otherwise
    //   ld64 rejects the object file.
    //
    // * Wasm - the native LLD linker is hard-coded to skip `.llvmbc` and
    //   `.llvmcmd` sections, so there's nothing extra we need to do.
    //
    // * COFF - if we don't do anything the linker will by default copy all
    //   these sections to the output artifact, not what we want! To subvert
    //   this we want to flag the sections we inserted here as
    //   `IMAGE_SCN_LNK_REMOVE`.
    //
    // * ELF - this is very similar to COFF above. One difference is that these
    //   sections are removed from the output linked artifact when
    //   `--gc-sections` is passed, which we pass by default. If that flag isn't
    //   passed though then these sections will show up in the final output.
    //   Additionally the flag that we need to set here is `SHF_EXCLUDE`.
    //
    // * XCOFF - AIX linker ignores content in .ipa and .info if no auxiliary
    //   symbol associated with these sections.
    //
    // Unfortunately, LLVM provides no way to set custom section flags. For ELF
    // and COFF we emit the sections using module level inline assembly for that
    // reason (see issue #90326 for historical background).

    if cgcx.target_is_like_darwin
        || cgcx.target_is_like_aix
        || cgcx.target_arch == "wasm32"
        || cgcx.target_arch == "wasm64"
    {
        // We don't need custom section flags, create LLVM globals.
        let llconst = common::bytes_in_context(llcx, bitcode);
        let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
        llvm::set_initializer(llglobal, llconst);

        llvm::set_section(llglobal, bitcode_section_name(cgcx));
        llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
        llvm::LLVMSetGlobalConstant(llglobal, llvm::TRUE);

        let llconst = common::bytes_in_context(llcx, &[]);
        let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
        llvm::set_initializer(llglobal, llconst);
        let section = if cgcx.target_is_like_darwin {
            c"__LLVM,__cmdline"
        } else if cgcx.target_is_like_aix {
            c".info"
        } else {
            c".llvmcmd"
        };
        llvm::set_section(llglobal, section);
        llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
    } else {
        // We need custom section flags, so emit module-level inline assembly.
        let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
        let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
        llvm::append_module_inline_asm(llmod, &asm);
        let asm = create_section_with_flags_asm(".llvmcmd", section_flags, &[]);
        llvm::append_module_inline_asm(llmod, &asm);
    }
}

// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
// This is required to satisfy `dllimport` references to static data in .rlibs
// when using MSVC linker. We do this only for data, as linker can fix up
// code references on its own.
// See #26591, #27438
fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) {
    if !cgcx.msvc_imps_needed {
        return;
    }
    // The x86 ABI seems to require that leading underscores are added to symbol
    // names, so we need an extra underscore on x86. There's also a leading
    // '\x01' here which disables LLVM's symbol mangling (e.g., no extra
    // underscores added in front).
    let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" };

    let ptr_ty = llvm_type_ptr(llcx);
    let globals = base::iter_globals(llmod)
        .filter(|&val| {
            llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage && !llvm::is_declaration(val)
        })
        .filter_map(|val| {
            // Exclude some symbols that we know are not Rust symbols.
            let name = llvm::get_value_name(val);
            if ignored(&name) { None } else { Some((val, name)) }
        })
        .map(move |(val, name)| {
            let mut imp_name = prefix.as_bytes().to_vec();
            imp_name.extend(name);
            let imp_name = CString::new(imp_name).unwrap();
            (imp_name, val)
        })
        .collect::<Vec<_>>();

    for (imp_name, val) in globals {
        let imp = llvm::add_global(llmod, ptr_ty, &imp_name);

        llvm::set_initializer(imp, val);
        llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
    }

    // Use this function to exclude certain symbols from `__imp` generation.
    fn ignored(symbol_name: &[u8]) -> bool {
        // These are symbols generated by LLVM's profiling instrumentation
        symbol_name.starts_with(b"__llvm_profile_")
    }
}

fn record_artifact_size(
    self_profiler_ref: &SelfProfilerRef,
    artifact_kind: &'static str,
    path: &Path,
) {
    // Don't stat the file if we are not going to record its size.
    if !self_profiler_ref.enabled() {
        return;
    }

    if let Some(artifact_name) = path.file_name() {
        let file_size = std::fs::metadata(path).map(|m| m.len()).unwrap_or(0);
        self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
    }
}

fn record_llvm_cgu_instructions_stats(prof: &SelfProfilerRef, name: &str, llmod: &llvm::Module) {
    if !prof.enabled() {
        return;
    }

    let total = unsafe { llvm::LLVMRustModuleInstructionStats(llmod) };
    prof.artifact_size("cgu_instructions", name, total);
}
