about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2019-11-17 14:30:08 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-11-26 14:02:23 +0100
commita3297562f6c1bb8ca7bcb80d265fc41dc10d5a9f (patch)
tree9974c5fa926b523230e7693718a530745f4ab387
parent0f6f66fcdc4abf110171ee06b1a72bdd2883b74f (diff)
downloadrust-a3297562f6c1bb8ca7bcb80d265fc41dc10d5a9f.tar.gz
rust-a3297562f6c1bb8ca7bcb80d265fc41dc10d5a9f.zip
Show the sign of signed interpreter values
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs6
-rw-r--r--src/librustc_mir/interpret/operand.rs37
2 files changed, 40 insertions, 3 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 23f7b1acb54..34265055ed4 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 4f03b132090..292584f6a6b 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<Tag: Copy> 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<Tag>;
     #[inline(always)]