use rustc_abi::Align;
use rustc_hir::LangItem;
use rustc_index::IndexVec;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::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 CheckAlignment;

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

    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        // Skip trivially aligned place types.
        let excluded_pointees = [tcx.types.bool, tcx.types.i8, tcx.types.u8];

        // When checking the alignment of references to field projections (`&(*ptr).a`),
        // we need to make sure that the reference is aligned according to the field type
        // and not to the pointer type.
        check_pointers(
            tcx,
            body,
            &excluded_pointees,
            insert_alignment_check,
            BorrowedFieldProjectionMode::FollowProjections,
        );
    }

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

/// Inserts the actual alignment check's logic. Returns a
/// [AssertKind::MisalignedPointerDereference] on failure.
fn insert_alignment_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)))));

    // Get the alignment of the pointee
    let align_def_id = tcx.require_lang_item(LangItem::AlignOf, source_info.span);
    let alignment =
        Operand::unevaluated_constant(tcx, align_def_id, &[pointee_ty.into()], source_info.span);

    // Subtract 1 from the alignment to get the alignment mask
    let alignment_mask =
        local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
    let one = Operand::Constant(Box::new(ConstOperand {
        span: source_info.span,
        user_ty: None,
        const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize),
    }));
    stmts.push(Statement::new(
        source_info,
        StatementKind::Assign(Box::new((
            alignment_mask,
            Rvalue::BinaryOp(BinOp::Sub, Box::new((alignment.clone(), one))),
        ))),
    ));

    // If this target does not have reliable alignment, further limit the mask by anding it with
    // the mask for the highest reliable alignment.
    #[allow(irrefutable_let_patterns)]
    if let max_align = tcx.sess.target.max_reliable_alignment()
        && max_align < Align::MAX
    {
        let max_mask = max_align.bytes() - 1;
        let max_mask = Operand::Constant(Box::new(ConstOperand {
            span: source_info.span,
            user_ty: None,
            const_: Const::Val(
                ConstValue::Scalar(Scalar::from_target_usize(max_mask, &tcx)),
                tcx.types.usize,
            ),
        }));
        stmts.push(Statement::new(
            source_info,
            StatementKind::Assign(Box::new((
                alignment_mask,
                Rvalue::BinaryOp(
                    BinOp::BitAnd,
                    Box::new((Operand::Copy(alignment_mask), max_mask)),
                ),
            ))),
        ));
    }

    // BitAnd the alignment mask with the pointer
    let alignment_bits =
        local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
    stmts.push(Statement::new(
        source_info,
        StatementKind::Assign(Box::new((
            alignment_bits,
            Rvalue::BinaryOp(
                BinOp::BitAnd,
                Box::new((Operand::Copy(addr), Operand::Copy(alignment_mask))),
            ),
        ))),
    ));

    // Check if the alignment bits are all zero
    let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
    let zero = Operand::Constant(Box::new(ConstOperand {
        span: source_info.span,
        user_ty: None,
        const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize),
    }));
    stmts.push(Statement::new(
        source_info,
        StatementKind::Assign(Box::new((
            is_ok,
            Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(alignment_bits), zero.clone()))),
        ))),
    ));

    // Emit a check that asserts on the alignment and otherwise triggers a
    // AssertKind::MisalignedPointerDereference.
    PointerCheck {
        cond: Operand::Copy(is_ok),
        assert_kind: Box::new(AssertKind::MisalignedPointerDereference {
            required: alignment,
            found: Operand::Copy(addr),
        }),
    }
}
