11c521e17SSingleAccretion use crate::{debug::Reader, translate::get_vmctx_value_label};
292cc0ad7SSingleAccretion use core::fmt;
390ac295eSAlex Crichton use cranelift_codegen::{LabelValueLoc, ValueLabelsRanges, ir::ValueLabel, isa::TargetIsa};
4*c4a38d67SPhilip Craig use gimli::{AttributeValue, LittleEndian, UnitRef, write};
592cc0ad7SSingleAccretion 
61c521e17SSingleAccretion macro_rules! dbi_log_enabled {
71c521e17SSingleAccretion     () => {
81c521e17SSingleAccretion         cfg!(any(feature = "trace-log", debug_assertions))
91c521e17SSingleAccretion             && ::log::log_enabled!(target: "debug-info-transform", ::log::Level::Trace)
101c521e17SSingleAccretion     };
111c521e17SSingleAccretion }
1292cc0ad7SSingleAccretion macro_rules! dbi_log {
1392cc0ad7SSingleAccretion     ($($tt:tt)*) => {
1492cc0ad7SSingleAccretion         if cfg!(any(feature = "trace-log", debug_assertions)) {
1592cc0ad7SSingleAccretion             ::log::trace!(target: "debug-info-transform", $($tt)*);
1692cc0ad7SSingleAccretion         }
1792cc0ad7SSingleAccretion     };
1892cc0ad7SSingleAccretion }
1992cc0ad7SSingleAccretion pub(crate) use dbi_log;
201c521e17SSingleAccretion pub(crate) use dbi_log_enabled;
2192cc0ad7SSingleAccretion 
22bd7b59daSPhilip Craig pub struct CompileUnitSummary<'a, 'r> {
23bd7b59daSPhilip Craig     unit: UnitRef<'a, Reader<'r>>,
2492cc0ad7SSingleAccretion }
2592cc0ad7SSingleAccretion 
26bd7b59daSPhilip Craig impl<'a, 'r> fmt::Debug for CompileUnitSummary<'a, 'r> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2792cc0ad7SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2892cc0ad7SSingleAccretion         let unit = self.unit;
297ee620a5SPhilip Craig         write!(f, "0x{:08x} [", unit.header.offset().0)?;
3092cc0ad7SSingleAccretion         let comp_dir = match unit.comp_dir {
3192cc0ad7SSingleAccretion             Some(dir) => &dir.to_string_lossy(),
3292cc0ad7SSingleAccretion             None => "None",
3392cc0ad7SSingleAccretion         };
3492cc0ad7SSingleAccretion         write!(f, "\"{comp_dir}\"")?;
3592cc0ad7SSingleAccretion         let name = match unit.name {
3692cc0ad7SSingleAccretion             Some(name) => &name.to_string_lossy(),
3792cc0ad7SSingleAccretion             None => "None",
3892cc0ad7SSingleAccretion         };
3992cc0ad7SSingleAccretion         write!(f, ", \"{name}\"]")
4092cc0ad7SSingleAccretion     }
4192cc0ad7SSingleAccretion }
4292cc0ad7SSingleAccretion 
log_get_cu_summary<'a, 'r>(unit: UnitRef<'a, Reader<'r>>) -> CompileUnitSummary<'a, 'r>43bd7b59daSPhilip Craig pub fn log_get_cu_summary<'a, 'r>(unit: UnitRef<'a, Reader<'r>>) -> CompileUnitSummary<'a, 'r> {
4492cc0ad7SSingleAccretion     CompileUnitSummary { unit }
4592cc0ad7SSingleAccretion }
4692cc0ad7SSingleAccretion 
47bd7b59daSPhilip Craig pub struct DieRefSummary<'a, 'r> {
48*c4a38d67SPhilip Craig     entry: &'a write::ConvertUnitEntry<'a, Reader<'r>>,
490b2c9d72SSingleAccretion }
500b2c9d72SSingleAccretion 
51bd7b59daSPhilip Craig impl<'a, 'r> fmt::Debug for DieRefSummary<'a, 'r> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result520b2c9d72SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53*c4a38d67SPhilip Craig         let section_offs = self
54*c4a38d67SPhilip Craig             .entry
55*c4a38d67SPhilip Craig             .offset
56*c4a38d67SPhilip Craig             .to_unit_section_offset(&self.entry.read_unit);
577ee620a5SPhilip Craig         write!(f, "0x{:08x}", section_offs.0)
580b2c9d72SSingleAccretion     }
590b2c9d72SSingleAccretion }
600b2c9d72SSingleAccretion 
log_get_die_ref<'a, 'r>( entry: &'a write::ConvertUnitEntry<'a, Reader<'r>>, ) -> DieRefSummary<'a, 'r>61bd7b59daSPhilip Craig pub fn log_get_die_ref<'a, 'r>(
62*c4a38d67SPhilip Craig     entry: &'a write::ConvertUnitEntry<'a, Reader<'r>>,
63bd7b59daSPhilip Craig ) -> DieRefSummary<'a, 'r> {
64*c4a38d67SPhilip Craig     DieRefSummary { entry }
650b2c9d72SSingleAccretion }
660b2c9d72SSingleAccretion 
67bd7b59daSPhilip Craig struct DieDetailedSummary<'a, 'r> {
68*c4a38d67SPhilip Craig     entry: &'a write::ConvertUnitEntry<'a, Reader<'r>>,
6992cc0ad7SSingleAccretion }
7092cc0ad7SSingleAccretion 
log_begin_input_die<'a, 'r>(entry: &'a write::ConvertUnitEntry<'a, Reader<'r>>)71*c4a38d67SPhilip Craig pub fn log_begin_input_die<'a, 'r>(entry: &'a write::ConvertUnitEntry<'a, Reader<'r>>) {
7292cc0ad7SSingleAccretion     dbi_log!(
730b2c9d72SSingleAccretion         "=== Begin DIE at {:?} (depth = {}):\n{:?}",
74*c4a38d67SPhilip Craig         log_get_die_ref(entry),
75*c4a38d67SPhilip Craig         entry.depth,
76*c4a38d67SPhilip Craig         DieDetailedSummary { entry }
7792cc0ad7SSingleAccretion     );
7892cc0ad7SSingleAccretion }
7992cc0ad7SSingleAccretion 
80bd7b59daSPhilip Craig impl<'a, 'r> fmt::Debug for DieDetailedSummary<'a, 'r> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result8192cc0ad7SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82*c4a38d67SPhilip Craig         let unit = self.entry.read_unit;
83*c4a38d67SPhilip Craig         write!(f, "{}\n", self.entry.tag)?;
8492cc0ad7SSingleAccretion 
85*c4a38d67SPhilip Craig         for attr in &self.entry.attrs {
8692cc0ad7SSingleAccretion             write!(f, "  {} (", attr.name())?;
8792cc0ad7SSingleAccretion             let attr_value = attr.value();
8892cc0ad7SSingleAccretion             match attr_value {
8992cc0ad7SSingleAccretion                 AttributeValue::Addr(addr) => {
9092cc0ad7SSingleAccretion                     write!(f, "{addr:08x}")
9192cc0ad7SSingleAccretion                 }
9292cc0ad7SSingleAccretion                 AttributeValue::DebugAddrIndex(index) => {
93bd7b59daSPhilip Craig                     if let Some(addr) = unit.address(index).ok() {
9492cc0ad7SSingleAccretion                         write!(f, "{addr:08x}")
9592cc0ad7SSingleAccretion                     } else {
9692cc0ad7SSingleAccretion                         write!(f, "<error reading address at index: {}>", index.0)
9792cc0ad7SSingleAccretion                     }
9892cc0ad7SSingleAccretion                 }
9992cc0ad7SSingleAccretion                 AttributeValue::Block(d) => write!(f, "{d:?}"),
10092cc0ad7SSingleAccretion                 AttributeValue::Udata(d) => write!(f, "{d}"),
10192cc0ad7SSingleAccretion                 AttributeValue::Data1(d) => write!(f, "{d}"),
10292cc0ad7SSingleAccretion                 AttributeValue::Data2(d) => write!(f, "{d}"),
10392cc0ad7SSingleAccretion                 AttributeValue::Data4(d) => write!(f, "{d}"),
10492cc0ad7SSingleAccretion                 AttributeValue::Data8(d) => write!(f, "{d}"),
10592cc0ad7SSingleAccretion                 AttributeValue::Sdata(d) => write!(f, "{d}"),
10692cc0ad7SSingleAccretion                 AttributeValue::Flag(d) => write!(f, "{d}"),
10792cc0ad7SSingleAccretion                 AttributeValue::DebugLineRef(offset) => write!(f, "0x{:08x}", offset.0),
10892cc0ad7SSingleAccretion                 AttributeValue::FileIndex(index) => write!(f, "0x{index:08x}"),
10992cc0ad7SSingleAccretion                 AttributeValue::String(_)
11092cc0ad7SSingleAccretion                 | AttributeValue::DebugStrRef(_)
11192cc0ad7SSingleAccretion                 | AttributeValue::DebugStrOffsetsIndex(_) => {
112bd7b59daSPhilip Craig                     if let Ok(s) = unit.attr_string(attr_value) {
11392cc0ad7SSingleAccretion                         write!(f, "\"{}\"", &s.to_string_lossy())
11492cc0ad7SSingleAccretion                     } else {
11592cc0ad7SSingleAccretion                         write!(f, "<error reading string>")
11692cc0ad7SSingleAccretion                     }
11792cc0ad7SSingleAccretion                 }
11892cc0ad7SSingleAccretion                 AttributeValue::RangeListsRef(_) | AttributeValue::DebugRngListsIndex(_) => {
119bd7b59daSPhilip Craig                     let _ = unit.attr_ranges_offset(attr_value);
12092cc0ad7SSingleAccretion                     write!(f, "<TODO: rnglist dump>")
12192cc0ad7SSingleAccretion                 }
12292cc0ad7SSingleAccretion                 AttributeValue::LocationListsRef(_) | AttributeValue::DebugLocListsIndex(_) => {
123bd7b59daSPhilip Craig                     let _ = unit.attr_locations_offset(attr_value);
12492cc0ad7SSingleAccretion                     write!(f, "<TODO: loclist dump>")
12592cc0ad7SSingleAccretion                 }
12692cc0ad7SSingleAccretion                 AttributeValue::Exprloc(_) => {
12792cc0ad7SSingleAccretion                     write!(f, "<TODO: exprloc dump>")
12892cc0ad7SSingleAccretion                 }
12992cc0ad7SSingleAccretion                 AttributeValue::Encoding(value) => write!(f, "{value}"),
13092cc0ad7SSingleAccretion                 AttributeValue::DecimalSign(value) => write!(f, "{value}"),
13192cc0ad7SSingleAccretion                 AttributeValue::Endianity(value) => write!(f, "{value}"),
13292cc0ad7SSingleAccretion                 AttributeValue::Accessibility(value) => write!(f, "{value}"),
13392cc0ad7SSingleAccretion                 AttributeValue::Visibility(value) => write!(f, "{value}"),
13492cc0ad7SSingleAccretion                 AttributeValue::Virtuality(value) => write!(f, "{value}"),
13592cc0ad7SSingleAccretion                 AttributeValue::Language(value) => write!(f, "{value}"),
13692cc0ad7SSingleAccretion                 AttributeValue::AddressClass(value) => write!(f, "{value}"),
13792cc0ad7SSingleAccretion                 AttributeValue::IdentifierCase(value) => write!(f, "{value}"),
13892cc0ad7SSingleAccretion                 AttributeValue::CallingConvention(value) => write!(f, "{value}"),
13992cc0ad7SSingleAccretion                 AttributeValue::Inline(value) => write!(f, "{value}"),
14092cc0ad7SSingleAccretion                 AttributeValue::Ordering(value) => write!(f, "{value}"),
14141ff8e7bSSingleAccretion                 AttributeValue::UnitRef(offset) => {
1427ee620a5SPhilip Craig                     write!(f, "0x{:08x}", offset.to_unit_section_offset(&unit).0)
14341ff8e7bSSingleAccretion                 }
14492cc0ad7SSingleAccretion                 AttributeValue::DebugInfoRef(offset) => write!(f, "0x{:08x}", offset.0),
14592cc0ad7SSingleAccretion                 unexpected_attr => write!(f, "<unexpected attr: {unexpected_attr:?}>"),
14692cc0ad7SSingleAccretion             }?;
14792cc0ad7SSingleAccretion             write!(f, ")\n")?;
14892cc0ad7SSingleAccretion         }
14992cc0ad7SSingleAccretion         Ok(())
15092cc0ad7SSingleAccretion     }
15192cc0ad7SSingleAccretion }
15292cc0ad7SSingleAccretion 
15392cc0ad7SSingleAccretion struct OutDieDetailedSummary<'a> {
15492cc0ad7SSingleAccretion     die_id: write::UnitEntryId,
15592cc0ad7SSingleAccretion     unit: &'a write::Unit,
15692cc0ad7SSingleAccretion     strings: &'a write::StringTable,
15792cc0ad7SSingleAccretion }
15892cc0ad7SSingleAccretion 
15992cc0ad7SSingleAccretion impl<'a> fmt::Debug for OutDieDetailedSummary<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result16092cc0ad7SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16192cc0ad7SSingleAccretion         let die = self.unit.get(self.die_id);
16292cc0ad7SSingleAccretion         write!(f, "{}\n", die.tag())?;
16392cc0ad7SSingleAccretion         for attr in die.attrs() {
16492cc0ad7SSingleAccretion             write!(f, "  {} (", attr.name())?;
16592cc0ad7SSingleAccretion             let attr_value = attr.get();
16692cc0ad7SSingleAccretion             match attr_value {
16792cc0ad7SSingleAccretion                 write::AttributeValue::Address(addr) => match addr {
16892cc0ad7SSingleAccretion                     write::Address::Constant(addr_value) => write!(f, "{addr_value:08x}"),
16992cc0ad7SSingleAccretion                     write::Address::Symbol { symbol, addend } => {
17092cc0ad7SSingleAccretion                         write!(f, "symbol #{symbol}+{addend}")
17192cc0ad7SSingleAccretion                     }
17292cc0ad7SSingleAccretion                 },
17392cc0ad7SSingleAccretion                 write::AttributeValue::Block(d) => {
17492cc0ad7SSingleAccretion                     write!(f, "{:?}", Reader::new(d.as_slice(), LittleEndian))
17592cc0ad7SSingleAccretion                 }
17692cc0ad7SSingleAccretion                 write::AttributeValue::Udata(d) => write!(f, "{d}"),
17792cc0ad7SSingleAccretion                 write::AttributeValue::Data1(d) => write!(f, "{d}"),
17892cc0ad7SSingleAccretion                 write::AttributeValue::Data2(d) => write!(f, "{d}"),
17992cc0ad7SSingleAccretion                 write::AttributeValue::Data4(d) => write!(f, "{d}"),
18092cc0ad7SSingleAccretion                 write::AttributeValue::Data8(d) => write!(f, "{d}"),
18192cc0ad7SSingleAccretion                 write::AttributeValue::Sdata(d) => write!(f, "{d}"),
18292cc0ad7SSingleAccretion                 write::AttributeValue::Flag(d) => write!(f, "{d}"),
18392cc0ad7SSingleAccretion                 write::AttributeValue::LineProgramRef => write!(f, "LineProgramRef"),
18492cc0ad7SSingleAccretion                 write::AttributeValue::FileIndex(index) => match index {
18592cc0ad7SSingleAccretion                     Some(id) => write!(f, "{id:?}"),
18692cc0ad7SSingleAccretion                     None => write!(f, "<file index missing>"),
18792cc0ad7SSingleAccretion                 },
18892cc0ad7SSingleAccretion                 write::AttributeValue::String(s) => {
18992cc0ad7SSingleAccretion                     write!(f, "\"{}\"", &String::from_utf8_lossy(s))
19092cc0ad7SSingleAccretion                 }
19192cc0ad7SSingleAccretion                 write::AttributeValue::StringRef(id) => {
19292cc0ad7SSingleAccretion                     write!(f, "\"{}\"", &String::from_utf8_lossy(self.strings.get(*id)))
19392cc0ad7SSingleAccretion                 }
19492cc0ad7SSingleAccretion                 write::AttributeValue::RangeListRef(_) => {
19592cc0ad7SSingleAccretion                     write!(f, "<TODO: out rnglist dump>")
19692cc0ad7SSingleAccretion                 }
19792cc0ad7SSingleAccretion                 write::AttributeValue::LocationListRef(_) => {
19892cc0ad7SSingleAccretion                     write!(f, "<TODO: out loclist dump>")
19992cc0ad7SSingleAccretion                 }
20092cc0ad7SSingleAccretion                 write::AttributeValue::Exprloc(_) => {
20192cc0ad7SSingleAccretion                     write!(f, "<TODO: out exprloc dump>")
20292cc0ad7SSingleAccretion                 }
20392cc0ad7SSingleAccretion                 write::AttributeValue::Encoding(value) => write!(f, "{value}"),
20492cc0ad7SSingleAccretion                 write::AttributeValue::DecimalSign(value) => write!(f, "{value}"),
20592cc0ad7SSingleAccretion                 write::AttributeValue::Endianity(value) => write!(f, "{value}"),
20692cc0ad7SSingleAccretion                 write::AttributeValue::Accessibility(value) => write!(f, "{value}"),
20792cc0ad7SSingleAccretion                 write::AttributeValue::Visibility(value) => write!(f, "{value}"),
20892cc0ad7SSingleAccretion                 write::AttributeValue::Virtuality(value) => write!(f, "{value}"),
20992cc0ad7SSingleAccretion                 write::AttributeValue::Language(value) => write!(f, "{value}"),
21092cc0ad7SSingleAccretion                 write::AttributeValue::AddressClass(value) => write!(f, "{value}"),
21192cc0ad7SSingleAccretion                 write::AttributeValue::IdentifierCase(value) => write!(f, "{value}"),
21292cc0ad7SSingleAccretion                 write::AttributeValue::CallingConvention(value) => write!(f, "{value}"),
21392cc0ad7SSingleAccretion                 write::AttributeValue::Inline(value) => write!(f, "{value}"),
21492cc0ad7SSingleAccretion                 write::AttributeValue::Ordering(value) => write!(f, "{value}"),
21592cc0ad7SSingleAccretion                 write::AttributeValue::UnitRef(unit_ref) => write!(f, "{unit_ref:?}>"),
21692cc0ad7SSingleAccretion                 write::AttributeValue::DebugInfoRef(reference) => match reference {
2177ee620a5SPhilip Craig                     write::DebugInfoRef::Symbol(index) => write!(f, "symbol #{index}>"),
2187ee620a5SPhilip Craig                     write::DebugInfoRef::Entry(unit_id, die_id) => {
21992cc0ad7SSingleAccretion                         write!(f, "{die_id:?} in {unit_id:?}>")
22092cc0ad7SSingleAccretion                     }
22192cc0ad7SSingleAccretion                 },
22292cc0ad7SSingleAccretion                 unexpected_attr => write!(f, "<unexpected attr: {unexpected_attr:?}>"),
22392cc0ad7SSingleAccretion             }?;
22492cc0ad7SSingleAccretion             write!(f, ")\n")?;
22592cc0ad7SSingleAccretion         }
22692cc0ad7SSingleAccretion         Ok(())
22792cc0ad7SSingleAccretion     }
22892cc0ad7SSingleAccretion }
22992cc0ad7SSingleAccretion 
log_end_output_die( die_id: write::UnitEntryId, entry: &write::ConvertUnitEntry<'_, Reader<'_>>, unit: &write::ConvertUnit<'_, Reader<'_>>, )23092cc0ad7SSingleAccretion pub fn log_end_output_die(
23192cc0ad7SSingleAccretion     die_id: write::UnitEntryId,
232*c4a38d67SPhilip Craig     entry: &write::ConvertUnitEntry<'_, Reader<'_>>,
233*c4a38d67SPhilip Craig     unit: &write::ConvertUnit<'_, Reader<'_>>,
23492cc0ad7SSingleAccretion ) {
23592cc0ad7SSingleAccretion     dbi_log!(
2360b2c9d72SSingleAccretion         "=== End DIE at {:?} (depth = {}):\n{:?}",
237*c4a38d67SPhilip Craig         log_get_die_ref(entry),
238*c4a38d67SPhilip Craig         entry.depth,
23992cc0ad7SSingleAccretion         OutDieDetailedSummary {
24092cc0ad7SSingleAccretion             die_id,
241*c4a38d67SPhilip Craig             unit: &unit.unit,
242*c4a38d67SPhilip Craig             strings: &unit.strings,
24392cc0ad7SSingleAccretion         }
24492cc0ad7SSingleAccretion     );
24592cc0ad7SSingleAccretion }
24692cc0ad7SSingleAccretion 
log_end_output_die_skipped(entry: &write::ConvertUnitEntry<'_, Reader<'_>>, reason: &str)247*c4a38d67SPhilip Craig pub fn log_end_output_die_skipped(entry: &write::ConvertUnitEntry<'_, Reader<'_>>, reason: &str) {
24892cc0ad7SSingleAccretion     dbi_log!(
2490b2c9d72SSingleAccretion         "=== End DIE at {:?} (depth = {}):\n  Skipped as {}\n",
250*c4a38d67SPhilip Craig         log_get_die_ref(entry),
251*c4a38d67SPhilip Craig         entry.depth,
25292cc0ad7SSingleAccretion         reason
25392cc0ad7SSingleAccretion     );
25492cc0ad7SSingleAccretion }
255a126152dSSingleAccretion 
log_get_value_name(value: ValueLabel) -> ValueNameSummary2561c521e17SSingleAccretion pub fn log_get_value_name(value: ValueLabel) -> ValueNameSummary {
2571c521e17SSingleAccretion     ValueNameSummary { value }
2581c521e17SSingleAccretion }
2591c521e17SSingleAccretion 
2601c521e17SSingleAccretion pub struct ValueNameSummary {
2611c521e17SSingleAccretion     value: ValueLabel,
2621c521e17SSingleAccretion }
2631c521e17SSingleAccretion 
2641c521e17SSingleAccretion impl fmt::Debug for ValueNameSummary {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2651c521e17SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2661c521e17SSingleAccretion         if self.value == get_vmctx_value_label() {
2671c521e17SSingleAccretion             f.pad("VMCTX")
2681c521e17SSingleAccretion         } else {
2691c521e17SSingleAccretion             f.pad(&format!("L#{}", self.value.as_u32()))
2701c521e17SSingleAccretion         }
2711c521e17SSingleAccretion     }
2721c521e17SSingleAccretion }
2731c521e17SSingleAccretion 
log_get_value_loc(loc: LabelValueLoc, isa: &dyn TargetIsa) -> ValueLocSummary<'_>2748a42768fSAlex Crichton pub fn log_get_value_loc(loc: LabelValueLoc, isa: &dyn TargetIsa) -> ValueLocSummary<'_> {
2751c521e17SSingleAccretion     ValueLocSummary { loc, isa }
2761c521e17SSingleAccretion }
2771c521e17SSingleAccretion 
2781c521e17SSingleAccretion pub struct ValueLocSummary<'a> {
2791c521e17SSingleAccretion     loc: LabelValueLoc,
2801c521e17SSingleAccretion     isa: &'a dyn TargetIsa,
2811c521e17SSingleAccretion }
2821c521e17SSingleAccretion 
2831c521e17SSingleAccretion impl<'a> fmt::Debug for ValueLocSummary<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2841c521e17SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2851c521e17SSingleAccretion         if let LabelValueLoc::Reg(reg) = self.loc {
2861c521e17SSingleAccretion             let reg_name = self.isa.pretty_print_reg(reg, self.isa.pointer_bytes());
2871c521e17SSingleAccretion             return write!(f, "{reg_name}");
2881c521e17SSingleAccretion         }
2891c521e17SSingleAccretion 
2901c521e17SSingleAccretion         write!(f, "{:?}", self.loc)
2911c521e17SSingleAccretion     }
2921c521e17SSingleAccretion }
2931c521e17SSingleAccretion 
log_get_value_ranges<'a>( ranges: Option<&'a ValueLabelsRanges>, isa: &'a dyn TargetIsa, ) -> ValueRangesSummary<'a>2941c521e17SSingleAccretion pub fn log_get_value_ranges<'a>(
2951c521e17SSingleAccretion     ranges: Option<&'a ValueLabelsRanges>,
2961c521e17SSingleAccretion     isa: &'a dyn TargetIsa,
2971c521e17SSingleAccretion ) -> ValueRangesSummary<'a> {
2981c521e17SSingleAccretion     ValueRangesSummary { ranges, isa }
2991c521e17SSingleAccretion }
3001c521e17SSingleAccretion 
3011c521e17SSingleAccretion pub struct ValueRangesSummary<'a> {
3021c521e17SSingleAccretion     ranges: Option<&'a ValueLabelsRanges>,
3031c521e17SSingleAccretion     isa: &'a dyn TargetIsa,
3041c521e17SSingleAccretion }
3051c521e17SSingleAccretion 
3061c521e17SSingleAccretion impl<'a> fmt::Debug for ValueRangesSummary<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result3071c521e17SSingleAccretion     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3081c521e17SSingleAccretion         if let Some(ranges) = self.ranges {
3091c521e17SSingleAccretion             // Sort the output first for nicer display.
3101c521e17SSingleAccretion             let mut locals = Vec::new();
3111c521e17SSingleAccretion             for value in ranges {
3121c521e17SSingleAccretion                 locals.push(*value.0);
3131c521e17SSingleAccretion             }
3141c521e17SSingleAccretion             locals.sort_by_key(|n| n.as_u32());
3151c521e17SSingleAccretion 
3161c521e17SSingleAccretion             for i in 0..locals.len() {
3171c521e17SSingleAccretion                 let name = locals[i];
3181c521e17SSingleAccretion                 write!(f, "{:<6?}:", log_get_value_name(name))?;
3191c521e17SSingleAccretion                 for range in ranges.get(&name).unwrap() {
3201c521e17SSingleAccretion                     write!(f, " {:?}", log_get_value_loc(range.loc, self.isa))?;
3211c521e17SSingleAccretion                     write!(f, "@[{}..{})", range.start, range.end)?;
3221c521e17SSingleAccretion                 }
3231c521e17SSingleAccretion                 if i != locals.len() - 1 {
3241c521e17SSingleAccretion                     writeln!(f)?;
3251c521e17SSingleAccretion                 }
3261c521e17SSingleAccretion             }
3271c521e17SSingleAccretion         }
3281c521e17SSingleAccretion         Ok(())
3291c521e17SSingleAccretion     }
3301c521e17SSingleAccretion }
331