// tidy-alphabetical-start
// Note: please avoid adding other feature gates where possible
#![feature(rustc_private)]
// Only used to define intrinsics in `compiler_builtins.rs`.
#![cfg_attr(feature = "jit", feature(f16))]
#![cfg_attr(feature = "jit", feature(f128))]
// Note: please avoid adding other feature gates where possible
#![warn(rust_2018_idioms)]
#![warn(unreachable_pub)]
#![warn(unused_lifetimes)]
// tidy-alphabetical-end

#[macro_use]
extern crate rustc_middle;
extern crate rustc_abi;
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_log;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;

// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
extern crate rustc_driver;

use std::any::Any;
use std::cell::OnceCell;
use std::env;
use std::sync::Arc;

use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenResults, TargetConfig};
use rustc_log::tracing::info;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
use rustc_session::config::OutputFilenames;
use rustc_span::{Symbol, sym};
use rustc_target::spec::{Abi, Arch, Env, Os};

pub use crate::config::*;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod base;
mod cast;
mod codegen_f16_f128;
mod codegen_i128;
mod common;
mod compiler_builtins;
mod concurrency_limiter;
mod config;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod global_asm;
mod inline_asm;
mod intrinsics;
mod linkage;
mod main_shim;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod toolchain;
mod unsize;
mod unwind_module;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::{
        AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot,
        StackSlotData, StackSlotKind, TrapCode, Type, Value, types,
    };
    pub(crate) use cranelift_module::{self, DataDescription, FuncId, Linkage, Module};
    pub(crate) use rustc_abi::{BackendRepr, FIRST_VARIANT, FieldIdx, Scalar, Size, VariantIdx};
    pub(crate) use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_index::Idx;
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
    pub(crate) use rustc_middle::ty::{
        self, FloatTy, Instance, InstanceKind, IntTy, Ty, TyCtxt, UintTy,
    };
    pub(crate) use rustc_span::Span;

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{codegen_operand, codegen_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::value_and_place::{CPlace, CValue};
}

struct PrintOnPanic<F: Fn() -> String>(F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
    fn drop(&mut self) {
        if ::std::thread::panicking() {
            println!("{}", (self.0)());
        }
    }
}

pub struct CraneliftCodegenBackend {
    pub config: OnceCell<BackendConfig>,
}

impl CodegenBackend for CraneliftCodegenBackend {
    fn name(&self) -> &'static str {
        "cranelift"
    }

    fn init(&self, sess: &Session) {
        use rustc_session::config::{InstrumentCoverage, Lto};
        match sess.lto() {
            Lto::No | Lto::ThinLocal => {}
            Lto::Thin | Lto::Fat => {
                sess.dcx().warn("LTO is not supported. You may get a linker error.")
            }
        }

        if sess.opts.cg.instrument_coverage() != InstrumentCoverage::No {
            sess.dcx()
                .fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift");
        }

        let config = self.config.get_or_init(|| {
            BackendConfig::from_opts(&sess.opts.cg.llvm_args)
                .unwrap_or_else(|err| sess.dcx().fatal(err))
        });

        if config.jit_mode && !sess.opts.output_types.should_codegen() {
            sess.dcx().fatal("JIT mode doesn't work with `cargo check`");
        }
    }

    fn target_config(&self, sess: &Session) -> TargetConfig {
        // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
        let target_features = match sess.target.arch {
            Arch::X86_64 if sess.target.os != Os::None => {
                // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
                vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")]
            }
            Arch::AArch64 => match &sess.target.os {
                Os::None => vec![],
                // On macOS the aes, sha2 and sha3 features are enabled by default and ring
                // fails to compile on macOS when they are not present.
                Os::MacOs => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
                // AArch64 mandates Neon support
                _ => vec![sym::neon],
            },
            _ => vec![],
        };
        // FIXME do `unstable_target_features` properly
        let unstable_target_features = target_features.clone();

        // FIXME(f16_f128): `rustc_codegen_llvm` currently disables support on Windows GNU
        // targets due to GCC using a different ABI than LLVM. Therefore `f16` and `f128`
        // won't be available when using a LLVM-built sysroot.
        let has_reliable_f16_f128 = !(sess.target.arch == Arch::X86_64
            && sess.target.os == Os::Windows
            && sess.target.env == Env::Gnu
            && sess.target.abi != Abi::Llvm);

        TargetConfig {
            target_features,
            unstable_target_features,
            // `rustc_codegen_cranelift` polyfills functionality not yet
            // available in Cranelift.
            has_reliable_f16: has_reliable_f16_f128,
            has_reliable_f16_math: has_reliable_f16_f128,
            has_reliable_f128: has_reliable_f16_f128,
            has_reliable_f128_math: has_reliable_f16_f128,
        }
    }

    fn print_version(&self) {
        println!("Cranelift version: {}", cranelift_codegen::VERSION);
    }

    fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
        info!("codegen crate {}", tcx.crate_name(LOCAL_CRATE));
        let config = self.config.get().unwrap();
        if config.jit_mode {
            #[cfg(feature = "jit")]
            driver::jit::run_jit(tcx, config.jit_args.clone());

            #[cfg(not(feature = "jit"))]
            tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
        } else {
            driver::aot::run_aot(tcx)
        }
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        sess: &Session,
        outputs: &OutputFilenames,
    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
        ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(sess, outputs)
    }
}

/// Determine if the Cranelift ir verifier should run.
///
/// Returns true when `-Zverify-llvm-ir` is passed, the `CG_CLIF_ENABLE_VERIFIER` env var is set to
/// 1 or when cg_clif is compiled with debug assertions enabled or false otherwise.
fn enable_verifier(sess: &Session) -> bool {
    sess.verify_llvm_ir()
        || cfg!(debug_assertions)
        || env::var("CG_CLIF_ENABLE_VERIFIER").as_deref() == Ok("1")
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    match sess.target.llvm_target.parse() {
        Ok(triple) => triple,
        Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)),
    }
}

fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    flags_builder.set("is_pic", if jit { "false" } else { "true" }).unwrap();
    let enable_verifier = if enable_verifier(sess) { "true" } else { "false" };
    flags_builder.set("enable_verifier", enable_verifier).unwrap();
    flags_builder.set("regalloc_checker", enable_verifier).unwrap();

    let frame_ptr =
        { sess.target.options.frame_pointer }.ratchet(sess.opts.cg.force_frame_pointers);
    let preserve_frame_pointer = frame_ptr != rustc_target::spec::FramePointer::MayOmit;
    flags_builder
        .set("preserve_frame_pointers", if preserve_frame_pointer { "true" } else { "false" })
        .unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();

    if let Some(align) = sess.opts.unstable_opts.min_function_alignment {
        flags_builder
            .set("log2_min_function_alignment", &align.bytes().ilog2().to_string())
            .unwrap();
    }

    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less
        | OptLevel::More
        | OptLevel::Size
        | OptLevel::SizeMin
        | OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
    }

    if let target_lexicon::OperatingSystem::Windows = target_triple.operating_system {
        // FIXME remove dependency on this from the Rust ABI. cc bytecodealliance/wasmtime#9510
        flags_builder.enable("enable_multi_ret_implicit_sret").unwrap();
    }

    if let target_lexicon::Architecture::S390x = target_triple.architecture {
        // FIXME remove dependency on this from the Rust ABI. cc bytecodealliance/wasmtime#9510
        flags_builder.enable("enable_multi_ret_implicit_sret").unwrap();
    }

    if let target_lexicon::Architecture::Aarch64(_)
    | target_lexicon::Architecture::Riscv64(_)
    | target_lexicon::Architecture::X86_64 = target_triple.architecture
    {
        // Windows depends on stack probes to grow the committed part of the stack.
        // On other platforms it helps prevents stack smashing.
        flags_builder.enable("enable_probestack").unwrap();
        flags_builder.set("probestack_strategy", "inline").unwrap();
    } else {
        // __cranelift_probestack is not provided and inline stack probes are only supported on
        // AArch64, Riscv64 and x86_64.
        flags_builder.set("enable_probestack", "false").unwrap();
    }

    let flags = settings::Flags::new(flags_builder);

    let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
        Some("native") => cranelift_native::builder_with_options(true).unwrap(),
        Some(value) => {
            let mut builder =
                cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| {
                    sess.dcx().fatal(format!("can't compile for {}: {}", target_triple, err));
                });
            if builder.enable(value).is_err() {
                sess.dcx()
                    .fatal("the specified target cpu isn't currently supported by Cranelift.");
            }
            builder
        }
        None => {
            let mut builder =
                cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| {
                    sess.dcx().fatal(format!("can't compile for {}: {}", target_triple, err));
                });
            if target_triple.architecture == target_lexicon::Architecture::X86_64 {
                // Only set the target cpu on x86_64 as Cranelift is missing
                // the target cpu list for most other targets.
                builder.enable(sess.target.cpu.as_ref()).unwrap();
            }
            builder
        }
    };

    match isa_builder.finish(flags) {
        Ok(target_isa) => target_isa,
        Err(err) => sess.dcx().fatal(format!("failed to build TargetIsa: {}", err)),
    }
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[unsafe(no_mangle)]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend { config: OnceCell::new() })
}
