Remove another use of as_results_cursor
.
The new code is a little clunky, but I couldn't see how to make it better.
This commit is contained in:
parent
3dea72aa1b
commit
cf82b410f9
3 changed files with 62 additions and 40 deletions
|
@ -271,29 +271,31 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut results = Results { analysis, entry_sets, _marker: PhantomData };
|
let results = Results { analysis, entry_sets, _marker: PhantomData };
|
||||||
|
|
||||||
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
|
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
|
||||||
let res = write_graphviz_results(tcx, body, &mut results, pass_name);
|
let (res, results) = write_graphviz_results(tcx, body, results, pass_name);
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
error!("Failed to write graphviz dataflow results: {}", e);
|
error!("Failed to write graphviz dataflow results: {}", e);
|
||||||
}
|
}
|
||||||
|
results
|
||||||
|
} else {
|
||||||
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
results
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Graphviz
|
// Graphviz
|
||||||
|
|
||||||
/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
|
/// Writes a DOT file containing the results of a dataflow analysis if the user requested it via
|
||||||
/// `rustc_mir` attributes and `-Z dump-mir-dataflow`.
|
/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are
|
||||||
|
/// the same.
|
||||||
fn write_graphviz_results<'tcx, A>(
|
fn write_graphviz_results<'tcx, A>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &mir::Body<'tcx>,
|
body: &mir::Body<'tcx>,
|
||||||
results: &mut Results<'tcx, A>,
|
results: Results<'tcx, A>,
|
||||||
pass_name: Option<&'static str>,
|
pass_name: Option<&'static str>,
|
||||||
) -> std::io::Result<()>
|
) -> (std::io::Result<()>, Results<'tcx, A>)
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
A::Domain: DebugWithContext<A>,
|
A::Domain: DebugWithContext<A>,
|
||||||
|
@ -304,23 +306,30 @@ where
|
||||||
let def_id = body.source.def_id();
|
let def_id = body.source.def_id();
|
||||||
let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else {
|
let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else {
|
||||||
// Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse`
|
// Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse`
|
||||||
return Ok(());
|
return (Ok(()), results);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut file = match attrs.output_path(A::NAME) {
|
let file = try {
|
||||||
Some(path) => {
|
match attrs.output_path(A::NAME) {
|
||||||
debug!("printing dataflow results for {:?} to {}", def_id, path.display());
|
Some(path) => {
|
||||||
if let Some(parent) = path.parent() {
|
debug!("printing dataflow results for {:?} to {}", def_id, path.display());
|
||||||
fs::create_dir_all(parent)?;
|
if let Some(parent) = path.parent() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
let f = fs::File::create(&path)?;
|
||||||
|
io::BufWriter::new(f)
|
||||||
}
|
}
|
||||||
io::BufWriter::new(fs::File::create(&path)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
None if dump_enabled(tcx, A::NAME, def_id) => {
|
None if dump_enabled(tcx, A::NAME, def_id) => {
|
||||||
create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)?
|
create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)?
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => return Ok(()),
|
_ => return (Ok(()), results),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut file = match file {
|
||||||
|
Ok(f) => f,
|
||||||
|
Err(e) => return (Err(e), results),
|
||||||
};
|
};
|
||||||
|
|
||||||
let style = match attrs.formatter {
|
let style = match attrs.formatter {
|
||||||
|
@ -336,11 +345,14 @@ where
|
||||||
if tcx.sess.opts.unstable_opts.graphviz_dark_mode {
|
if tcx.sess.opts.unstable_opts.graphviz_dark_mode {
|
||||||
render_opts.push(dot::RenderOption::DarkTheme);
|
render_opts.push(dot::RenderOption::DarkTheme);
|
||||||
}
|
}
|
||||||
with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)?);
|
let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts));
|
||||||
|
|
||||||
file.write_all(&buf)?;
|
let lhs = try {
|
||||||
|
r?;
|
||||||
|
file.write_all(&buf)?;
|
||||||
|
};
|
||||||
|
|
||||||
Ok(())
|
(lhs, graphviz.into_results())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rustc_middle::mir::graphviz_safe_def_name;
|
||||||
use rustc_middle::mir::{self, BasicBlock, Body, Location};
|
use rustc_middle::mir::{self, BasicBlock, Body, Location};
|
||||||
|
|
||||||
use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
|
use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
|
||||||
use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor};
|
use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum OutputStyle {
|
pub(crate) enum OutputStyle {
|
||||||
|
@ -29,27 +29,31 @@ impl OutputStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Formatter<'res, 'mir, 'tcx, A>
|
pub(crate) struct Formatter<'mir, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
body: &'mir Body<'tcx>,
|
body: &'mir Body<'tcx>,
|
||||||
results: RefCell<&'res mut Results<'tcx, A>>,
|
results: RefCell<Option<Results<'tcx, A>>>,
|
||||||
style: OutputStyle,
|
style: OutputStyle,
|
||||||
reachable: BitSet<BasicBlock>,
|
reachable: BitSet<BasicBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A>
|
impl<'mir, 'tcx, A> Formatter<'mir, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
body: &'mir Body<'tcx>,
|
body: &'mir Body<'tcx>,
|
||||||
results: &'res mut Results<'tcx, A>,
|
results: Results<'tcx, A>,
|
||||||
style: OutputStyle,
|
style: OutputStyle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let reachable = mir::traversal::reachable_as_bitset(body);
|
let reachable = mir::traversal::reachable_as_bitset(body);
|
||||||
Formatter { body, results: results.into(), style, reachable }
|
Formatter { body, results: Some(results).into(), style, reachable }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn into_results(self) -> Results<'tcx, A> {
|
||||||
|
self.results.into_inner().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +73,7 @@ fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec<CfgEdge> {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, '_, 'tcx, A>
|
impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
A::Domain: DebugWithContext<A>,
|
A::Domain: DebugWithContext<A>,
|
||||||
|
@ -88,14 +92,19 @@ where
|
||||||
|
|
||||||
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
|
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
|
||||||
let mut label = Vec::new();
|
let mut label = Vec::new();
|
||||||
let mut results = self.results.borrow_mut();
|
self.results.replace_with(|results| {
|
||||||
let mut fmt = BlockFormatter {
|
// `Formatter::result` is a `RefCell<Option<_>>` so we can replace
|
||||||
results: results.as_results_cursor(self.body),
|
// the value with `None`, move it into the results cursor, move it
|
||||||
style: self.style,
|
// back out, and return it to the refcell wrapped in `Some`.
|
||||||
bg: Background::Light,
|
let mut fmt = BlockFormatter {
|
||||||
};
|
results: results.take().unwrap().into_results_cursor(self.body),
|
||||||
|
style: self.style,
|
||||||
|
bg: Background::Light,
|
||||||
|
};
|
||||||
|
|
||||||
fmt.write_node_label(&mut label, *block).unwrap();
|
fmt.write_node_label(&mut label, *block).unwrap();
|
||||||
|
Some(fmt.results.into_results())
|
||||||
|
});
|
||||||
dot::LabelText::html(String::from_utf8(label).unwrap())
|
dot::LabelText::html(String::from_utf8(label).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +118,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'_, 'mir, 'tcx, A>
|
impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
|
@ -143,16 +152,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BlockFormatter<'res, 'mir, 'tcx, A>
|
struct BlockFormatter<'mir, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
{
|
{
|
||||||
results: ResultsRefCursor<'res, 'mir, 'tcx, A>,
|
results: ResultsCursor<'mir, 'tcx, A>,
|
||||||
bg: Background,
|
bg: Background,
|
||||||
style: OutputStyle,
|
style: OutputStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'res, 'mir, 'tcx, A> BlockFormatter<'res, 'mir, 'tcx, A>
|
impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
|
||||||
where
|
where
|
||||||
A: Analysis<'tcx>,
|
A: Analysis<'tcx>,
|
||||||
A::Domain: DebugWithContext<A>,
|
A::Domain: DebugWithContext<A>,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
#![feature(try_blocks)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue