use super::metadata::file_metadata;
use super::utils::DIB;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;

use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::{DILocation, DIScope};
use rustc_middle::mir::{Body, SourceScope};
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo;

use rustc_index::bit_set::BitSet;
use rustc_index::Idx;

/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`.
pub fn compute_mir_scopes<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    instance: Instance<'tcx>,
    mir: &Body<'tcx>,
    debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
) {
    // Find all scopes with variables defined in them.
    let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
        let mut vars = BitSet::new_empty(mir.source_scopes.len());
        // FIXME(eddyb) take into account that arguments always have debuginfo,
        // irrespective of their name (assuming full debuginfo is enabled).
        // NOTE(eddyb) actually, on second thought, those are always in the
        // function scope, which always exists.
        for var_debug_info in &mir.var_debug_info {
            vars.insert(var_debug_info.source_info.scope);
        }
        Some(vars)
    } else {
        // Nothing to emit, of course.
        None
    };
    let mut instantiated = BitSet::new_empty(mir.source_scopes.len());
    // Instantiate all scopes.
    for idx in 0..mir.source_scopes.len() {
        let scope = SourceScope::new(idx);
        make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope);
    }
    assert!(instantiated.count() == mir.source_scopes.len());
}

fn make_mir_scope<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    instance: Instance<'tcx>,
    mir: &Body<'tcx>,
    variables: &Option<BitSet<SourceScope>>,
    debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
    instantiated: &mut BitSet<SourceScope>,
    scope: SourceScope,
) {
    if instantiated.contains(scope) {
        return;
    }

    let scope_data = &mir.source_scopes[scope];
    let parent_scope = if let Some(parent) = scope_data.parent_scope {
        make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent);
        debug_context.scopes[parent]
    } else {
        // The root is the function itself.
        let loc = cx.lookup_debug_loc(mir.span.lo());
        debug_context.scopes[scope] = DebugScope {
            file_start_pos: loc.file.start_pos,
            file_end_pos: loc.file.end_pos,
            ..debug_context.scopes[scope]
        };
        instantiated.insert(scope);
        return;
    };

    if let Some(vars) = variables && !vars.contains(scope) && scope_data.inlined.is_none() {
        // Do not create a DIScope if there are no variables defined in this
        // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
        debug_context.scopes[scope] = parent_scope;
        instantiated.insert(scope);
        return;
    }

    let loc = cx.lookup_debug_loc(scope_data.span.lo());
    let file_metadata = file_metadata(cx, &loc.file);

    let dbg_scope = match scope_data.inlined {
        Some((callee, _)) => {
            // FIXME(eddyb) this would be `self.monomorphize(&callee)`
            // if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
            let callee = cx.tcx.subst_and_normalize_erasing_regions(
                instance.substs,
                ty::ParamEnv::reveal_all(),
                ty::EarlyBinder::new(callee),
            );
            let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
            cx.dbg_scope_fn(callee, callee_fn_abi, None)
        }
        None => unsafe {
            llvm::LLVMRustDIBuilderCreateLexicalBlock(
                DIB(cx),
                parent_scope.dbg_scope,
                file_metadata,
                loc.line,
                loc.col,
            )
        },
    };

    let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
        // FIXME(eddyb) this doesn't account for the macro-related
        // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
        let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
        cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
    });

    debug_context.scopes[scope] = DebugScope {
        dbg_scope,
        inlined_at: inlined_at.or(parent_scope.inlined_at),
        file_start_pos: loc.file.start_pos,
        file_end_pos: loc.file.end_pos,
    };
    instantiated.insert(scope);
}
