improve debug-printing of scalars

Before: Immediate(ScalarMaybeUndef(Scalar(Ptr(Pointer { alloc_id: AllocId(3401), offset: Size { raw: 4 }, tag: Tagged(7723) }))))
After: Immediate(Scalar(AllocId(3401).0x4[<7723>]))

Before: Immediate(ScalarMaybeUndef(Scalar(Bits { size: 8, bits: 10 })))
After: Immediate(Scalar(0x000000000000000A))

Before: Immediate(ScalarMaybeUndef(Scalar(Bits { size: 1, bits: 1 })))
After: Immediate(Scalar(0x01))
This commit is contained in:
Ralf Jung 2019-05-24 13:03:28 +02:00
parent 46805805ab
commit d01ef7d918
2 changed files with 47 additions and 3 deletions

View File

@ -1,3 +1,5 @@
use std::fmt;
use crate::mir;
use crate::ty::layout::{self, HasDataLayout, Size};
use rustc_macros::HashStable;
@ -70,7 +72,7 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
///
/// Pointer is also generic over the `Tag` associated with each pointer,
/// which is used to do provenance tracking during execution.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd,
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
RustcEncodable, RustcDecodable, Hash, HashStable)]
pub struct Pointer<Tag=(),Id=AllocId> {
pub alloc_id: Id,
@ -80,6 +82,18 @@ pub struct Pointer<Tag=(),Id=AllocId> {
static_assert_size!(Pointer, 16);
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Pointer<Tag, Id> {
default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}.{:#x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag)
}
}
// Specialization for no tag
impl<Id: fmt::Debug> fmt::Debug for Pointer<(), Id> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}.{:#x}", self.alloc_id, self.offset.bytes())
}
}
/// Produces a `Pointer` which points to the beginning of the Allocation
impl From<AllocId> for Pointer {
#[inline(always)]

View File

@ -93,7 +93,7 @@ impl<'tcx> ConstValue<'tcx> {
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
/// of a simple value or a pointer into another `Allocation`
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd,
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd,
RustcEncodable, RustcDecodable, Hash, HashStable)]
pub enum Scalar<Tag=(), Id=AllocId> {
/// The raw bytes of a simple value.
@ -113,6 +113,27 @@ pub enum Scalar<Tag=(), Id=AllocId> {
#[cfg(target_arch = "x86_64")]
static_assert_size!(Scalar, 24);
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for Scalar<Tag, Id> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scalar::Ptr(ptr) =>
write!(f, "{:?}", ptr),
&Scalar::Bits { bits, size } => {
if size == 0 {
assert_eq!(bits, 0, "ZST value must be 0");
write!(f, "<ZST>")
} else {
assert_eq!(truncate(bits, Size::from_bytes(size as u64)), bits,
"Scalar value {:#x} exceeds size of {} bytes", bits, size);
// Format as hex number wide enough to fit any value of the given `size`.
// So e.g. bits=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
write!(f, "0x{:>0width$x}", bits, width=(size*2) as usize)
}
}
}
}
}
impl<Tag> fmt::Display for Scalar<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@ -412,7 +433,7 @@ impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
Scalar(Scalar<Tag, Id>),
Undef,
@ -425,6 +446,15 @@ impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
}
}
impl<Tag: fmt::Debug, Id: fmt::Debug> fmt::Debug for ScalarMaybeUndef<Tag, Id> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ScalarMaybeUndef::Undef => write!(f, "Undef"),
ScalarMaybeUndef::Scalar(s) => write!(f, "{:?}", s),
}
}
}
impl<Tag> fmt::Display for ScalarMaybeUndef<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {