#![allow(non_camel_case_types)]

use rustc_hir::LangItem;
use rustc_hir::attrs::PeImportNameType;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Instance, TyCtxt};
use rustc_middle::{bug, mir, span_bug};
use rustc_session::cstore::{DllCallingConvention, DllImport, DllImportSymbolType};
use rustc_span::Span;
use rustc_target::spec::{CfgAbi, Env, Os, Target};

use crate::traits::*;

#[derive(Copy, Clone, Debug)]
pub enum IntPredicate {
    IntEQ,
    IntNE,
    IntUGT,
    IntUGE,
    IntULT,
    IntULE,
    IntSGT,
    IntSGE,
    IntSLT,
    IntSLE,
}

#[derive(Copy, Clone, Debug)]
pub enum RealPredicate {
    RealPredicateFalse,
    RealOEQ,
    RealOGT,
    RealOGE,
    RealOLT,
    RealOLE,
    RealONE,
    RealORD,
    RealUNO,
    RealUEQ,
    RealUGT,
    RealUGE,
    RealULT,
    RealULE,
    RealUNE,
    RealPredicateTrue,
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum AtomicRmwBinOp {
    AtomicXchg,
    AtomicAdd,
    AtomicSub,
    AtomicAnd,
    AtomicNand,
    AtomicOr,
    AtomicXor,
    AtomicMax,
    AtomicMin,
    AtomicUMax,
    AtomicUMin,
}

#[derive(Copy, Clone, Debug)]
pub enum SynchronizationScope {
    SingleThread,
    CrossThread,
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum TypeKind {
    Void,
    Half,
    Float,
    Double,
    X86_FP80,
    FP128,
    PPC_FP128,
    Label,
    Integer,
    Function,
    Struct,
    Array,
    Pointer,
    Vector,
    Metadata,
    Token,
    ScalableVector,
    BFloat,
    X86_AMX,
}

// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
//            the StableHash trait. Normally DepGraph::with_task() calls are
//            hidden behind queries, but CGU creation is a special case in two
//            ways: (1) it's not a query and (2) CGU are output nodes, so their
//            Fingerprints are not actually needed. It remains to be clarified
//            how exactly this case will be handled in the red/green system but
//            for now we content ourselves with providing a no-op StableHash
//            implementation for CGUs.
mod temp_stable_hash_impls {
    use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher};

    use crate::ModuleCodegen;

    impl<M> StableHash for ModuleCodegen<M> {
        fn stable_hash<Hcx: StableHashCtxt>(&self, _: &mut Hcx, _: &mut StableHasher) {
            // do nothing
        }
    }
}

pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
    bx: &Bx,
    span: Span,
    li: LangItem,
) -> (Bx::FnAbiOfResult, Bx::Value, Instance<'tcx>) {
    let tcx = bx.tcx();
    let def_id = tcx.require_lang_item(li, span);
    let instance = ty::Instance::mono(tcx, def_id);
    (
        bx.fn_abi_of_instance(instance, ty::List::empty()),
        bx.get_fn_addr(instance, Some(PacMetadata::default())),
        instance,
    )
}

pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
    bx: &mut Bx,
    llty: Bx::Type,
    mask_llty: Bx::Type,
    invert: bool,
) -> Bx::Value {
    let kind = bx.type_kind(llty);
    match kind {
        TypeKind::Integer => {
            // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
            let val = bx.int_width(llty) - 1;
            if invert {
                bx.const_int(mask_llty, !val as i64)
            } else {
                bx.const_uint(mask_llty, val)
            }
        }
        TypeKind::Vector => {
            let mask =
                shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
            bx.vector_splat(bx.vector_length(mask_llty), mask)
        }
        _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
    }
}

pub fn asm_const_to_str<'tcx>(
    tcx: TyCtxt<'tcx>,
    sp: Span,
    const_value: mir::ConstValue,
    ty_and_layout: TyAndLayout<'tcx>,
) -> String {
    let mir::ConstValue::Scalar(scalar) = const_value else {
        span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
    };
    let value = scalar.assert_scalar_int().to_bits(ty_and_layout.size);
    match ty_and_layout.ty.kind() {
        ty::Uint(_) => value.to_string(),
        ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
            ty::IntTy::I8 => (value as i8).to_string(),
            ty::IntTy::I16 => (value as i16).to_string(),
            ty::IntTy::I32 => (value as i32).to_string(),
            ty::IntTy::I64 => (value as i64).to_string(),
            ty::IntTy::I128 => (value as i128).to_string(),
            ty::IntTy::Isize => unreachable!(),
        },
        _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
    }
}

pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
    target.os == Os::Windows && target.env == Env::Gnu && target.cfg_abi == CfgAbi::Unspecified
}

pub fn i686_decorated_name(
    dll_import: &DllImport,
    mingw: bool,
    disable_name_mangling: bool,
    force_fully_decorated: bool,
) -> String {
    let name = dll_import.name.as_str();

    let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
        // No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
        // ignore `force_fully_decorated` and always partially decorate it.
        (_, Some(PeImportNameType::NoPrefix)) => (false, true),
        (false, Some(PeImportNameType::Undecorated)) => (false, false),
        _ => (true, true),
    };

    // Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
    let mut decorated_name = String::with_capacity(name.len() + 6);

    if disable_name_mangling {
        // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be
        // disabled.
        decorated_name.push('\x01');
    }

    let prefix = if add_prefix && dll_import.symbol_type == DllImportSymbolType::Function {
        match dll_import.calling_convention {
            DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
            DllCallingConvention::Stdcall(_) => (!mingw
                || dll_import.import_name_type == Some(PeImportNameType::Decorated))
            .then_some('_'),
            DllCallingConvention::Fastcall(_) => Some('@'),
        }
    } else if dll_import.symbol_type != DllImportSymbolType::Function && !mingw {
        // For static variables, prefix with '_' on MSVC.
        Some('_')
    } else {
        None
    };
    if let Some(prefix) = prefix {
        decorated_name.push(prefix);
    }

    decorated_name.push_str(name);

    if add_suffix && dll_import.symbol_type == DllImportSymbolType::Function {
        use std::fmt::Write;

        match dll_import.calling_convention {
            DllCallingConvention::C => {}
            DllCallingConvention::Stdcall(arg_list_size)
            | DllCallingConvention::Fastcall(arg_list_size) => {
                write!(&mut decorated_name, "@{arg_list_size}").unwrap();
            }
            DllCallingConvention::Vectorcall(arg_list_size) => {
                write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
            }
        }
    }

    decorated_name
}
