From a3297562f6c1bb8ca7bcb80d265fc41dc10d5a9f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 17 Nov 2019 14:30:08 +0100 Subject: [PATCH] Show the sign of signed interpreter values --- src/librustc_mir/interpret/intrinsics.rs | 6 ++-- src/librustc_mir/interpret/operand.rs | 37 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 23f7b1acb54d4..34265055ed44f 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -417,13 +417,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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 4f03b1320903a..292584f6a6b2e 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -19,6 +19,7 @@ use super::{ }; pub use rustc::mir::interpret::ScalarMaybeUndef; use rustc_macros::HashStable; +use syntax::ast; /// An `Immediate` represents a single immediate self-contained Rust value. /// @@ -93,6 +94,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)]