//! 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_args(
            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)));
        }
    }
}
