/*
 * TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?)
 * TODO(antoyo): support #[inline] attributes.
 * TODO(antoyo): support LTO (gcc's equivalent to Full LTO is -flto -flto-partition=one — https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html).
 * For Thin LTO, this might be helpful:
// cspell:disable-next-line
 * In gcc 4.6 -fwhopr was removed and became default with -flto. The non-whopr path can still be executed via -flto-partition=none.
 * Or the new incremental LTO (https://www.phoronix.com/news/GCC-Incremental-LTO-Patches)?
 *
 * Maybe some missing optimizations enabled by rustc's LTO is in there: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
// cspell:disable-next-line
 * Like -fipa-icf (should be already enabled) and maybe -fdevirtualize-at-ltrans.
 * TODO: disable debug info always being emitted. Perhaps this slows down things?
 *
 * TODO(antoyo): remove the patches.
 */

#![allow(internal_features)]
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
#![feature(rustc_private)]
#![recursion_limit = "256"]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![deny(clippy::pattern_type_mismatch)]
#![allow(clippy::needless_lifetimes, clippy::uninlined_format_args)]

// These crates are pulled from the sysroot because they are part of
// rustc's public API, so we need to ensure version compatibility.
extern crate smallvec;
#[macro_use]
extern crate tracing;

// The rustc crates we need
extern crate rustc_abi;
extern crate rustc_apfloat;
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fluent_macro;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_index;
#[cfg(feature = "master")]
extern crate rustc_interface;
extern crate rustc_macros;
extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
extern crate rustc_type_ir;

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

mod abi;
mod allocator;
mod asm;
mod attributes;
mod back;
mod base;
mod builder;
mod callee;
mod common;
mod consts;
mod context;
mod coverageinfo;
mod debuginfo;
mod declare;
mod errors;
mod gcc_util;
mod int;
mod intrinsic;
mod mono_item;
mod type_;
mod type_of;

use std::any::Any;
use std::fmt::Debug;
use std::ops::Deref;
use std::path::PathBuf;
#[cfg(not(feature = "master"))]
use std::sync::atomic::AtomicBool;
#[cfg(not(feature = "master"))]
use std::sync::atomic::Ordering;
use std::sync::{Arc, Mutex};

use back::lto::{ThinBuffer, ThinData};
use gccjit::{CType, Context, OptimizationLevel};
#[cfg(feature = "master")]
use gccjit::{TargetInfo, Version};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
use rustc_codegen_ssa::back::write::{
    CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::base::codegen_crate;
use rustc_codegen_ssa::target_features::cfg_target_feature;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_errors::DiagCtxtHandle;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
use rustc_middle::util::Providers;
use rustc_session::Session;
use rustc_session::config::{OptLevel, OutputFilenames};
use rustc_span::Symbol;
use rustc_span::fatal_error::FatalError;
use rustc_target::spec::RelocModel;
use tempfile::TempDir;

use crate::back::lto::ModuleBuffer;
use crate::gcc_util::target_cpu;

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

pub struct PrintOnPanic<F: Fn() -> String>(pub F);

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

#[cfg(not(feature = "master"))]
#[derive(Debug)]
pub struct TargetInfo {
    supports_128bit_integers: AtomicBool,
}

#[cfg(not(feature = "master"))]
impl TargetInfo {
    fn cpu_supports(&self, _feature: &str) -> bool {
        false
    }

    fn supports_target_dependent_type(&self, typ: CType) -> bool {
        match typ {
            CType::UInt128t | CType::Int128t => {
                if self.supports_128bit_integers.load(Ordering::SeqCst) {
                    return true;
                }
            }
            _ => (),
        }
        false
    }
}

#[derive(Clone)]
pub struct LockedTargetInfo {
    info: Arc<Mutex<IntoDynSyncSend<TargetInfo>>>,
}

impl Debug for LockedTargetInfo {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.info.lock().expect("lock").fmt(formatter)
    }
}

impl LockedTargetInfo {
    fn cpu_supports(&self, feature: &str) -> bool {
        self.info.lock().expect("lock").cpu_supports(feature)
    }

    fn supports_target_dependent_type(&self, typ: CType) -> bool {
        self.info.lock().expect("lock").supports_target_dependent_type(typ)
    }
}

#[derive(Clone)]
pub struct GccCodegenBackend {
    target_info: LockedTargetInfo,
}

impl CodegenBackend for GccCodegenBackend {
    fn locale_resource(&self) -> &'static str {
        crate::DEFAULT_LOCALE_RESOURCE
    }

    fn init(&self, _sess: &Session) {
        #[cfg(feature = "master")]
        {
            let target_cpu = target_cpu(_sess);

            // Get the second TargetInfo with the correct CPU features by setting the arch.
            let context = Context::default();
            if target_cpu != "generic" {
                context.add_command_line_option(format!("-march={}", target_cpu));
            }

            **self.target_info.info.lock().expect("lock") = context.get_target_info();
        }

        #[cfg(feature = "master")]
        gccjit::set_global_personality_function_name(b"rust_eh_personality\0");

        #[cfg(not(feature = "master"))]
        {
            let temp_dir = TempDir::new().expect("cannot create temporary directory");
            let temp_file = temp_dir.keep().join("result.asm");
            let check_context = Context::default();
            check_context.set_print_errors_to_stderr(false);
            let _int128_ty = check_context.new_c_type(CType::UInt128t);
            // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
            check_context.compile_to_file(
                gccjit::OutputKind::Assembler,
                temp_file.to_str().expect("path to str"),
            );
            self.target_info
                .info
                .lock()
                .expect("lock")
                .supports_128bit_integers
                .store(check_context.get_last_error() == Ok(None), Ordering::SeqCst);
        }
    }

    fn provide(&self, providers: &mut Providers) {
        providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
    }

    fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
        let target_cpu = target_cpu(tcx.sess);
        let res = codegen_crate(self.clone(), tcx, target_cpu.to_string());

        Box::new(res)
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        sess: &Session,
        _outputs: &OutputFilenames,
    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
        ongoing_codegen
            .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
            .expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
            .join(sess)
    }

    fn target_config(&self, sess: &Session) -> TargetConfig {
        target_config(sess, &self.target_info)
    }
}

fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
    let context = Context::default();
    if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
        context.add_command_line_option("-masm=intel");
    }
    #[cfg(feature = "master")]
    {
        context.set_special_chars_allowed_in_func_names("$.*");
        let version = Version::get();
        let version = format!("{}.{}.{}", version.major, version.minor, version.patch);
        context.set_output_ident(&format!(
            "rustc version {} with libgccjit {}",
            rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
            version,
        ));
    }
    // TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n.
    context.add_command_line_option("-fno-asynchronous-unwind-tables");
    context
}

impl ExtraBackendMethods for GccCodegenBackend {
    fn supports_parallel(&self) -> bool {
        false
    }

    fn codegen_allocator(
        &self,
        tcx: TyCtxt<'_>,
        module_name: &str,
        kind: AllocatorKind,
        alloc_error_handler_kind: AllocatorKind,
    ) -> Self::Module {
        let mut mods = GccContext {
            context: Arc::new(SyncContext::new(new_context(tcx))),
            relocation_model: tcx.sess.relocation_model(),
            should_combine_object_files: false,
            temp_dir: None,
        };

        unsafe {
            allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind);
        }
        mods
    }

    fn compile_codegen_unit(
        &self,
        tcx: TyCtxt<'_>,
        cgu_name: Symbol,
    ) -> (ModuleCodegen<Self::Module>, u64) {
        base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone())
    }

    fn target_machine_factory(
        &self,
        _sess: &Session,
        _opt_level: OptLevel,
        _features: &[String],
    ) -> TargetMachineFactoryFn<Self> {
        // TODO(antoyo): set opt level.
        Arc::new(|_| Ok(()))
    }
}

pub struct GccContext {
    context: Arc<SyncContext>,
    /// This field is needed in order to be able to set the flag -fPIC when necessary when doing
    /// LTO.
    relocation_model: RelocModel,
    should_combine_object_files: bool,
    // Temporary directory used by LTO. We keep it here so that it's not removed before linking.
    temp_dir: Option<TempDir>,
}

struct SyncContext {
    context: Context<'static>,
}

impl SyncContext {
    fn new(context: Context<'static>) -> Self {
        Self { context }
    }
}

impl Deref for SyncContext {
    type Target = Context<'static>;

    fn deref(&self) -> &Self::Target {
        &self.context
    }
}

unsafe impl Send for SyncContext {}
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()".
unsafe impl Sync for SyncContext {}

impl WriteBackendMethods for GccCodegenBackend {
    type Module = GccContext;
    type TargetMachine = ();
    type TargetMachineError = ();
    type ModuleBuffer = ModuleBuffer;
    type ThinData = ThinData;
    type ThinBuffer = ThinBuffer;

    fn run_and_optimize_fat_lto(
        cgcx: &CodegenContext<Self>,
        // FIXME(bjorn3): Limit LTO exports to these symbols
        _exported_symbols_for_lto: &[String],
        each_linked_rlib_for_lto: &[PathBuf],
        modules: Vec<FatLtoInput<Self>>,
    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
        back::lto::run_fat(cgcx, each_linked_rlib_for_lto, modules)
    }

    fn run_thin_lto(
        cgcx: &CodegenContext<Self>,
        // FIXME(bjorn3): Limit LTO exports to these symbols
        _exported_symbols_for_lto: &[String],
        each_linked_rlib_for_lto: &[PathBuf],
        modules: Vec<(String, Self::ThinBuffer)>,
        cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
    ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
        back::lto::run_thin(cgcx, each_linked_rlib_for_lto, modules, cached_modules)
    }

    fn print_pass_timings(&self) {
        unimplemented!();
    }

    fn print_statistics(&self) {
        unimplemented!()
    }

    fn optimize(
        _cgcx: &CodegenContext<Self>,
        _dcx: DiagCtxtHandle<'_>,
        module: &mut ModuleCodegen<Self::Module>,
        config: &ModuleConfig,
    ) -> Result<(), FatalError> {
        module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
        Ok(())
    }

    fn optimize_thin(
        cgcx: &CodegenContext<Self>,
        thin: ThinModule<Self>,
    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
        back::lto::optimize_thin_module(thin, cgcx)
    }

    fn codegen(
        cgcx: &CodegenContext<Self>,
        module: ModuleCodegen<Self::Module>,
        config: &ModuleConfig,
    ) -> Result<CompiledModule, FatalError> {
        back::write::codegen(cgcx, module, config)
    }

    fn prepare_thin(
        module: ModuleCodegen<Self::Module>,
        emit_summary: bool,
    ) -> (String, Self::ThinBuffer) {
        back::lto::prepare_thin(module, emit_summary)
    }

    fn serialize_module(_module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
        unimplemented!();
    }
}

/// This is the entrypoint for a hot plugged rustc_codegen_gccjit
#[unsafe(no_mangle)]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    #[cfg(feature = "master")]
    let info = {
        // Check whether the target supports 128-bit integers, and sized floating point types (like
        // Float16).
        let context = Context::default();
        Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
    };
    #[cfg(not(feature = "master"))]
    let info = Arc::new(Mutex::new(IntoDynSyncSend(TargetInfo {
        supports_128bit_integers: AtomicBool::new(false),
    })));

    Box::new(GccCodegenBackend { target_info: LockedTargetInfo { info } })
}

fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
    match optlevel {
        None => OptimizationLevel::None,
        Some(level) => match level {
            OptLevel::No => OptimizationLevel::None,
            OptLevel::Less => OptimizationLevel::Limited,
            OptLevel::More => OptimizationLevel::Standard,
            OptLevel::Aggressive => OptimizationLevel::Aggressive,
            OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
        },
    }
}

/// Returns the features that should be set in `cfg(target_feature)`.
fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig {
    let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| {
        // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
        if feature == "neon" {
            return false;
        }
        target_info.cpu_supports(feature)
        // cSpell:disable
        /*
          adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
          avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
          bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
          sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
        */
        // cSpell:enable
    });

    let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16);
    let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128);

    TargetConfig {
        target_features,
        unstable_target_features,
        // There are no known bugs with GCC support for f16 or f128
        has_reliable_f16,
        has_reliable_f16_math: has_reliable_f16,
        has_reliable_f128,
        has_reliable_f128_math: has_reliable_f128,
    }
}
