use rustc::ty::{self, layout::TyLayout};
use syntax::ast::FloatTy;
use rustc_apfloat::Float;
-use rustc::mir::interpret::{InterpResult, PanicMessage, Scalar};
+use rustc::mir::interpret::{InterpResult, Scalar};
use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
r,
right_layout.ty
);
- return err!(Unimplemented(msg));
+ throw_unsup!(Unimplemented(msg))
}
// Operations that need special treatment for signed integers
return Ok((Scalar::from_bool(op(&l, &r)), false));
}
let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
- Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
- Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
+ Div if r == 0 => throw_panic!(DivisionByZero),
+ Rem if r == 0 => throw_panic!(RemainderByZero),
Div => Some(i128::overflowing_div),
Rem => Some(i128::overflowing_rem),
Add => Some(i128::overflowing_add),
Add => u128::overflowing_add,
Sub => u128::overflowing_sub,
Mul => u128::overflowing_mul,
- Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
- Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
+ Div if r == 0 => throw_panic!(DivisionByZero),
+ Rem if r == 0 => throw_panic!(RemainderByZero),
Div => u128::overflowing_div,
Rem => u128::overflowing_rem,
_ => bug!(),
r,
right_layout.ty,
);
- return err!(Unimplemented(msg));
+ throw_unsup!(Unimplemented(msg))
}
};
FloatTy::F64 => self.binary_float_op(bin_op, left.to_f64()?, right.to_f64()?),
})
}
- _ => {
- // Must be integer(-like) types. Don't forget about == on fn pointers.
- assert!(
- left.layout.ty.is_integral() ||
- left.layout.ty.is_unsafe_ptr() || left.layout.ty.is_fn_ptr(),
- "Unexpected LHS type {:?} for BinOp {:?}", left.layout.ty, bin_op);
+ _ if left.layout.ty.is_integral() => {
+ // the RHS type can be different, e.g. for shifts -- but it has to be integral, too
assert!(
- right.layout.ty.is_integral() ||
- right.layout.ty.is_unsafe_ptr() || right.layout.ty.is_fn_ptr(),
- "Unexpected RHS type {:?} for BinOp {:?}", right.layout.ty, bin_op);
-
- // Handle operations that support pointer values
- if left.to_scalar_ptr()?.is_ptr() ||
- right.to_scalar_ptr()?.is_ptr() ||
- bin_op == mir::BinOp::Offset
- {
- return M::ptr_op(self, bin_op, left, right);
- }
+ right.layout.ty.is_integral(),
+ "Unexpected types for BinOp: {:?} {:?} {:?}",
+ left.layout.ty, bin_op, right.layout.ty
+ );
- // Everything else only works with "proper" bits
- let l = left.to_bits().expect("we checked is_ptr");
- let r = right.to_bits().expect("we checked is_ptr");
+ let l = self.force_bits(left.to_scalar()?, left.layout.size)?;
+ let r = self.force_bits(right.to_scalar()?, right.layout.size)?;
self.binary_int_op(bin_op, l, left.layout, r, right.layout)
}
+ _ if left.layout.ty.is_any_ptr() => {
+ // The RHS type must be the same *or an integer type* (for `Offset`).
+ assert!(
+ right.layout.ty == left.layout.ty || right.layout.ty.is_integral(),
+ "Unexpected types for BinOp: {:?} {:?} {:?}",
+ left.layout.ty, bin_op, right.layout.ty
+ );
+
+ M::binary_ptr_op(self, bin_op, left, right)
+ }
+ _ => bug!("Invalid MIR: bad LHS type for binop: {:?}", left.layout.ty),
}
}