From: Mazdak Farrokhzad Date: Tue, 3 Dec 2019 10:06:57 +0000 (+0100) Subject: Rollup merge of #66148 - oli-obk:it_must_be_a_sign, r=RalfJung X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=3045d22263b88e17e3ff2e824b25d727d31dea6d;hp=4787e97475de6be9487e3d9255a9c2d3c0bf9252;p=rust.git Rollup merge of #66148 - oli-obk:it_must_be_a_sign, r=RalfJung Show the sign for signed ops on `exact_div` r? @RalfJung Cc https://github.com/rust-lang/miri/pull/961/files#r341842128 I'm fairly unhappy with the duplication and the general effort required for this. Maybe it would be better to add a `display` impl for `ImmTy`? --- diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 118dfcb3d9a..75fc6b389e8 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -424,13 +424,13 @@ pub fn exact_div( if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 { // Then, check if `b` is -1, which is the "min_value / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); - let b = b.to_scalar().unwrap(); - if b == minus1 { + let b_scalar = b.to_scalar().unwrap(); + if b_scalar == minus1 { throw_ub_format!("exact_div: result of dividing MIN by -1 cannot be represented") } else { throw_ub_format!( "exact_div: {} cannot be divided by {} without remainder", - a.to_scalar().unwrap(), + a, b, ) } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 9e94ae2c160..48e7193ec39 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -19,6 +19,7 @@ }; pub use rustc::mir::interpret::ScalarMaybeUndef; use rustc_macros::HashStable; +use syntax::ast; /// An `Immediate` represents a single immediate self-contained Rust value. /// @@ -100,6 +101,42 @@ pub struct ImmTy<'tcx, Tag=()> { pub layout: TyLayout<'tcx>, } +// `Tag: Copy` because some methods on `Scalar` consume them by value +impl std::fmt::Display for ImmTy<'tcx, Tag> { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.imm { + Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => match s.to_bits(self.layout.size) { + Ok(s) => { + match self.layout.ty.kind { + ty::Int(_) => return write!( + fmt, "{}", + super::sign_extend(s, self.layout.size) as i128, + ), + ty::Uint(_) => return write!(fmt, "{}", s), + ty::Bool if s == 0 => return fmt.write_str("false"), + ty::Bool if s == 1 => return fmt.write_str("true"), + ty::Char => if let Some(c) = + u32::try_from(s).ok().and_then(std::char::from_u32) { + return write!(fmt, "{}", c); + }, + ty::Float(ast::FloatTy::F32) => if let Ok(u) = u32::try_from(s) { + return write!(fmt, "{}", f32::from_bits(u)); + }, + ty::Float(ast::FloatTy::F64) => if let Ok(u) = u64::try_from(s) { + return write!(fmt, "{}", f64::from_bits(u)); + }, + _ => {}, + } + write!(fmt, "{:x}", s) + }, + Err(_) => fmt.write_str("{pointer}"), + }, + Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"), + Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"), + } + } +} + impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> { type Target = Immediate; #[inline(always)]