use std::collections::BTreeSet;
+use std::fmt::Display;
use std::fmt::Write as _;
-use std::fmt::{Debug, Display};
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_middle::mir::interpret::{
- read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer,
+ read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, Provenance,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
});
filters.split('|').any(|or_filter| {
or_filter.split('&').all(|and_filter| {
- and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter)
+ let and_filter_trimmed = and_filter.trim();
+ and_filter_trimmed == "all"
+ || pass_name.contains(and_filter_trimmed)
+ || node_path.contains(and_filter_trimmed)
})
})
}
}
}
-fn use_verbose(ty: &&TyS<'tcx>) -> bool {
+fn use_verbose(ty: &&TyS<'tcx>, fn_def: bool) -> bool {
match ty.kind() {
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
// Unit type
ty::Tuple(g_args) if g_args.is_empty() => false,
- ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty())),
- ty::Array(ty, _) => use_verbose(ty),
- ty::FnDef(..) => false,
+ ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty(), fn_def)),
+ ty::Array(ty, _) => use_verbose(ty, fn_def),
+ ty::FnDef(..) => fn_def,
_ => true,
}
}
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
self.super_constant(constant, location);
let Constant { span, user_ty, literal } = constant;
- match literal.ty().kind() {
- ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {}
- // Unit type
- ty::Tuple(tys) if tys.is_empty() => {}
- _ => {
- self.push("mir::Constant");
- self.push(&format!(
- "+ span: {}",
- self.tcx.sess.source_map().span_to_embeddable_string(*span)
- ));
- if let Some(user_ty) = user_ty {
- self.push(&format!("+ user_ty: {:?}", user_ty));
- }
- match literal {
- ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
- ConstantKind::Val(val, ty) => {
- // To keep the diffs small, we render this almost like we render ty::Const
- self.push(&format!(
- "+ literal: Const {{ ty: {}, val: Value({:?}) }}",
- ty, val
- ))
- }
+ if use_verbose(&literal.ty(), true) {
+ self.push("mir::Constant");
+ self.push(&format!(
+ "+ span: {}",
+ self.tcx.sess.source_map().span_to_embeddable_string(*span)
+ ));
+ if let Some(user_ty) = user_ty {
+ self.push(&format!("+ user_ty: {:?}", user_ty));
+ }
+ match literal {
+ ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)),
+ ConstantKind::Val(val, ty) => {
+ // To keep the diffs small, we render this almost like we render ty::Const
+ self.push(&format!("+ literal: Const {{ ty: {}, val: Value({:?}) }}", ty, val))
}
}
}
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
self.super_const(constant);
let ty::Const { ty, val, .. } = constant;
- if use_verbose(ty) {
+ if use_verbose(ty, false) {
self.push("ty::Const");
self.push(&format!("+ ty: {:?}", ty));
let val = match val {
w: &mut dyn Write,
) -> io::Result<()> {
fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
- alloc.relocations().values().map(|(_, id)| *id)
+ alloc.relocations().values().map(|id| *id)
}
fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
match val {
- ConstValue::Scalar(interpret::Scalar::Ptr(ptr)) => {
- Either::Left(Either::Left(std::iter::once(ptr.alloc_id)))
+ ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => {
+ Either::Left(Either::Left(std::iter::once(ptr.provenance)))
}
ConstValue::Scalar(interpret::Scalar::Int { .. }) => {
Either::Left(Either::Right(std::iter::empty()))
/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
/// characters or characters whose value is larger than 127) with a `.`
/// This also prints relocations adequately.
-pub fn display_allocation<Tag: Copy + Debug, Extra>(
+pub fn display_allocation<Tag, Extra>(
tcx: TyCtxt<'tcx>,
alloc: &'a Allocation<Tag, Extra>,
) -> RenderAllocation<'a, 'tcx, Tag, Extra> {
alloc: &'a Allocation<Tag, Extra>,
}
-impl<Tag: Copy + Debug, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> {
+impl<Tag: Provenance, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> {
fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let RenderAllocation { tcx, alloc } = *self;
write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?;
/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
/// is only one line). Note that your prefix should contain a trailing space as the lines are
/// printed directly after it.
-fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
+fn write_allocation_bytes<Tag: Provenance, Extra>(
tcx: TyCtxt<'tcx>,
alloc: &Allocation<Tag, Extra>,
w: &mut dyn std::fmt::Write,
) -> std::fmt::Result {
let num_lines = alloc.size().bytes_usize().saturating_sub(BYTES_PER_LINE);
// Number of chars needed to represent all line numbers.
- let pos_width = format!("{:x}", alloc.size().bytes()).len();
+ let pos_width = hex_number_length(alloc.size().bytes());
if num_lines > 0 {
write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?;
if i != line_start {
write!(w, " ")?;
}
- if let Some(&(tag, target_id)) = alloc.relocations().get(&i) {
+ if let Some(&tag) = alloc.relocations().get(&i) {
// Memory with a relocation must be defined
let j = i.bytes_usize();
let offset = alloc
let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap();
let offset = Size::from_bytes(offset);
let relocation_width = |bytes| bytes * 3;
- let ptr = Pointer::new_with_tag(target_id, offset, tag);
+ let ptr = Pointer::new(tag, offset);
let mut target = format!("{:?}", ptr);
if target.len() > relocation_width(ptr_size.bytes_usize() - 1) {
// This is too long, try to save some space.
tcx.mir_keys(()).iter().map(|def_id| def_id.to_def_id()).collect()
}
}
+
+/// Calc converted u64 decimal into hex and return it's length in chars
+///
+/// ```ignore (cannot-test-private-function)
+/// assert_eq!(1, hex_number_length(0));
+/// assert_eq!(1, hex_number_length(1));
+/// assert_eq!(2, hex_number_length(16));
+/// ```
+fn hex_number_length(x: u64) -> usize {
+ if x == 0 {
+ return 1;
+ }
+ let mut length = 0;
+ let mut x_left = x;
+ while x_left > 0 {
+ x_left /= 16;
+ length += 1;
+ }
+ length
+}