<commit_before>use crate::prelude::*;

use cranelift_codegen::ir::immediates::Offset32;

fn codegen_field<'tcx>(
    fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
    base: Pointer,
    extra: Option<Value>,
    layout: TyLayout<'tcx>,
    field: mir::Field,
) -> (Pointer, TyLayout<'tcx>) {
    let field_offset = layout.fields.offset(field.index());
    let field_layout = layout.field(&*fx, field.index());

    let simple = |fx: &mut FunctionCx<_>| {
        (
            base.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()),
            field_layout,
        )
    };

    if let Some(extra) = extra {
        if !field_layout.is_unsized() {
            return simple(fx);
        }
        match field_layout.ty.kind {
            ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(fx),
            ty::Adt(def, _) if def.repr.packed() => {
                assert_eq!(layout.align.abi.bytes(), 1);
                return simple(fx);
            }
            _ => {
                // We have to align the offset for DST's
                let unaligned_offset = field_offset.bytes();
                let (_, unsized_align) = crate::unsize::size_and_align_of_dst(fx, field_layout.ty, extra);

                let one = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 1);
                let align_sub_1 = fx.bcx.ins().isub(unsized_align, one);
                let and_lhs = fx.bcx.ins().iadd_imm(align_sub_1, unaligned_offset as i64);
                let zero = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 0);
                let and_rhs = fx.bcx.ins().isub(zero, unsized_align);
                let offset = fx.bcx.ins().band(and_lhs, and_rhs);

                (
                    base.offset_value(fx, offset),
                    field_layout,
                )
            }
        }
    } else {
        simple(fx)
    }
}

fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: &Scalar, b_scalar: &Scalar) -> Offset32 {
    let b_offset = a_scalar
        .value
        .size(&tcx)
        .align_to(b_scalar.value.align(&tcx).abi);
    Offset32::new(b_offset.bytes().try_into().unwrap())
}

/// A read-only value
#[derive(Debug, Copy, Clone)]
pub struct CValue<'tcx>(CValueInner, TyLayout<'tcx>);

#[derive(Debug, Copy, Clone)]
enum CValueInner {
    ByRef(Pointer),
    ByVal(Value),
    ByValPair(Value, Value),
}

impl<'tcx> CValue<'tcx> {
    pub fn by_ref(ptr: Pointer, layout: TyLayout<'tcx>) -> CValue<'tcx> {
        CValue(CValueInner::ByRef(ptr), layout)
    }

    pub fn by_val(value: Value, layout: TyLayout<'tcx>) -> CValue<'tcx> {
        CValue(CValueInner::ByVal(value), layout)
    }

    pub fn by_val_pair(value: Value, extra: Value, layout: TyLayout<'tcx>) -> CValue<'tcx> {
        CValue(CValueInner::ByValPair(value, extra), layout)
    }

    pub fn layout(&self) -> TyLayout<'tcx> {
        self.1
    }

    pub fn force_stack<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Pointer {
        let layout = self.1;
        match self.0 {
            CValueInner::ByRef(ptr) => ptr,
            CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => {
                let cplace = CPlace::new_stack_slot(fx, layout.ty);
                cplace.write_cvalue(fx, self);
                cplace.to_ptr(fx)
            }
        }
    }

    pub fn try_to_addr(self) -> Option<Value> {
        match self.0 {
            CValueInner::ByRef(ptr) => {
                if let Some((base_addr, offset)) = ptr.try_get_addr_and_offset() {
                    if offset == Offset32::new(0) {
                        Some(base_addr)
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => None,
        }
    }

    /// Load a value with layout.abi of scalar
    pub fn load_scalar<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Value {
        let layout = self.1;
        match self.0 {
            CValueInner::ByRef(ptr) => {
                let clif_ty = match layout.abi {
                    layout::Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
                    layout::Abi::Vector { ref element, count } => {
                        scalar_to_clif_type(fx.tcx, element.clone())
                            .by(u16::try_from(count).unwrap()).unwrap()
                    }
                    _ => unreachable!(),
                };
                ptr.load(fx, clif_ty, MemFlags::new())
            }<commit_msg>Remove vector support from load_scalar<commit_after>use crate::prelude::*;

use cranelift_codegen::ir::immediates::Offset32;

fn codegen_field<'tcx>(
    fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
    base: Pointer,
    extra: Option<Value>,
    layout: TyLayout<'tcx>,
    field: mir::Field,
) -> (Pointer, TyLayout<'tcx>) {
    let field_offset = layout.fields.offset(field.index());
    let field_layout = layout.field(&*fx, field.index());

    let simple = |fx: &mut FunctionCx<_>| {
        (
            base.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()),
            field_layout,
        )
    };

    if let Some(extra) = extra {
        if !field_layout.is_unsized() {
            return simple(fx);
        }
        match field_layout.ty.kind {
            ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(fx),
            ty::Adt(def, _) if def.repr.packed() => {
                assert_eq!(layout.align.abi.bytes(), 1);
                return simple(fx);
            }
            _ => {
                // We have to align the offset for DST's
                let unaligned_offset = field_offset.bytes();
                let (_, unsized_align) = crate::unsize::size_and_align_of_dst(fx, field_layout.ty, extra);

                let one = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 1);
                let align_sub_1 = fx.bcx.ins().isub(unsized_align, one);
                let and_lhs = fx.bcx.ins().iadd_imm(align_sub_1, unaligned_offset as i64);
                let zero = fx.bcx.ins().iconst(pointer_ty(fx.tcx), 0);
                let and_rhs = fx.bcx.ins().isub(zero, unsized_align);
                let offset = fx.bcx.ins().band(and_lhs, and_rhs);

                (
                    base.offset_value(fx, offset),
                    field_layout,
                )
            }
        }
    } else {
        simple(fx)
    }
}

fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: &Scalar, b_scalar: &Scalar) -> Offset32 {
    let b_offset = a_scalar
        .value
        .size(&tcx)
        .align_to(b_scalar.value.align(&tcx).abi);
    Offset32::new(b_offset.bytes().try_into().unwrap())
}

/// A read-only value
#[derive(Debug, Copy, Clone)]
pub struct CValue<'tcx>(CValueInner, TyLayout<'tcx>);

#[derive(Debug, Copy, Clone)]
enum CValueInner {
    ByRef(Pointer),
    ByVal(Value),
    ByValPair(Value, Value),
}

impl<'tcx> CValue<'tcx> {
    pub fn by_ref(ptr: Pointer, layout: TyLayout<'tcx>) -> CValue<'tcx> {
        CValue(CValueInner::ByRef(ptr), layout)
    }

    pub fn by_val(value: Value, layout: TyLayout<'tcx>) -> CValue<'tcx> {
        CValue(CValueInner::ByVal(value), layout)
    }

    pub fn by_val_pair(value: Value, extra: Value, layout: TyLayout<'tcx>) -> CValue<'tcx> {
        CValue(CValueInner::ByValPair(value, extra), layout)
    }

    pub fn layout(&self) -> TyLayout<'tcx> {
        self.1
    }

    pub fn force_stack<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Pointer {
        let layout = self.1;
        match self.0 {
            CValueInner::ByRef(ptr) => ptr,
            CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => {
                let cplace = CPlace::new_stack_slot(fx, layout.ty);
                cplace.write_cvalue(fx, self);
                cplace.to_ptr(fx)
            }
        }
    }

    pub fn try_to_addr(self) -> Option<Value> {
        match self.0 {
            CValueInner::ByRef(ptr) => {
                if let Some((base_addr, offset)) = ptr.try_get_addr_and_offset() {
                    if offset == Offset32::new(0) {
                        Some(base_addr)
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => None,
        }
    }

    /// Load a value with layout.abi of scalar
    pub fn load_scalar<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Value {
        let layout = self.1;
        match self.0 {
            CValueInner::ByRef(ptr) => {
                let scalar = match layout.abi {
                    layout::Abi::Scalar(ref scalar) => scalar.clone(),
                    _ => unreachable!(),
                };
                let clif_ty = scalar_to_clif_type(fx.tcx, scalar);
                ptr.load(fx, clif_ty, MemFlags::new())
            }
{'fraction_non_alphanumeric': 0.14396714396714397, 'fraction_numerical': 0.005994005994005994, 'mean_word_length': 1.8458622867972205, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 88, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1513874', 'n_tokens_mistral': 2962, 'n_tokens_neox': 2938, 'n_words': 536}