// See doc.rs for documentation.
mod doc;

use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;

use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
use self::namespace::mangled_name_of_instance;
use self::type_names::compute_debuginfo_type_name;
use self::metadata::{type_metadata, file_metadata, TypeMap};
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};

use crate::llvm;
use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DIArray, DIFlags,
    DISPFlags, DILexicalBlock};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ty::subst::{SubstsRef, GenericArgKind};

use crate::abi::FnAbi;
use crate::common::CodegenCx;
use crate::builder::Builder;
use crate::value::Value;
use rustc::ty::{self, ParamEnv, Ty, InstanceDef, Instance};
use rustc::mir;
use rustc::session::config::{self, DebugInfo};
use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_index::vec::IndexVec;
use rustc_codegen_ssa::debuginfo::type_names;
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope,
    VariableKind};

use libc::c_uint;
use std::cell::RefCell;
use std::ffi::{CStr, CString};

use smallvec::SmallVec;
use syntax_pos::{self, BytePos, Span, Pos};
use syntax::ast;
use syntax::symbol::Symbol;
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Size};
use rustc_codegen_ssa::traits::*;

pub mod gdb;
mod utils;
mod namespace;
pub mod metadata;
mod create_scope_map;
mod source_loc;

pub use self::create_scope_map::compute_mir_scopes;
pub use self::metadata::create_global_var_metadata;
pub use self::metadata::extend_scope_to_file;
pub use self::source_loc::set_source_location;

#[allow(non_upper_case_globals)]
const DW_TAG_auto_variable: c_uint = 0x100;
#[allow(non_upper_case_globals)]
const DW_TAG_arg_variable: c_uint = 0x101;

/// A context object for maintaining all state needed by the debuginfo module.
pub struct CrateDebugContext<'a, 'tcx> {
    llcontext: &'a llvm::Context,
    llmod: &'a llvm::Module,
    builder: &'a mut DIBuilder<'a>,
    created_files: RefCell<FxHashMap<(Option<String>, Option<String>), &'a DIFile>>,
    created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,

    type_map: RefCell<TypeMap<'a, 'tcx>>,
    namespace_map: RefCell<DefIdMap<&'a DIScope>>,

    // This collection is used to assert that composite types (structs, enums,
    // ...) have their members only set once:
    composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
}

impl Drop for CrateDebugContext<'a, 'tcx> {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
        }
    }
}

impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
    pub fn new(llmod: &'a llvm::Module) -> Self {
        debug!("CrateDebugContext::new");
        let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
        // DIBuilder inherits context from the module, so we'd better use the same one
        let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
        CrateDebugContext {
            llcontext,
            llmod,
            builder,
            created_files: Default::default(),
            created_enum_disr_types: Default::default(),
            type_map: Default::default(),
            namespace_map: RefCell::new(Default::default()),
            composite_types_completed: Default::default(),
        }
    }
}

/// Creates any deferred debug metadata nodes
pub fn finalize(cx: &CodegenCx<'_, '_>) {
    if cx.dbg_cx.is_none() {
        return;
    }

    debug!("finalize");

    if gdb::needs_gdb_debug_scripts_section(cx) {
        // Add a .debug_gdb_scripts section to this compile-unit. This will
        // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
        // which activates the Rust pretty printers for binary this section is
        // contained in.
        gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
    }

    unsafe {
        llvm::LLVMRustDIBuilderFinalize(DIB(cx));
        // Debuginfo generation in LLVM by default uses a higher
        // version of dwarf than macOS currently understands. We can
        // instruct LLVM to emit an older version of dwarf, however,
        // for macOS to understand. For more info see #11352
        // This can be overridden using --llvm-opts -dwarf-version,N.
        // Android has the same issue (#22398)
        if cx.sess().target.target.options.is_like_osx ||
           cx.sess().target.target.options.is_like_android {
            llvm::LLVMRustAddModuleFlag(cx.llmod,
                                        "Dwarf Version\0".as_ptr().cast(),
                                        2)
        }

        // Indicate that we want CodeView debug information on MSVC
        if cx.sess().target.target.options.is_like_msvc {
            llvm::LLVMRustAddModuleFlag(cx.llmod,
                                        "CodeView\0".as_ptr().cast(),
                                        1)
        }

        // Prevent bitcode readers from deleting the debug info.
        let ptr = "Debug Info Version\0".as_ptr();
        llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(),
                                    llvm::LLVMRustDebugMetadataVersion());
    };
}

impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
    fn declare_local(
        &mut self,
        dbg_context: &FunctionDebugContext<&'ll DIScope>,
        variable_name: ast::Name,
        variable_type: Ty<'tcx>,
        scope_metadata: &'ll DIScope,
        variable_alloca: Self::Value,
        direct_offset: Size,
        indirect_offsets: &[Size],
        variable_kind: VariableKind,
        span: Span,
    ) {
        assert!(!dbg_context.source_locations_enabled);
        let cx = self.cx();

        let file = span_start(cx, span).file;
        let file_metadata = file_metadata(cx,
                                          &file.name,
                                          dbg_context.defining_crate);

        let loc = span_start(cx, span);
        let type_metadata = type_metadata(cx, variable_type, span);

        let (argument_index, dwarf_tag) = match variable_kind {
            ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
            LocalVariable => (0, DW_TAG_auto_variable)
        };
        let align = cx.align_of(variable_type);

        // Convert the direct and indirect offsets to address ops.
        let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
        let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
        let mut addr_ops = SmallVec::<[_; 8]>::new();

        if direct_offset.bytes() > 0 {
            addr_ops.push(op_plus_uconst());
            addr_ops.push(direct_offset.bytes() as i64);
        }
        for &offset in indirect_offsets {
            addr_ops.push(op_deref());
            if offset.bytes() > 0 {
                addr_ops.push(op_plus_uconst());
                addr_ops.push(offset.bytes() as i64);
            }
        }

        let name = SmallCStr::new(&variable_name.as_str());
        let metadata = unsafe {
            llvm::LLVMRustDIBuilderCreateVariable(
                DIB(cx),
                dwarf_tag,
                scope_metadata,
                name.as_ptr(),
                file_metadata,
                loc.line as c_uint,
                type_metadata,
                cx.sess().opts.optimize != config::OptLevel::No,
                DIFlags::FlagZero,
                argument_index,
                align.bytes() as u32,
            )
        };
        source_loc::set_debug_location(self,
            InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
        unsafe {
            let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
            let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
                DIB(cx),
                variable_alloca,
                metadata,
                addr_ops.as_ptr(),
                addr_ops.len() as c_uint,
                debug_loc,
                self.llbb());

            llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
        }
        source_loc::set_debug_location(self, UnknownLocation);
    }

    fn set_source_location(
        &mut self,
        debug_context: &mut FunctionDebugContext<&'ll DIScope>,
        scope: &'ll DIScope,
        span: Span,
    ) {
        set_source_location(debug_context, &self, scope, span)
    }
    fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
        gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
    }

    fn set_var_name(&mut self, value: &'ll Value, name: &str) {
        // Avoid wasting time if LLVM value names aren't even enabled.
        if self.sess().fewer_names() {
            return;
        }

        // Only function parameters and instructions are local to a function,
        // don't change the name of anything else (e.g. globals).
        let param_or_inst = unsafe {
            llvm::LLVMIsAArgument(value).is_some() ||
            llvm::LLVMIsAInstruction(value).is_some()
        };
        if !param_or_inst {
            return;
        }

        let old_name = unsafe {
            CStr::from_ptr(llvm::LLVMGetValueName(value))
        };
        match old_name.to_str() {
            Ok("") => {}
            Ok(_) => {
                // Avoid replacing the name if it already exists.
                // While we could combine the names somehow, it'd
                // get noisy quick, and the usefulness is dubious.
                return;
            }
            Err(_) => return,
        }

        let cname = SmallCStr::new(name);
        unsafe {
            llvm::LLVMSetValueName(value, cname.as_ptr());
        }
    }
}

impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
    fn create_function_debug_context(
        &self,
        instance: Instance<'tcx>,
        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
        llfn: &'ll Value,
        mir: &mir::Body<'_>,
    ) -> Option<FunctionDebugContext<&'ll DIScope>> {
        if self.sess().opts.debuginfo == DebugInfo::None {
            return None;
        }

        if let InstanceDef::Item(def_id) = instance.def {
            if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
                return None;
            }
        }

        let span = mir.span;

        // This can be the case for functions inlined from another crate
        if span.is_dummy() {
            // FIXME(simulacrum): Probably can't happen; remove.
            return None;
        }

        let def_id = instance.def_id();
        let containing_scope = get_containing_scope(self, instance);
        let loc = span_start(self, span);
        let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);

        let function_type_metadata = unsafe {
            let fn_signature = get_function_signature(self, fn_abi);
            llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature)
        };

        // Find the enclosing function, in case this is a closure.
        let def_key = self.tcx().def_key(def_id);
        let mut name = def_key.disambiguated_data.data.to_string();

        let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);

        // Get_template_parameters() will append a `<...>` clause to the function
        // name if necessary.
        let generics = self.tcx().generics_of(enclosing_fn_def_id);
        let substs = instance.substs.truncate_to(self.tcx(), generics);
        let template_parameters = get_template_parameters(self,
                                                          &generics,
                                                          substs,
                                                          file_metadata,
                                                          &mut name);

        // Get the linkage_name, which is just the symbol name
        let linkage_name = mangled_name_of_instance(self, instance);

        let scope_line = span_start(self, span).line;

        let function_name = CString::new(name).unwrap();
        let linkage_name = SmallCStr::new(&linkage_name.name.as_str());

        let mut flags = DIFlags::FlagPrototyped;

        if fn_abi.ret.layout.abi.is_uninhabited() {
            flags |= DIFlags::FlagNoReturn;
        }

        let mut spflags = DISPFlags::SPFlagDefinition;
        if is_node_local_to_unit(self, def_id) {
            spflags |= DISPFlags::SPFlagLocalToUnit;
        }
        if self.sess().opts.optimize != config::OptLevel::No {
            spflags |= DISPFlags::SPFlagOptimized;
        }
        if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
            if id == def_id {
                spflags |= DISPFlags::SPFlagMainSubprogram;
            }
        }

        let fn_metadata = unsafe {
            llvm::LLVMRustDIBuilderCreateFunction(
                DIB(self),
                containing_scope,
                function_name.as_ptr(),
                linkage_name.as_ptr(),
                file_metadata,
                loc.line as c_uint,
                function_type_metadata,
                scope_line as c_uint,
                flags,
                spflags,
                llfn,
                template_parameters,
                None)
        };

        // Initialize fn debug context (including scopes).
        // FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`.
        let null_scope = DebugScope {
            scope_metadata: None,
            file_start_pos: BytePos(0),
            file_end_pos: BytePos(0)
        };
        let mut fn_debug_context = FunctionDebugContext {
            scopes: IndexVec::from_elem(null_scope, &mir.source_scopes),
            source_locations_enabled: false,
            defining_crate: def_id.krate,
        };

        // Fill in all the scopes, with the information from the MIR body.
        compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context);

        return Some(fn_debug_context);

        fn get_function_signature<'ll, 'tcx>(
            cx: &CodegenCx<'ll, 'tcx>,
            fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
        ) -> &'ll DIArray {
            if cx.sess().opts.debuginfo == DebugInfo::Limited {
                return create_DIArray(DIB(cx), &[]);
            }

            let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);

            // Return type -- llvm::DIBuilder wants this at index 0
            signature.push(if fn_abi.ret.is_ignore() {
                None
            } else {
                Some(type_metadata(cx, fn_abi.ret.layout.ty, syntax_pos::DUMMY_SP))
            });

            // Arguments types
            if cx.sess().target.target.options.is_like_msvc {
                // FIXME(#42800):
                // There is a bug in MSDIA that leads to a crash when it encounters
                // a fixed-size array of `u8` or something zero-sized in a
                // function-type (see #40477).
                // As a workaround, we replace those fixed-size arrays with a
                // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
                // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
                // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
                // This transformed type is wrong, but these function types are
                // already inaccurate due to ABI adjustments (see #42800).
                signature.extend(fn_abi.args.iter().map(|arg| {
                    let t = arg.layout.ty;
                    let t = match t.kind {
                        ty::Array(ct, _)
                            if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
                            cx.tcx.mk_imm_ptr(ct)
                        }
                        _ => t
                    };
                    Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
                }));
            } else {
                signature.extend(fn_abi.args.iter().map(|arg| {
                    Some(type_metadata(cx, arg.layout.ty, syntax_pos::DUMMY_SP))
                }));
            }

            create_DIArray(DIB(cx), &signature[..])
        }

        fn get_template_parameters<'ll, 'tcx>(
            cx: &CodegenCx<'ll, 'tcx>,
            generics: &ty::Generics,
            substs: SubstsRef<'tcx>,
            file_metadata: &'ll DIFile,
            name_to_append_suffix_to: &mut String,
        ) -> &'ll DIArray {
            if substs.types().next().is_none() {
                return create_DIArray(DIB(cx), &[]);
            }

            name_to_append_suffix_to.push('<');
            for (i, actual_type) in substs.types().enumerate() {
                if i != 0 {
                    name_to_append_suffix_to.push_str(",");
                }

                let actual_type =
                    cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
                // Add actual type name to <...> clause of function name
                let actual_type_name = compute_debuginfo_type_name(cx.tcx(),
                                                                   actual_type,
                                                                   true);
                name_to_append_suffix_to.push_str(&actual_type_name[..]);
            }
            name_to_append_suffix_to.push('>');

            // Again, only create type information if full debuginfo is enabled
            let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
                let names = get_parameter_names(cx, generics);
                substs.iter().zip(names).filter_map(|(kind, name)| {
                    if let GenericArgKind::Type(ty) = kind.unpack() {
                        let actual_type =
                            cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                        let actual_type_metadata =
                            type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
                        let name = SmallCStr::new(&name.as_str());
                        Some(unsafe {
                            Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                                DIB(cx),
                                None,
                                name.as_ptr(),
                                actual_type_metadata,
                                file_metadata,
                                0,
                                0,
                            ))
                        })
                    } else {
                        None
                    }
                }).collect()
            } else {
                vec![]
            };

            return create_DIArray(DIB(cx), &template_params[..]);
        }

        fn get_parameter_names(cx: &CodegenCx<'_, '_>,
                               generics: &ty::Generics)
                               -> Vec<Symbol> {
            let mut names = generics.parent.map_or(vec![], |def_id| {
                get_parameter_names(cx, cx.tcx.generics_of(def_id))
            });
            names.extend(generics.params.iter().map(|param| param.name));
            names
        }

        fn get_containing_scope<'ll, 'tcx>(
            cx: &CodegenCx<'ll, 'tcx>,
            instance: Instance<'tcx>,
        ) -> &'ll DIScope {
            // First, let's see if this is a method within an inherent impl. Because
            // if yes, we want to make the result subroutine DIE a child of the
            // subroutine's self-type.
            let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
                // If the method does *not* belong to a trait, proceed
                if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
                    let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
                        instance.substs,
                        ty::ParamEnv::reveal_all(),
                        &cx.tcx.type_of(impl_def_id),
                    );

                    // Only "class" methods are generally understood by LLVM,
                    // so avoid methods on other types (e.g., `<*mut T>::null`).
                    match impl_self_ty.kind {
                        ty::Adt(def, ..) if !def.is_box() => {
                            Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
                        }
                        _ => None
                    }
                } else {
                    // For trait method impls we still use the "parallel namespace"
                    // strategy
                    None
                }
            });

            self_type.unwrap_or_else(|| {
                namespace::item_namespace(cx, DefId {
                    krate: instance.def_id().krate,
                    index: cx.tcx
                             .def_key(instance.def_id())
                             .parent
                             .expect("get_containing_scope: missing parent?")
                })
            })
        }
    }

    fn create_vtable_metadata(
        &self,
        ty: Ty<'tcx>,
        vtable: Self::Value,
    ) {
        metadata::create_vtable_metadata(self, ty, vtable)
    }

    fn extend_scope_to_file(
         &self,
         scope_metadata: &'ll DIScope,
         file: &syntax_pos::SourceFile,
         defining_crate: CrateNum,
     ) -> &'ll DILexicalBlock {
         metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
     }

    fn debuginfo_finalize(&self) {
        finalize(self)
    }
}
