rustc_mir_dataflow/
pretty.rs1use std::io;
2
3use rustc_attr_ir::{RustcMirKind, find_attr};
4use rustc_data_structures::fx::FxIndexMap;
5use rustc_middle::mir::{self, Body, Local, MirDumper, PassWhere, traversal};
6use rustc_middle::ty::TyCtxt;
7
8use crate::debuginfo::debuginfo_locals;
9use crate::framework::Analysis;
10use crate::impls::{
11 MaybeLiveLocals, MaybeTransitiveLiveLocals, SplitPointEffect, SplitPointIndex, borrowed_locals,
12 liveness_matrix,
13};
14use crate::points::DenseLocationMap;
15use crate::{ResultsVisitor, visit_results};
16
17type ExtraDataFn = dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>;
18
19pub(crate) fn mir_pretty_extra_data<'tcx>(
20 tcx: TyCtxt<'tcx>,
21 body: &Body<'tcx>,
22) -> Option<Box<ExtraDataFn>> {
23 let def_id = body.source.def_id();
24 let Some(kinds) = {
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx) {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcMir(kind)) => {
break 'done Some(kind);
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(tcx, def_id, RustcMir(kind) => kind) else {
25 return None;
26 };
27 let mut annotations = Annotations::default();
28 for kind in kinds {
29 match kind {
30 RustcMirKind::PrettyLiveLocals => {
31 let results = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None);
32 let blocks = traversal::reachable(body).map(|(bb, _)| bb);
33 visit_results(
34 body,
35 blocks,
36 &results,
37 &mut Annotator { annotations: &mut annotations },
38 );
39 }
40 RustcMirKind::PrettyPreciseLiveness => {
41 let points = DenseLocationMap::new(body);
42 let matrix = liveness_matrix(tcx, body, &points, None);
43 for (block, data) in body.basic_blocks.iter_enumerated() {
44 for statement_index in 0..=data.statements.len() {
45 let location = mir::Location { block, statement_index };
46 let point = points.point_from_location(location);
47 let locals_live_at = |effect| {
48 let split_point = SplitPointIndex::new(point, effect);
49 matrix
50 .rows()
51 .filter(|&r| matrix.contains(r, split_point))
52 .collect::<Vec<_>>()
53 };
54 let early = locals_live_at(SplitPointEffect::Early);
55 annotations
56 .add(PassWhere::BeforeLocation(location), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("early: {0:?}", early))
})format!("early: {early:?}"));
57 let late = locals_live_at(SplitPointEffect::Late);
58 annotations
59 .add(PassWhere::BeforeLocation(location), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("late: {0:?}", late))
})format!("late: {late:?}"));
60 }
61 }
62 }
63 RustcMirKind::PrettyTransitiveLiveLocals => {
64 let borrowed_locals = borrowed_locals(body);
65 let debuginfo_locals = debuginfo_locals(body);
66 let results = MaybeTransitiveLiveLocals::new(&borrowed_locals, &debuginfo_locals)
67 .iterate_to_fixpoint(tcx, body, None);
68 let blocks = traversal::reachable(body).map(|(bb, _)| bb);
69 visit_results(
70 body,
71 blocks,
72 &results,
73 &mut Annotator { annotations: &mut annotations },
74 );
75 }
76 _ => {}
77 }
78 }
79 let extra_data = annotations.into_extra_data()?;
80 if let Some(dumper) = MirDumper::new(tcx, "dataflow", body) {
81 dumper.set_extra_data(&*extra_data).dump_mir(body);
82 }
83 Some(extra_data)
84}
85
86#[derive(#[automatically_derived]
impl ::core::default::Default for Annotations {
#[inline]
fn default() -> Self {
Annotations { entries: ::core::default::Default::default() }
}
}Default)]
87struct Annotations {
88 entries: FxIndexMap<PassWhere, Vec<String>>,
89}
90
91impl Annotations {
92 fn add(&mut self, pass_where: PassWhere, s: String) {
93 self.entries.entry(pass_where).or_default().push(s);
94 }
95
96 fn into_extra_data(self) -> Option<Box<ExtraDataFn>> {
97 if self.entries.is_empty() {
98 return None;
99 }
100 Some(Box::new(move |pass_where: PassWhere, out: &mut dyn io::Write| {
101 let Some(notes) = self.entries.get(&pass_where) else {
102 return Ok(());
103 };
104 for s in notes {
105 out.write_fmt(format_args!(" // {0}\n", s))writeln!(out, " // {s}")?;
106 }
107 Ok(())
108 }))
109 }
110}
111
112struct Annotator<'a> {
114 annotations: &'a mut Annotations,
115}
116
117impl<'tcx> ResultsVisitor<'tcx, MaybeLiveLocals> for Annotator<'_> {
118 fn visit_after_primary_statement_effect(
119 &mut self,
120 state: &<MaybeLiveLocals as Analysis<'tcx>>::Domain,
121 _statement: &mir::Statement<'tcx>,
122 location: mir::Location,
123 ) {
124 let live: Vec<Local> = state.iter().collect();
125 self.annotations.add(PassWhere::BeforeLocation(location), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("live: {0:?}", live))
})format!("live: {live:?}"));
126 }
127
128 fn visit_after_primary_terminator_effect(
129 &mut self,
130 state: &<MaybeLiveLocals as Analysis<'tcx>>::Domain,
131 _terminator: &mir::Terminator<'tcx>,
132 location: mir::Location,
133 ) {
134 let live: Vec<Local> = state.iter().collect();
135 self.annotations.add(PassWhere::BeforeLocation(location), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("live: {0:?}", live))
})format!("live: {live:?}"));
136 }
137}
138
139impl<'tcx> ResultsVisitor<'tcx, MaybeTransitiveLiveLocals<'_>> for Annotator<'_> {
140 fn visit_after_primary_statement_effect(
141 &mut self,
142 state: &<MaybeLiveLocals as Analysis<'tcx>>::Domain,
143 _statement: &mir::Statement<'tcx>,
144 location: mir::Location,
145 ) {
146 let live: Vec<Local> = state.iter().collect();
147 self.annotations.add(PassWhere::BeforeLocation(location), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("live: {0:?}", live))
})format!("live: {live:?}"));
148 }
149
150 fn visit_after_primary_terminator_effect(
151 &mut self,
152 state: &<MaybeLiveLocals as Analysis<'tcx>>::Domain,
153 _terminator: &mir::Terminator<'tcx>,
154 location: mir::Location,
155 ) {
156 let live: Vec<Local> = state.iter().collect();
157 self.annotations.add(PassWhere::BeforeLocation(location), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("live: {0:?}", live))
})format!("live: {live:?}"));
158 }
159}