From 0c5de8633c8ea5d73606103db5049529c9b5d034 Mon Sep 17 00:00:00 2001 From: Paul Faria Date: Tue, 26 Sep 2017 22:24:19 -0400 Subject: [PATCH 01/10] Store a new Region value every time we create a new region variable --- src/librustc_mir/transform/nll/mod.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index bd02788df1653..0ed0321a948b6 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -15,12 +15,14 @@ use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind}; use rustc::mir::visit::{MutVisitor, Lookup}; use rustc::mir::transform::{MirPass, MirSource}; use rustc::infer::{self, InferCtxt}; +use rustc::util::nodemap::FxHashSet; use syntax_pos::DUMMY_SP; use std::collections::HashMap; #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { lookup_map: HashMap, + regions: Vec, infcx: InferCtxt<'a, 'gcx, 'tcx>, } @@ -29,6 +31,7 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { NLLVisitor { infcx, lookup_map: HashMap::new(), + regions: vec![], } } @@ -36,8 +39,9 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { self.lookup_map } - fn renumber_regions(&self, value: &T) -> T where T: TypeFoldable<'tcx> { + fn renumber_regions(&mut self, value: &T) -> T where T: TypeFoldable<'tcx> { self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| { + self.regions.push(Region::default()); self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP)) }) } @@ -143,4 +147,9 @@ impl MirPass for NLL { let _results = visitor.into_results(); }) } -} \ No newline at end of file +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +struct Region { + points: FxHashSet, +} From f5cef21569115d41171114ec07bb144a3875afc3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 27 Sep 2017 14:29:11 -0300 Subject: [PATCH 02/10] Convert regions to IndexVec --- src/librustc_mir/transform/nll/mod.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index 0ed0321a948b6..f06441f77e265 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -16,13 +16,14 @@ use rustc::mir::visit::{MutVisitor, Lookup}; use rustc::mir::transform::{MirPass, MirSource}; use rustc::infer::{self, InferCtxt}; use rustc::util::nodemap::FxHashSet; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::DUMMY_SP; use std::collections::HashMap; #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { lookup_map: HashMap, - regions: Vec, + regions: IndexVec, infcx: InferCtxt<'a, 'gcx, 'tcx>, } @@ -31,7 +32,7 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { NLLVisitor { infcx, lookup_map: HashMap::new(), - regions: vec![], + regions: IndexVec::new(), } } @@ -153,3 +154,19 @@ impl MirPass for NLL { struct Region { points: FxHashSet, } + +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct RegionIndex(pub u32); + +impl Idx for RegionIndex { + #[inline] + fn new(idx: usize) -> Self { + assert!(idx <= ::std::u32::MAX as usize); + RegionIndex(idx as u32) + } + + #[inline] + fn index(self) -> usize { + self.0 as usize + } +} From 3d230af80b01ebe62d27de8436832d0e7ab9ed94 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 27 Sep 2017 19:47:41 -0300 Subject: [PATCH 03/10] Move newtype_index to rustc_data_structures --- src/librustc/lib.rs | 2 +- src/librustc/mir/mod.rs | 24 -------------------- src/librustc_data_structures/indexed_vec.rs | 25 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 1e90aa47267ff..3322142c9cf28 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -71,7 +71,7 @@ extern crate graphviz; extern crate libc; extern crate owning_ref; extern crate rustc_back; -extern crate rustc_data_structures; +#[macro_use] extern crate rustc_data_structures; extern crate serialize; extern crate rustc_const_math; extern crate rustc_errors as errors; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba221ef6ae10b..b909269e1538e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -43,30 +43,6 @@ pub mod visit; pub mod transform; pub mod traversal; -macro_rules! newtype_index { - ($name:ident, $debug_name:expr) => ( - #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, - RustcEncodable, RustcDecodable)] - pub struct $name(u32); - - impl Idx for $name { - fn new(value: usize) -> Self { - assert!(value < (u32::MAX) as usize); - $name(value as u32) - } - fn index(self) -> usize { - self.0 as usize - } - } - - impl Debug for $name { - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "{}{}", $debug_name, self.0) - } - } - ) -} - /// Types for locals type LocalDecls<'tcx> = IndexVec>; diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 1d0e88ee32855..7674018075cc5 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -38,6 +38,31 @@ impl Idx for u32 { fn index(self) -> usize { self as usize } } +#[macro_export] +macro_rules! newtype_index { + ($name:ident, $debug_name:expr) => ( + #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, + RustcEncodable, RustcDecodable)] + pub struct $name(u32); + + impl Idx for $name { + fn new(value: usize) -> Self { + assert!(value < (u32::MAX) as usize); + $name(value as u32) + } + fn index(self) -> usize { + self.0 as usize + } + } + + impl Debug for $name { + fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + write!(fmt, "{}{}", $debug_name, self.0) + } + } + ) +} + #[derive(Clone, PartialEq, Eq)] pub struct IndexVec { pub raw: Vec, From c8549a158648db323690fbb42356042f6b5d956b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 27 Sep 2017 22:18:38 -0300 Subject: [PATCH 04/10] Generate Idx in nll using newtype_index! --- src/Cargo.lock | 1 + src/librustc_mir/Cargo.toml | 1 + src/librustc_mir/lib.rs | 3 ++- src/librustc_mir/transform/nll/mod.rs | 18 +++--------------- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 26be463f6bb6f..77e33855f2344 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1668,6 +1668,7 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 936fd5a774d3c..b7a576babeb67 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -17,5 +17,6 @@ rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } +serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index d0b9849986b82..553fec20217bf 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -30,7 +30,8 @@ extern crate bitflags; extern crate graphviz as dot; #[macro_use] extern crate rustc; -extern crate rustc_data_structures; +#[macro_use] extern crate rustc_data_structures; +extern crate serialize as rustc_serialize; extern crate rustc_errors; #[macro_use] extern crate syntax; diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index f06441f77e265..c6acc53f5fa9e 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -19,6 +19,8 @@ use rustc::util::nodemap::FxHashSet; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::DUMMY_SP; use std::collections::HashMap; +use std::fmt::{self, Debug, Formatter}; +use std::u32; #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -155,18 +157,4 @@ struct Region { points: FxHashSet, } -#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] -pub struct RegionIndex(pub u32); - -impl Idx for RegionIndex { - #[inline] - fn new(idx: usize) -> Self { - assert!(idx <= ::std::u32::MAX as usize); - RegionIndex(idx as u32) - } - - #[inline] - fn index(self) -> usize { - self.0 as usize - } -} +newtype_index!(RegionIndex, "region_index"); From 9af7426b47a99f5f4b06c79d1e294e424eb74a1f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 28 Sep 2017 12:30:13 -0300 Subject: [PATCH 05/10] Make newtype_index macro use full path to resolve constants --- src/librustc_data_structures/indexed_vec.rs | 6 +++--- src/librustc_mir/transform/nll/mod.rs | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 7674018075cc5..01fb29306878b 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -47,7 +47,7 @@ macro_rules! newtype_index { impl Idx for $name { fn new(value: usize) -> Self { - assert!(value < (u32::MAX) as usize); + assert!(value < (::std::u32::MAX) as usize); $name(value as u32) } fn index(self) -> usize { @@ -55,8 +55,8 @@ macro_rules! newtype_index { } } - impl Debug for $name { - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { + impl ::std::fmt::Debug for $name { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(fmt, "{}{}", $debug_name, self.0) } } diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index c6acc53f5fa9e..7ef8e3bdbd55e 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -19,8 +19,6 @@ use rustc::util::nodemap::FxHashSet; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::DUMMY_SP; use std::collections::HashMap; -use std::fmt::{self, Debug, Formatter}; -use std::u32; #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { From 3502bec0322829d8bbe61b65c62bb796814e4bd3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 3 Oct 2017 14:19:56 -0300 Subject: [PATCH 06/10] Make newtype_index get debug_name using reflection --- src/librustc_data_structures/indexed_vec.rs | 4 ++++ src/librustc_mir/lib.rs | 1 + src/librustc_mir/transform/nll/mod.rs | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 01fb29306878b..82882f944404d 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -40,6 +40,10 @@ impl Idx for u32 { #[macro_export] macro_rules! newtype_index { + ($name:ident) => ( + newtype_index!($name, unsafe { ::std::intrinsics::type_name::<$name>() }); + ); + ($name:ident, $debug_name:expr) => ( #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 553fec20217bf..3339e7a2c30d1 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -18,6 +18,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(core_intrinsics)] #![feature(i128_type)] #![feature(rustc_diagnostic_macros)] #![feature(placement_in_syntax)] diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index 7ef8e3bdbd55e..d4a5354c78f0e 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -155,4 +155,4 @@ struct Region { points: FxHashSet, } -newtype_index!(RegionIndex, "region_index"); +newtype_index!(RegionIndex); From b5a5556dd4807ee97cb51ab395d5dbfc858152dd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 28 Sep 2017 15:56:28 -0300 Subject: [PATCH 07/10] Generate DepNodeIndexNew using newtype_index macro --- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/lib.rs | 1 + src/librustc_data_structures/indexed_vec.rs | 7 +++++++ src/librustc_mir/lib.rs | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 2d2558fd815c4..5057b1c6065bb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -406,7 +406,7 @@ impl DepGraph { for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() { let start = edge_list_data.len() as u32; // This should really just be a memcpy :/ - edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index))); + edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index() as u32))); let end = edge_list_data.len() as u32; debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len()); diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 3322142c9cf28..015dbbb7affa9 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -43,6 +43,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] +#![feature(const_fn)] #![feature(core_intrinsics)] #![feature(i128_type)] #![cfg_attr(windows, feature(libc))] diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 82882f944404d..ce2468fb9f1f5 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -49,6 +49,13 @@ macro_rules! newtype_index { RustcEncodable, RustcDecodable)] pub struct $name(u32); + impl $name { + // HACK use for constants + pub const fn const_new(x: u32) -> Self { + $name(x) + } + } + impl Idx for $name { fn new(value: usize) -> Self { assert!(value < (::std::u32::MAX) as usize); diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 3339e7a2c30d1..7e4206e14c561 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -18,6 +18,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_fn)] #![feature(core_intrinsics)] #![feature(i128_type)] #![feature(rustc_diagnostic_macros)] From 8ee16f4352f3621be75084167185c1f9617859eb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 28 Sep 2017 16:11:06 -0300 Subject: [PATCH 08/10] Generate SerializedDepNodeIndex using newtype_index macro --- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/dep_graph/serialized.rs | 18 +----------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 5057b1c6065bb..cb4126245afae 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -406,7 +406,7 @@ impl DepGraph { for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() { let start = edge_list_data.len() as u32; // This should really just be a memcpy :/ - edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index() as u32))); + edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index()))); let end = edge_list_data.len() as u32; debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len()); diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs index 7275a740e76f8..c96040ab9b6e3 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc/dep_graph/serialized.rs @@ -14,23 +14,7 @@ use dep_graph::DepNode; use ich::Fingerprint; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -/// The index of a DepNode in the SerializedDepGraph::nodes array. -#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug, - RustcEncodable, RustcDecodable)] -pub struct SerializedDepNodeIndex(pub u32); - -impl Idx for SerializedDepNodeIndex { - #[inline] - fn new(idx: usize) -> Self { - assert!(idx <= ::std::u32::MAX as usize); - SerializedDepNodeIndex(idx as u32) - } - - #[inline] - fn index(self) -> usize { - self.0 as usize - } -} +newtype_index!(SerializedDepNodeIndex); /// Data for use when recompiling the **current crate**. #[derive(Debug, RustcEncodable, RustcDecodable)] From 271a492cb2028090c0198e893c18024c19bb6fc7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 28 Sep 2017 17:08:28 -0300 Subject: [PATCH 09/10] Generate ScopeId using newtype_index macro --- src/librustc_data_structures/indexed_vec.rs | 3 ++- src/librustc_mir/build/mod.rs | 14 +------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index ce2468fb9f1f5..4b7f55eba06be 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -51,7 +51,8 @@ macro_rules! newtype_index { impl $name { // HACK use for constants - pub const fn const_new(x: u32) -> Self { + #[allow(unused)] + const fn const_new(x: u32) -> Self { $name(x) } } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 68ef646184c2c..46a5e5abbddfb 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -311,19 +311,7 @@ struct CFG<'tcx> { basic_blocks: IndexVec>, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct ScopeId(u32); - -impl Idx for ScopeId { - fn new(index: usize) -> ScopeId { - assert!(index < (u32::MAX as usize)); - ScopeId(index as u32) - } - - fn index(self) -> usize { - self.0 as usize - } -} +newtype_index!(ScopeId); /////////////////////////////////////////////////////////////////////////// /// The `BlockAnd` "monad" packages up the new basic block along with a From 54d63a0d3380758ae359995330fb64ccdd79069a Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Thu, 28 Sep 2017 00:14:34 -0400 Subject: [PATCH 10/10] Expand mir dump in order to handle NLL pass Extend `dump_mir` and functions it calls in order to allow callers to add custom information. We do this by adding an enum `PassWhere` and an extra argument of type `FnMut(PassWhere, &mut Write) -> io::Result<()>`. This callback is responsible for printing the extra information when MIR is dumped at various stages. For the "nll" pass, use the new mechanism to dump the `Region` information after the header, but before the control flow graph for every function. In the interest of keeping the output somewhat concise, implement a custom Debug impl for `Region` Open Questions: * What should we call what has been called `PassWhere` so far? --- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/transform/dump_mir.rs | 13 +++- src/librustc_mir/transform/generator.rs | 8 +- src/librustc_mir/transform/nll/mod.rs | 24 +++++- src/librustc_mir/util/liveness.rs | 2 +- src/librustc_mir/util/mod.rs | 2 +- src/librustc_mir/util/pretty.rs | 98 ++++++++++++++++--------- 7 files changed, 107 insertions(+), 44 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 46a5e5abbddfb..b8bb2a404620e 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -149,7 +149,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir); + mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) ); mir }) @@ -227,7 +227,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir); + mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) ); mir }) diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 67a3281dba48b..cea66837d9aaf 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -65,7 +65,18 @@ impl PassHook for DumpMir { pass_name, &Disambiguator { is_after }, source, - mir); + mir, + |_, _| Ok(()) ); + for (index, promoted_mir) in mir.promoted.iter_enumerated() { + let promoted_source = MirSource::Promoted(source.item_id(), index); + mir_util::dump_mir(tcx, + Some((suite, pass_num)), + pass_name, + &Disambiguator { is_after }, + promoted_source, + promoted_mir, + |_, _| Ok(()) ); + } } } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 729fe46ef37ec..7d0814b67fba5 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -587,7 +587,7 @@ fn create_generator_drop_shim<'a, 'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(&mut mir); - dump_mir(tcx, None, "generator_drop", &0, source, &mut mir); + dump_mir(tcx, None, "generator_drop", &0, source, &mut mir, |_, _| Ok(()) ); mir } @@ -673,7 +673,7 @@ fn create_generator_resume_function<'a, 'tcx>( // unrelated code from the drop part of the function simplify::remove_dead_blocks(mir); - dump_mir(tcx, None, "generator_resume", &0, source, mir); + dump_mir(tcx, None, "generator_resume", &0, source, mir, |_, _| Ok(()) ); } fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo { @@ -816,14 +816,14 @@ impl MirPass for StateTransform { // This is expanded to a drop ladder in `elaborate_generator_drops`. let drop_clean = insert_clean_drop(mir); - dump_mir(tcx, None, "generator_pre-elab", &0, source, mir); + dump_mir(tcx, None, "generator_pre-elab", &0, source, mir, |_, _| Ok(()) ); // Expand `drop(generator_struct)` to a drop ladder which destroys upvars. // If any upvars are moved out of, drop elaboration will handle upvar destruction. // However we need to also elaborate the code generated by `insert_clean_drop`. elaborate_generator_drops(tcx, def_id, mir); - dump_mir(tcx, None, "generator_post-transform", &0, source, mir); + dump_mir(tcx, None, "generator_post-transform", &0, source, mir, |_, _| Ok(()) ); // Create a copy of our MIR and use it to create the drop shim for the generator let drop_shim = create_generator_drop_shim(tcx, diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index d4a5354c78f0e..4925b1fcfed28 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -19,6 +19,10 @@ use rustc::util::nodemap::FxHashSet; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::DUMMY_SP; use std::collections::HashMap; +use std::fmt; + +use util as mir_util; +use self::mir_util::PassWhere; #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -134,7 +138,7 @@ pub struct NLL; impl MirPass for NLL { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - _: MirSource, + source: MirSource, mir: &mut Mir<'tcx>) { if !tcx.sess.opts.debugging_opts.nll { return; @@ -145,14 +149,30 @@ impl MirPass for NLL { let mut renumbered_mir = mir.clone(); let mut visitor = NLLVisitor::new(infcx); visitor.visit_mir(&mut renumbered_mir); + mir_util::dump_mir(tcx, None, "nll", &0, source, mir, |pass_where, out| { + if let PassWhere::BeforeCFG = pass_where { + for (index, value) in visitor.regions.iter_enumerated() { + writeln!(out, "// R{:03}: {:?}", index.0, value)?; + } + } + Ok(()) + }); let _results = visitor.into_results(); }) } } -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Default, PartialEq, Eq)] struct Region { points: FxHashSet, } +impl fmt::Debug for Region { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(formatter, "{:?}", self.points) + } +} + + + newtype_index!(RegionIndex); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index e6d3a82ff9b53..1424c063d7385 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -232,7 +232,7 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, writeln!(w, "{} {{{}}}", prefix, live.join(", ")) }; print(w, " ", &result.ins)?; - write_basic_block(tcx, block, mir, w)?; + write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?; print(w, " ", &result.outs)?; if block.index() + 1 != mir.basic_blocks().len() { writeln!(w, "")?; diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 4b6da96824dcd..13c14f8920f4e 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -17,6 +17,6 @@ mod graphviz; mod pretty; pub mod liveness; -pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty}; +pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; pub use self::graphviz::{write_mir_graphviz}; pub use self::graphviz::write_node_label as write_graphviz_node_label; diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 9e1f05f6d2f77..8a9047fb4911c 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -25,6 +25,22 @@ const INDENT: &'static str = " "; /// Alignment for lining up comments following MIR statements const ALIGN: usize = 40; +/// An indication of where we are in the control flow graph. Used for printing +/// extra information in `dump_mir` +pub enum PassWhere { + /// We have not started dumping the control flow graph, but we are about to. + BeforeCFG, + + /// We just finished dumping the control flow graph. This is right before EOF + AfterCFG, + + /// We are about to start dumping the given basic block. + BeforeBlock(BasicBlock), + + /// We are just about to dumpt the given statement or terminator. + InCFG(Location), +} + /// If the session is properly configured, dumps a human-readable /// representation of the mir into: /// @@ -39,12 +55,16 @@ const ALIGN: usize = 40; /// - `substring1&substring2,...` -- `&`-separated list of substrings /// that can appear in the pass-name or the `item_path_str` for the given /// node-id. If any one of the substrings match, the data is dumped out. -pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass_num: Option<(MirSuite, MirPassIndex)>, - pass_name: &str, - disambiguator: &Display, - source: MirSource, - mir: &Mir<'tcx>) { +pub fn dump_mir<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: Option<(MirSuite, MirPassIndex)>, + pass_name: &str, + disambiguator: &Display, + source: MirSource, + mir: &Mir<'tcx>, + extra_data: F) +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ if !dump_enabled(tcx, pass_name, source) { return; } @@ -53,12 +73,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.item_path_str(tcx.hir.local_def_id(source.item_id())) }); dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, - disambiguator, source, mir); - for (index, promoted_mir) in mir.promoted.iter_enumerated() { - let promoted_source = MirSource::Promoted(source.item_id(), index); - dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator, - promoted_source, promoted_mir); - } + disambiguator, source, mir, extra_data); } pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -85,13 +100,17 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `item_path_str()` would otherwise trigger `type_of`, and this can // run while we are already attempting to evaluate `type_of`. -fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass_num: Option<(MirSuite, MirPassIndex)>, - pass_name: &str, - node_path: &str, - disambiguator: &Display, - source: MirSource, - mir: &Mir<'tcx>) { +fn dump_matched_mir_node<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: Option<(MirSuite, MirPassIndex)>, + pass_name: &str, + node_path: &str, + disambiguator: &Display, + source: MirSource, + mir: &Mir<'tcx>, + mut extra_data: F) +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ let promotion_id = match source { MirSource::Promoted(_, id) => format!("-{:?}", id), MirSource::GeneratorDrop(_) => format!("-drop"), @@ -125,7 +144,9 @@ fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, writeln!(file, "// generator_layout = {:?}", layout)?; } writeln!(file, "")?; - write_mir_fn(tcx, source, mir, &mut file)?; + extra_data(PassWhere::BeforeCFG, &mut file)?; + write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?; + extra_data(PassWhere::AfterCFG, &mut file)?; Ok(()) }); } @@ -152,24 +173,29 @@ pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let id = tcx.hir.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); - write_mir_fn(tcx, src, mir, w)?; + write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?; for (i, mir) in mir.promoted.iter_enumerated() { writeln!(w, "")?; - write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?; + write_mir_fn(tcx, MirSource::Promoted(id, i), mir, &mut |_, _| Ok(()), w)?; } } Ok(()) } -pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &Mir<'tcx>, - w: &mut Write) - -> io::Result<()> { +pub fn write_mir_fn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, + mir: &Mir<'tcx>, + extra_data: &mut F, + w: &mut Write) + -> io::Result<()> +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - write_basic_block(tcx, block, mir, w)?; + extra_data(PassWhere::BeforeBlock(block), w)?; + write_basic_block(tcx, block, mir, extra_data, w)?; if block.index() + 1 != mir.basic_blocks().len() { writeln!(w, "")?; } @@ -180,11 +206,15 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } /// Write out a human-readable textual representation for the given basic block. -pub fn write_basic_block(tcx: TyCtxt, - block: BasicBlock, - mir: &Mir, - w: &mut Write) - -> io::Result<()> { +pub fn write_basic_block(tcx: TyCtxt, + block: BasicBlock, + mir: &Mir, + extra_data: &mut F, + w: &mut Write) + -> io::Result<()> +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ let data = &mir[block]; // Basic block label at the top. @@ -195,6 +225,7 @@ pub fn write_basic_block(tcx: TyCtxt, // List of statements in the middle. let mut current_location = Location { block: block, statement_index: 0 }; for statement in &data.statements { + extra_data(PassWhere::InCFG(current_location), w)?; let indented_mir = format!("{0}{0}{1:?};", INDENT, statement); writeln!(w, "{0:1$} // {2}", indented_mir, @@ -205,6 +236,7 @@ pub fn write_basic_block(tcx: TyCtxt, } // Terminator at the bottom. + extra_data(PassWhere::InCFG(current_location), w)?; let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind); writeln!(w, "{0:1$} // {2}", indented_terminator,