//! Handling of everything related to debuginfo.

mod emit;
mod gcc_except_table;
mod line_info;
mod object;
mod types;
mod unwind;

use cranelift_codegen::ir::Endianness;
use cranelift_codegen::isa::TargetIsa;
use cranelift_module::DataId;
use gimli::write::{
    Address, AttributeValue, DwarfUnit, Expression, FileId, LineProgram, LineString, Range,
    RangeList, UnitEntryId,
};
use gimli::{AArch64, Encoding, Format, LineEncoding, Register, RiscV, RunTimeEndian, X86_64};
use indexmap::IndexSet;
use rustc_codegen_ssa::debuginfo::type_names;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefIdMap;
use rustc_session::Session;
use rustc_session::config::DebugInfo;
use rustc_span::{RemapPathScopeComponents, SourceFileHash, StableSourceFileId};
use rustc_target::callconv::FnAbi;

pub(crate) use self::emit::{DebugReloc, DebugRelocName};
pub(crate) use self::types::TypeDebugContext;
pub(crate) use self::unwind::{EXCEPTION_HANDLER_CATCH, EXCEPTION_HANDLER_CLEANUP, UnwindContext};
use crate::debuginfo::emit::{address_for_data, address_for_func};
use crate::prelude::*;

pub(crate) fn producer(sess: &Session) -> String {
    format!("rustc version {} with cranelift {}", sess.cfg_version, cranelift_codegen::VERSION)
}

pub(crate) struct DebugContext {
    endian: RunTimeEndian,

    dwarf: DwarfUnit,
    unit_range_list: RangeList,
    created_files: FxHashMap<(StableSourceFileId, SourceFileHash), FileId>,
    stack_pointer_register: Register,
    namespace_map: DefIdMap<UnitEntryId>,
    array_size_type: Option<UnitEntryId>,

    embed_source: bool,
}

pub(crate) struct FunctionDebugContext {
    entry_id: Option<UnitEntryId>,
    function_source_loc: (FileId, u64, u64),
    source_loc_set: IndexSet<(FileId, u64, u64)>,
}

impl DebugContext {
    pub(crate) fn new(
        tcx: TyCtxt<'_>,
        isa: &dyn TargetIsa,
        force_disable_debuginfo: bool,
        cgu_name: &str,
    ) -> Option<Self> {
        if tcx.sess.opts.debuginfo == DebugInfo::None
            || force_disable_debuginfo
            || tcx.sess.target.options.is_like_windows
        {
            return None;
        }

        let mut requested_dwarf_version = tcx.sess.dwarf_version();
        if tcx.sess.target.is_like_darwin && requested_dwarf_version > 4 {
            // Apple’s shipped debuggers still expect DWARF <= 4 by default.
            // Stay on v4 unless the user explicitly opts into a feature that
            // only works with v5 (e.g. -Zembed-source).
            if !tcx.sess.opts.unstable_opts.embed_source {
                requested_dwarf_version = 4;
            }
        }

        let encoding = Encoding {
            format: Format::Dwarf32,
            version: requested_dwarf_version as u16,
            address_size: isa.frontend_config().pointer_bytes(),
        };

        let embed_source = tcx.sess.opts.unstable_opts.embed_source && encoding.version >= 5;

        let endian = match isa.endianness() {
            Endianness::Little => RunTimeEndian::Little,
            Endianness::Big => RunTimeEndian::Big,
        };

        let stack_pointer_register = match isa.triple().architecture {
            target_lexicon::Architecture::Aarch64(_) => AArch64::SP,
            target_lexicon::Architecture::Riscv64(_) => RiscV::SP,
            target_lexicon::Architecture::X86_64 | target_lexicon::Architecture::X86_64h => {
                X86_64::RSP
            }
            _ => Register(u16::MAX),
        };

        let mut dwarf = DwarfUnit::new(encoding);

        let producer = producer(tcx.sess);
        let comp_dir = tcx
            .sess
            .source_map()
            .working_dir()
            .path(RemapPathScopeComponents::DEBUGINFO)
            .to_string_lossy();

        let (name, file_info) = match tcx.sess.local_crate_source_file() {
            Some(path) => {
                let name =
                    path.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy().into_owned();
                (name, None)
            }
            None => (tcx.crate_name(LOCAL_CRATE).to_string(), None),
        };

        let file_has_md5 = file_info.is_some();
        let mut line_program = LineProgram::new(
            encoding,
            LineEncoding::default(),
            LineString::new(comp_dir.as_bytes(), encoding, &mut dwarf.line_strings),
            None,
            LineString::new(name.as_bytes(), encoding, &mut dwarf.line_strings),
            file_info,
        );
        line_program.file_has_md5 = file_has_md5;
        if embed_source {
            line_program.file_has_source = true;
        }

        dwarf.unit.line_program = line_program;

        {
            let name = dwarf.strings.add(format!("{name}/@/{cgu_name}"));
            let comp_dir = dwarf.strings.add(&*comp_dir);

            let root = dwarf.unit.root();
            let root = dwarf.unit.get_mut(root);
            root.set(gimli::DW_AT_producer, AttributeValue::StringRef(dwarf.strings.add(producer)));
            root.set(gimli::DW_AT_language, AttributeValue::Language(gimli::DW_LANG_Rust));
            root.set(gimli::DW_AT_name, AttributeValue::StringRef(name));

            // This will be replaced when emitting the debuginfo. It is only
            // defined here to ensure that the order of the attributes matches
            // rustc.
            root.set(gimli::DW_AT_stmt_list, AttributeValue::Udata(0));

            root.set(gimli::DW_AT_comp_dir, AttributeValue::StringRef(comp_dir));
            root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0)));
        }

        let array_size_type = if tcx.sess.opts.debuginfo == DebugInfo::LineTablesOnly {
            None
        } else {
            let array_size_type = dwarf.unit.add(dwarf.unit.root(), gimli::DW_TAG_base_type);
            let array_size_type_entry = dwarf.unit.get_mut(array_size_type);
            array_size_type_entry.set(
                gimli::DW_AT_name,
                AttributeValue::StringRef(dwarf.strings.add("__ARRAY_SIZE_TYPE__")),
            );
            array_size_type_entry
                .set(gimli::DW_AT_encoding, AttributeValue::Encoding(gimli::DW_ATE_unsigned));
            array_size_type_entry.set(
                gimli::DW_AT_byte_size,
                AttributeValue::Udata(isa.frontend_config().pointer_bytes().into()),
            );
            Some(array_size_type)
        };

        Some(DebugContext {
            endian,
            dwarf,
            unit_range_list: RangeList(Vec::new()),
            created_files: FxHashMap::default(),
            stack_pointer_register,
            namespace_map: DefIdMap::default(),
            array_size_type,
            embed_source,
        })
    }

    fn item_namespace(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> UnitEntryId {
        if let Some(&scope) = self.namespace_map.get(&def_id) {
            return scope;
        }

        let def_key = tcx.def_key(def_id);
        let parent_scope = def_key
            .parent
            .map(|parent| self.item_namespace(tcx, DefId { krate: def_id.krate, index: parent }))
            .unwrap_or(self.dwarf.unit.root());

        let namespace_name = {
            let mut output = String::new();
            type_names::push_item_name(tcx, def_id, false, &mut output);
            output
        };
        let namespace_name_id = self.dwarf.strings.add(namespace_name);

        let scope = self.dwarf.unit.add(parent_scope, gimli::DW_TAG_namespace);
        let scope_entry = self.dwarf.unit.get_mut(scope);
        scope_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(namespace_name_id));

        self.namespace_map.insert(def_id, scope);
        scope
    }

    pub(crate) fn define_function<'tcx>(
        &mut self,
        tcx: TyCtxt<'tcx>,
        type_dbg: &mut TypeDebugContext<'tcx>,
        instance: Instance<'tcx>,
        fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
        linkage_name: &str,
        function_span: Span,
    ) -> FunctionDebugContext {
        let (file_id, line, column) = self.get_span_loc(tcx, function_span, function_span);

        if tcx.sess.opts.debuginfo == DebugInfo::LineTablesOnly {
            return FunctionDebugContext {
                entry_id: None,
                function_source_loc: (file_id, line, column),
                source_loc_set: IndexSet::new(),
            };
        }

        let scope = self.item_namespace(tcx, tcx.parent(instance.def_id()));

        let mut name = String::new();
        type_names::push_item_name(tcx, instance.def_id(), false, &mut name);

        // Find the enclosing function, in case this is a closure.
        let enclosing_fn_def_id = tcx.typeck_root_def_id(instance.def_id());

        // We look up the generics of the enclosing function and truncate the args
        // to their length in order to cut off extra stuff that might be in there for
        // closures or coroutines.
        let generics = tcx.generics_of(enclosing_fn_def_id);
        let args = instance.args.truncate_to(tcx, generics);

        type_names::push_generic_params(
            tcx,
            tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args),
            &mut name,
        );

        let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_subprogram);
        let entry = self.dwarf.unit.get_mut(entry_id);
        let linkage_name_id =
            if name != linkage_name { Some(self.dwarf.strings.add(linkage_name)) } else { None };
        let name_id = self.dwarf.strings.add(name);

        // These will be replaced in FunctionDebugContext::finalize. They are
        // only defined here to ensure that the order of the attributes matches
        // rustc.
        entry.set(gimli::DW_AT_low_pc, AttributeValue::Udata(0));
        entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(0));

        let mut frame_base_expr = Expression::new();
        frame_base_expr.op_reg(self.stack_pointer_register);
        entry.set(gimli::DW_AT_frame_base, AttributeValue::Exprloc(frame_base_expr));

        if let Some(linkage_name_id) = linkage_name_id {
            entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
        }
        // Gdb requires DW_AT_name. Otherwise the DW_TAG_subprogram is skipped.
        entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));

        entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
        entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));

        if !fn_abi.ret.is_ignore() {
            let return_dw_ty = self.debug_type(tcx, type_dbg, fn_abi.ret.layout.ty);
            let entry = self.dwarf.unit.get_mut(entry_id);
            entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(return_dw_ty));
        }

        if tcx.is_reachable_non_generic(instance.def_id()) {
            let entry = self.dwarf.unit.get_mut(entry_id);
            entry.set(gimli::DW_AT_external, AttributeValue::FlagPresent);
        }

        FunctionDebugContext {
            entry_id: Some(entry_id),
            function_source_loc: (file_id, line, column),
            source_loc_set: IndexSet::new(),
        }
    }

    // Adapted from https://github.com/rust-lang/rust/blob/10a7aa14fed9b528b74b0f098c4899c37c09a9c7/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs#L1288-L1346
    pub(crate) fn define_static<'tcx>(
        &mut self,
        tcx: TyCtxt<'tcx>,
        type_dbg: &mut TypeDebugContext<'tcx>,
        def_id: DefId,
        data_id: DataId,
    ) {
        if tcx.sess.opts.debuginfo == DebugInfo::LineTablesOnly {
            return;
        }

        let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
        if nested {
            return;
        }

        let scope = self.item_namespace(tcx, tcx.parent(def_id));

        let span = tcx.def_span(def_id);
        let (file_id, line, _column) = self.get_span_loc(tcx, span, span);

        let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::TypingEnv::fully_monomorphized());
        let static_layout = tcx
            .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(static_type))
            .unwrap();
        // FIXME use the actual type layout
        let type_id = self.debug_type(tcx, type_dbg, static_type);

        let name = tcx.item_name(def_id);
        let linkage_name = tcx.symbol_name(Instance::mono(tcx, def_id)).name;

        let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_variable);
        let entry = self.dwarf.unit.get_mut(entry_id);
        let linkage_name_id = if name.as_str() != linkage_name {
            Some(self.dwarf.strings.add(linkage_name))
        } else {
            None
        };
        let name_id = self.dwarf.strings.add(name.as_str());

        entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
        entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(type_id));

        if tcx.is_reachable_non_generic(def_id) {
            entry.set(gimli::DW_AT_external, AttributeValue::FlagPresent);
        }

        entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
        entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));

        entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.bytes()));

        let mut expr = Expression::new();
        expr.op_addr(address_for_data(data_id));
        entry.set(gimli::DW_AT_location, AttributeValue::Exprloc(expr));

        if let Some(linkage_name_id) = linkage_name_id {
            entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
        }
    }
}

impl FunctionDebugContext {
    pub(crate) fn finalize(
        mut self,
        debug_context: &mut DebugContext,
        func_id: FuncId,
        context: &Context,
    ) {
        let end = self.create_debug_lines(debug_context, func_id, context);

        debug_context
            .unit_range_list
            .0
            .push(Range::StartLength { begin: address_for_func(func_id), length: u64::from(end) });

        if let Some(entry_id) = self.entry_id {
            let entry = debug_context.dwarf.unit.get_mut(entry_id);
            // Gdb requires both DW_AT_low_pc and DW_AT_high_pc. Otherwise the DW_TAG_subprogram is skipped.
            entry.set(gimli::DW_AT_low_pc, AttributeValue::Address(address_for_func(func_id)));
            // Using Udata for DW_AT_high_pc requires at least DWARF4
            entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(end)));
        }
    }
}
