//! Code that is useful in various codegen modules.

use std::borrow::Borrow;

use libc::{c_char, c_uint};
use rustc_abi as abi;
use rustc_abi::HasDataLayout;
use rustc_abi::Primitive::Pointer;
use rustc_ast::Mutability;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hashes::Hash128;
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::DllImport;
use tracing::debug;

use crate::consts::const_alloc_to_llvm;
pub(crate) use crate::context::CodegenCx;
use crate::context::{GenericCx, SCx};
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
use crate::type_::Type;
use crate::value::Value;

/*
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
*
* An "extern" is an LLVM symbol we wind up emitting an undefined external
* reference to. This means "we don't have the thing in this compilation unit,
* please make sure you link it in at runtime". This could be a reference to
* C code found in a C library, or rust code found in a rust crate.
*
* Most "externs" are implicitly declared (automatically) as a result of a
* user declaring an extern _module_ dependency; this causes the rust driver
* to locate an extern crate, scan its compilation metadata, and emit extern
* declarations for any symbols used by the declaring crate.
*
* A "foreign" is an extern that references C (or other non-rust ABI) code.
* There is no metadata to scan for extern references so in these cases either
* a header-digester like bindgen, or manual function prototypes, have to
* serve as declarators. So these are usually given explicitly as prototype
* declarations, in rust code, with ABI attributes on them noting which ABI to
* link via.
*
* An "upcall" is a foreign call generated by the compiler (not corresponding
* to any user-written call in the code) into the runtime library, to perform
* some helper task such as bringing a task to life, allocating memory, etc.
*
*/

/// A structure representing an active landing pad for the duration of a basic
/// block.
///
/// Each `Block` may contain an instance of this, indicating whether the block
/// is part of a landing pad or not. This is used to make decision about whether
/// to emit `invoke` instructions (e.g., in a landing pad we don't continue to
/// use `invoke`) and also about various function call metadata.
///
/// For GNU exceptions (`landingpad` + `resume` instructions) this structure is
/// just a bunch of `None` instances (not too interesting), but for MSVC
/// exceptions (`cleanuppad` + `cleanupret` instructions) this contains data.
/// When inside of a landing pad, each function call in LLVM IR needs to be
/// annotated with which landing pad it's a part of. This is accomplished via
/// the `OperandBundleDef` value created for MSVC landing pads.
pub(crate) struct Funclet<'ll> {
    cleanuppad: &'ll Value,
    operand: llvm::OperandBundleBox<'ll>,
}

impl<'ll> Funclet<'ll> {
    pub(crate) fn new(cleanuppad: &'ll Value) -> Self {
        Funclet { cleanuppad, operand: llvm::OperandBundleBox::new("funclet", &[cleanuppad]) }
    }

    pub(crate) fn cleanuppad(&self) -> &'ll Value {
        self.cleanuppad
    }

    pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> {
        self.operand.as_ref()
    }
}

impl<'ll, CX: Borrow<SCx<'ll>>> BackendTypes for GenericCx<'ll, CX> {
    type Value = &'ll Value;
    type Metadata = &'ll Metadata;
    // FIXME(eddyb) replace this with a `Function` "subclass" of `Value`.
    type Function = &'ll Value;

    type BasicBlock = &'ll BasicBlock;
    type Type = &'ll Type;
    type Funclet = Funclet<'ll>;

    type DIScope = &'ll llvm::debuginfo::DIScope;
    type DILocation = &'ll llvm::debuginfo::DILocation;
    type DIVariable = &'ll llvm::debuginfo::DIVariable;
}

impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
    pub(crate) fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
        let len = u64::try_from(elts.len()).expect("LLVMConstArray2 elements len overflow");
        unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) }
    }

    pub(crate) fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
        bytes_in_context(self.llcx(), bytes)
    }

    pub(crate) fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
        unsafe {
            let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow");
            let r = llvm::LLVMGetAggregateElement(v, idx).unwrap();

            debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r);

            r
        }
    }
}

impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
    fn const_null(&self, t: &'ll Type) -> &'ll Value {
        unsafe { llvm::LLVMConstNull(t) }
    }

    fn const_undef(&self, t: &'ll Type) -> &'ll Value {
        unsafe { llvm::LLVMGetUndef(t) }
    }

    fn const_poison(&self, t: &'ll Type) -> &'ll Value {
        unsafe { llvm::LLVMGetPoison(t) }
    }

    fn const_bool(&self, val: bool) -> &'ll Value {
        self.const_uint(self.type_i1(), val as u64)
    }

    fn const_i8(&self, i: i8) -> &'ll Value {
        self.const_int(self.type_i8(), i as i64)
    }

    fn const_i16(&self, i: i16) -> &'ll Value {
        self.const_int(self.type_i16(), i as i64)
    }

    fn const_i32(&self, i: i32) -> &'ll Value {
        self.const_int(self.type_i32(), i as i64)
    }

    fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
        debug_assert!(
            self.type_kind(t) == TypeKind::Integer,
            "only allows integer types in const_int"
        );
        unsafe { llvm::LLVMConstInt(t, i as u64, True) }
    }

    fn const_u8(&self, i: u8) -> &'ll Value {
        self.const_uint(self.type_i8(), i as u64)
    }

    fn const_u32(&self, i: u32) -> &'ll Value {
        self.const_uint(self.type_i32(), i as u64)
    }

    fn const_u64(&self, i: u64) -> &'ll Value {
        self.const_uint(self.type_i64(), i)
    }

    fn const_u128(&self, i: u128) -> &'ll Value {
        self.const_uint_big(self.type_i128(), i)
    }

    fn const_usize(&self, i: u64) -> &'ll Value {
        let bit_size = self.data_layout().pointer_size().bits();
        if bit_size < 64 {
            // make sure it doesn't overflow
            assert!(i < (1 << bit_size));
        }

        self.const_uint(self.isize_ty, i)
    }

    fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value {
        debug_assert!(
            self.type_kind(t) == TypeKind::Integer,
            "only allows integer types in const_uint"
        );
        unsafe { llvm::LLVMConstInt(t, i, False) }
    }

    fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
        debug_assert!(
            self.type_kind(t) == TypeKind::Integer,
            "only allows integer types in const_uint_big"
        );
        unsafe {
            let words = [u as u64, (u >> 64) as u64];
            llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
        }
    }

    fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
        unsafe { llvm::LLVMConstReal(t, val) }
    }

    fn const_str(&self, s: &str) -> (&'ll Value, &'ll Value) {
        let mut const_str_cache = self.const_str_cache.borrow_mut();
        let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
            let sc = self.const_bytes(s.as_bytes());
            let sym = self.generate_local_symbol_name("str");
            let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
                bug!("symbol `{}` is already defined", sym);
            });
            llvm::set_initializer(g, sc);
            unsafe {
                llvm::LLVMSetGlobalConstant(g, True);
                llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
            }
            llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
            // Cast to default address space if globals are in a different addrspace
            let g = self.const_pointercast(g, self.type_ptr());
            const_str_cache.insert(s.to_owned(), g);
            g
        });
        let len = s.len();
        (str_global, self.const_usize(len as u64))
    }

    fn const_struct(&self, elts: &[&'ll Value], packed: bool) -> &'ll Value {
        struct_in_context(self.llcx, elts, packed)
    }

    fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
        let len = c_uint::try_from(elts.len()).expect("LLVMConstVector elements len overflow");
        unsafe { llvm::LLVMConstVector(elts.as_ptr(), len) }
    }

    fn const_to_opt_uint(&self, v: &'ll Value) -> Option<u64> {
        try_as_const_integral(v).and_then(|v| unsafe {
            let mut i = 0u64;
            let success = llvm::LLVMRustConstIntGetZExtValue(v, &mut i);
            success.then_some(i)
        })
    }

    fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option<u128> {
        try_as_const_integral(v).and_then(|v| unsafe {
            let (mut lo, mut hi) = (0u64, 0u64);
            let success = llvm::LLVMRustConstInt128Get(v, sign_ext, &mut hi, &mut lo);
            success.then_some(hi_lo_to_u128(lo, hi))
        })
    }

    fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value {
        let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
        match cv {
            Scalar::Int(int) => {
                let data = int.to_bits(layout.size(self));
                let llval = self.const_uint_big(self.type_ix(bitsize), data);
                if matches!(layout.primitive(), Pointer(_)) {
                    unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
                } else {
                    self.const_bitcast(llval, llty)
                }
            }
            Scalar::Ptr(ptr, _size) => {
                let (prov, offset) = ptr.prov_and_relative_offset();
                let global_alloc = self.tcx.global_alloc(prov.alloc_id());
                let base_addr = match global_alloc {
                    GlobalAlloc::Memory(alloc) => {
                        // For ZSTs directly codegen an aligned pointer.
                        // This avoids generating a zero-sized constant value and actually needing a
                        // real address at runtime.
                        if alloc.inner().len() == 0 {
                            assert_eq!(offset.bytes(), 0);
                            let llval = self.const_usize(alloc.inner().align.bytes());
                            return if matches!(layout.primitive(), Pointer(_)) {
                                unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
                            } else {
                                self.const_bitcast(llval, llty)
                            };
                        } else {
                            let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
                            let alloc = alloc.inner();
                            let value = match alloc.mutability {
                                Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
                                _ => self.static_addr_of_impl(init, alloc.align, None),
                            };
                            if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty()
                            {
                                let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
                                    let mut hasher = StableHasher::new();
                                    alloc.hash_stable(&mut hcx, &mut hasher);
                                    hasher.finish::<Hash128>()
                                });
                                llvm::set_value_name(
                                    value,
                                    format!("alloc_{hash:032x}").as_bytes(),
                                );
                            }
                            value
                        }
                    }
                    GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance),
                    GlobalAlloc::VTable(ty, dyn_ty) => {
                        let alloc = self
                            .tcx
                            .global_alloc(self.tcx.vtable_allocation((
                                ty,
                                dyn_ty.principal().map(|principal| {
                                    self.tcx.instantiate_bound_regions_with_erased(principal)
                                }),
                            )))
                            .unwrap_memory();
                        let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
                        let value = self.static_addr_of_impl(init, alloc.inner().align, None);
                        value
                    }
                    GlobalAlloc::Static(def_id) => {
                        assert!(self.tcx.is_static(def_id));
                        assert!(!self.tcx.is_thread_local_static(def_id));
                        self.get_static(def_id)
                    }
                };
                let base_addr_space = global_alloc.address_space(self);
                let llval = unsafe {
                    llvm::LLVMConstInBoundsGEP2(
                        self.type_i8(),
                        // Cast to the required address space if necessary
                        self.const_pointercast(base_addr, self.type_ptr_ext(base_addr_space)),
                        &self.const_usize(offset.bytes()),
                        1,
                    )
                };
                if !matches!(layout.primitive(), Pointer(_)) {
                    unsafe { llvm::LLVMConstPtrToInt(llval, llty) }
                } else {
                    self.const_bitcast(llval, llty)
                }
            }
        }
    }

    fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
        const_alloc_to_llvm(self, alloc, /*static*/ false)
    }

    fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
        unsafe {
            llvm::LLVMConstInBoundsGEP2(
                self.type_i8(),
                base_addr,
                &self.const_usize(offset.bytes()),
                1,
            )
        }
    }
}

/// Get the [LLVM type][Type] of a [`Value`].
pub(crate) fn val_ty(v: &Value) -> &Type {
    unsafe { llvm::LLVMTypeOf(v) }
}

pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
    unsafe {
        let ptr = bytes.as_ptr() as *const c_char;
        llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True)
    }
}

fn struct_in_context<'ll>(
    llcx: &'ll llvm::Context,
    elts: &[&'ll Value],
    packed: bool,
) -> &'ll Value {
    let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow");
    unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed as Bool) }
}

#[inline]
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
    ((hi as u128) << 64) | (lo as u128)
}

fn try_as_const_integral(v: &Value) -> Option<&ConstantInt> {
    unsafe { llvm::LLVMIsAConstantInt(v) }
}

pub(crate) fn get_dllimport<'tcx>(
    tcx: TyCtxt<'tcx>,
    id: DefId,
    name: &str,
) -> Option<&'tcx DllImport> {
    tcx.native_library(id)
        .and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
}

/// Extension trait for explicit casts to `*const c_char`.
pub(crate) trait AsCCharPtr {
    /// Equivalent to `self.as_ptr().cast()`, but only casts to `*const c_char`.
    fn as_c_char_ptr(&self) -> *const c_char;
}

impl AsCCharPtr for str {
    fn as_c_char_ptr(&self) -> *const c_char {
        self.as_ptr().cast()
    }
}

impl AsCCharPtr for [u8] {
    fn as_c_char_ptr(&self) -> *const c_char {
        self.as_ptr().cast()
    }
}
