use crate::prelude::*;
-pub fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> Option<IntCC> {
+pub(crate) fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> Option<IntCC> {
use BinOp::*;
use IntCC::*;
Some(match bin_op {
Eq => Equal,
- Lt => if signed { SignedLessThan } else { UnsignedLessThan},
- Le => if signed { SignedLessThanOrEqual } else { UnsignedLessThanOrEqual},
+ Lt => {
+ if signed {
+ SignedLessThan
+ } else {
+ UnsignedLessThan
+ }
+ }
+ Le => {
+ if signed {
+ SignedLessThanOrEqual
+ } else {
+ UnsignedLessThanOrEqual
+ }
+ }
Ne => NotEqual,
- Ge => if signed { SignedGreaterThanOrEqual } else { UnsignedGreaterThanOrEqual },
- Gt => if signed { SignedGreaterThan } else { UnsignedGreaterThan },
+ Ge => {
+ if signed {
+ SignedGreaterThanOrEqual
+ } else {
+ UnsignedGreaterThanOrEqual
+ }
+ }
+ Gt => {
+ if signed {
+ SignedGreaterThan
+ } else {
+ UnsignedGreaterThan
+ }
+ }
_ => return None,
})
}
rhs: Value,
) -> CValue<'tcx> {
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
- let val = codegen_icmp(fx, intcc, lhs, rhs);
+ let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
let val = fx.bcx.ins().bint(types::I8, val);
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
}
-pub fn codegen_binop<'tcx>(
+pub(crate) fn codegen_binop<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
bin_op: BinOp,
in_lhs: CValue<'tcx>,
) -> CValue<'tcx> {
match bin_op {
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
- match in_lhs.layout().ty.sty {
+ match in_lhs.layout().ty.kind {
ty::Bool | ty::Uint(_) | ty::Int(_) | ty::Char => {
let signed = type_sign(in_lhs.layout().ty);
let lhs = in_lhs.load_scalar(fx);
let rhs = in_rhs.load_scalar(fx);
- let (lhs, rhs) = if
- (bin_op == BinOp::Eq || bin_op == BinOp::Ne)
- && (in_lhs.layout().ty.sty == fx.tcx.types.i8.sty || in_lhs.layout().ty.sty == fx.tcx.types.i16.sty)
+ let (lhs, rhs) = if (bin_op == BinOp::Eq || bin_op == BinOp::Ne)
+ && (in_lhs.layout().ty.kind == fx.tcx.types.i8.kind
+ || in_lhs.layout().ty.kind == fx.tcx.types.i16.kind)
{
// FIXME(CraneStation/cranelift#896) icmp_imm.i8/i16 with eq/ne for signed ints is implemented wrong.
(
_ => {}
}
- match in_lhs.layout().ty.sty {
+ match in_lhs.layout().ty.kind {
ty::Bool => crate::num::trans_bool_binop(fx, bin_op, in_lhs, in_rhs),
- ty::Uint(_) | ty::Int(_)=> {
- crate::num::trans_int_binop(fx, bin_op, in_lhs, in_rhs)
- }
+ ty::Uint(_) | ty::Int(_) => crate::num::trans_int_binop(fx, bin_op, in_lhs, in_rhs),
ty::Float(_) => crate::num::trans_float_binop(fx, bin_op, in_lhs, in_rhs),
- ty::RawPtr(..) | ty::FnPtr(..) => {
- crate::num::trans_ptr_binop(fx, bin_op, in_lhs, in_rhs)
- }
- _ => unimplemented!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty),
+ ty::RawPtr(..) | ty::FnPtr(..) => crate::num::trans_ptr_binop(fx, bin_op, in_lhs, in_rhs),
+ _ => unreachable!(
+ "{:?}({:?}, {:?})",
+ bin_op,
+ in_lhs.layout().ty,
+ in_rhs.layout().ty
+ ),
}
}
-pub fn trans_bool_binop<'a, 'tcx: 'a>(
- fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
+pub(crate) fn trans_bool_binop<'tcx>(
+ fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
bin_op: BinOp,
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
CValue::by_val(res, fx.layout_of(fx.tcx.types.bool))
}
-pub fn trans_int_binop<'a, 'tcx: 'a>(
- fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
+pub(crate) fn trans_int_binop<'tcx>(
+ fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
bin_op: BinOp,
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
BinOp::Add => b.iadd(lhs, rhs),
BinOp::Sub => b.isub(lhs, rhs),
BinOp::Mul => b.imul(lhs, rhs),
- BinOp::Div => if signed { b.sdiv(lhs, rhs) } else { b.udiv(lhs, rhs) },
- BinOp::Rem => if signed { b.srem(lhs, rhs) } else { b.urem(lhs, rhs) },
+ BinOp::Div => {
+ if signed {
+ b.sdiv(lhs, rhs)
+ } else {
+ b.udiv(lhs, rhs)
+ }
+ }
+ BinOp::Rem => {
+ if signed {
+ b.srem(lhs, rhs)
+ } else {
+ b.urem(lhs, rhs)
+ }
+ }
BinOp::BitXor => b.bxor(lhs, rhs),
BinOp::BitAnd => b.band(lhs, rhs),
BinOp::BitOr => b.bor(lhs, rhs),
}
}
// Compare binops handles by `codegen_binop`.
- _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty),
+ _ => unreachable!(
+ "{:?}({:?}, {:?})",
+ bin_op,
+ in_lhs.layout().ty,
+ in_rhs.layout().ty
+ ),
};
CValue::by_val(val, in_lhs.layout())
}
-pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
- fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
+pub(crate) fn trans_checked_int_binop<'tcx>(
+ fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
bin_op: BinOp,
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
}
BinOp::Shl => {
let val = fx.bcx.ins().ishl(lhs, rhs);
- // TODO: check for overflow
- let has_overflow = fx.bcx.ins().bconst(types::B1, false);
+ let ty = fx.bcx.func.dfg.value_type(val);
+ let max_shift = i64::from(ty.bits()) - 1;
+ let has_overflow =
+ fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
(val, has_overflow)
}
BinOp::Shr => {
} else {
fx.bcx.ins().sshr(lhs, rhs)
};
- // TODO: check for overflow
- let has_overflow = fx.bcx.ins().bconst(types::B1, false);
+ let ty = fx.bcx.func.dfg.value_type(val);
+ let max_shift = i64::from(ty.bits()) - 1;
+ let has_overflow =
+ fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
(val, has_overflow)
}
_ => bug!(
};
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
- let out_place = CPlace::new_stack_slot(fx, fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
+
+ // FIXME directly write to result place instead
+ let out_place = CPlace::new_stack_slot(
+ fx,
+ fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter())),
+ );
let out_layout = out_place.layout();
out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout));
out_place.to_cvalue(fx)
}
-pub fn trans_float_binop<'a, 'tcx: 'a>(
- fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
+pub(crate) fn trans_float_binop<'tcx>(
+ fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
bin_op: BinOp,
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
BinOp::Mul => b.fmul(lhs, rhs),
BinOp::Div => b.fdiv(lhs, rhs),
BinOp::Rem => {
- let name = match in_lhs.layout().ty.sty {
+ let name = match in_lhs.layout().ty.kind {
ty::Float(FloatTy::F32) => "fmodf",
ty::Float(FloatTy::F64) => "fmod",
_ => bug!(),
CValue::by_val(res, in_lhs.layout())
}
-pub fn trans_ptr_binop<'a, 'tcx: 'a>(
- fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
+pub(crate) fn trans_ptr_binop<'tcx>(
+ fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
bin_op: BinOp,
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
) -> CValue<'tcx> {
- let not_fat = match in_lhs.layout().ty.sty {
- ty::RawPtr(TypeAndMut { ty, mutbl: _ }) => {
- ty.is_sized(fx.tcx.at(DUMMY_SP), ParamEnv::reveal_all())
- }
- ty::FnPtr(..) => true,
- _ => bug!("trans_ptr_binop on non ptr"),
- };
- if not_fat {
+ let is_thin_ptr = in_lhs.layout().ty.builtin_deref(true).map(|TypeAndMut { ty, mutbl: _}| {
+ !has_ptr_meta(fx.tcx, ty)
+ }).unwrap_or(true);
+
+ if is_thin_ptr {
match bin_op {
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
let lhs = in_lhs.load_scalar(fx);
return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs);
}
BinOp::Offset => {
+ let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty;
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
- let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
let base_val = base.load_scalar(fx);
BinOp::Lt | BinOp::Le | BinOp::Ge | BinOp::Gt => {
let ptr_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_ptr, rhs_ptr);
- let ptr_cmp = fx.bcx.ins().icmp(bin_op_to_intcc(bin_op, false).unwrap(), lhs_ptr, rhs_ptr);
- let extra_cmp = fx.bcx.ins().icmp(bin_op_to_intcc(bin_op, false).unwrap(), lhs_extra, rhs_extra);
+ let ptr_cmp =
+ fx.bcx
+ .ins()
+ .icmp(bin_op_to_intcc(bin_op, false).unwrap(), lhs_ptr, rhs_ptr);
+ let extra_cmp = fx.bcx.ins().icmp(
+ bin_op_to_intcc(bin_op, false).unwrap(),
+ lhs_extra,
+ rhs_extra,
+ );
fx.bcx.ins().select(ptr_eq, extra_cmp, ptr_cmp)
}
_ => panic!("bin_op {:?} on ptr", bin_op),
};
- CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
+ CValue::by_val(
+ fx.bcx.ins().bint(types::I8, res),
+ fx.layout_of(fx.tcx.types.bool),
+ )
}
}