use rustc_hir::LangItem;
use rustc_index::IndexVec;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext};
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_session::Session;

use crate::check_pointers::{BorrowedFieldProjectionMode, PointerCheck, check_pointers};

pub(super) struct CheckNull;

impl<'tcx> crate::MirPass<'tcx> for CheckNull {
    fn is_enabled(&self, sess: &Session) -> bool {
        sess.ub_checks()
    }

    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        check_pointers(
            tcx,
            body,
            &[],
            insert_null_check,
            BorrowedFieldProjectionMode::NoFollowProjections,
        );
    }

    fn is_required(&self) -> bool {
        true
    }
}

fn insert_null_check<'tcx>(
    tcx: TyCtxt<'tcx>,
    pointer: Place<'tcx>,
    pointee_ty: Ty<'tcx>,
    context: PlaceContext,
    local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
    stmts: &mut Vec<Statement<'tcx>>,
    source_info: SourceInfo,
) -> PointerCheck<'tcx> {
    // Cast the pointer to a *const ().
    let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit);
    let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr);
    let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into();
    stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((thin_ptr, rvalue)))));

    // Transmute the pointer to a usize (equivalent to `ptr.addr()`).
    let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize);
    let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
    stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((addr, rvalue)))));

    let zero = Operand::Constant(Box::new(ConstOperand {
        span: source_info.span,
        user_ty: None,
        const_: Const::Val(ConstValue::from_target_usize(0, &tcx), tcx.types.usize),
    }));

    let (pointee_should_be_checked, assert_kind) = match context {
        // Borrows pointing to "null" are UB even if the pointee is a ZST.
        PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
        | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
            // Pointer should be checked unconditionally.
            (
                Operand::Constant(Box::new(ConstOperand {
                    span: source_info.span,
                    user_ty: None,
                    const_: Const::from_bool(tcx, true),
                })),
                AssertKind::NullReferenceConstructed,
            )
        }
        // Other usages of null pointers only are UB if the pointee is not a ZST.
        _ => {
            let size_of = tcx.require_lang_item(LangItem::SizeOf, source_info.span);
            let size_of =
                Operand::unevaluated_constant(tcx, size_of, &[pointee_ty.into()], source_info.span);

            let pointee_should_be_checked =
                local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
            let rvalue = Rvalue::BinaryOp(BinOp::Ne, Box::new((size_of, zero.clone())));
            stmts.push(Statement::new(
                source_info,
                StatementKind::Assign(Box::new((pointee_should_be_checked, rvalue))),
            ));
            (Operand::Copy(pointee_should_be_checked), AssertKind::NullPointerDereference)
        }
    };

    // Check whether the pointer is null.
    let is_null = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
    stmts.push(Statement::new(
        source_info,
        StatementKind::Assign(Box::new((
            is_null,
            Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(addr), zero))),
        ))),
    ));

    // We want to throw an exception if the pointer is null and the pointee is not unconditionally
    // allowed (which for all non-borrow place uses, is when the pointee is ZST).
    let should_throw_exception =
        local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
    stmts.push(Statement::new(
        source_info,
        StatementKind::Assign(Box::new((
            should_throw_exception,
            Rvalue::BinaryOp(
                BinOp::BitAnd,
                Box::new((Operand::Copy(is_null), pointee_should_be_checked)),
            ),
        ))),
    ));

    // The final condition whether this pointer usage is ok or not.
    let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
    stmts.push(Statement::new(
        source_info,
        StatementKind::Assign(Box::new((
            is_ok,
            Rvalue::UnaryOp(UnOp::Not, Operand::Copy(should_throw_exception)),
        ))),
    ));

    // Emit a PointerCheck that asserts on the condition and otherwise triggers
    // the chosen AssertKind.
    PointerCheck { cond: Operand::Copy(is_ok), assert_kind: Box::new(assert_kind) }
}
