From c16ef6b21de93de3ebf6cf7bbb3484719427a4e7 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 24 Sep 2019 09:09:15 -0400 Subject: [PATCH 01/47] Remove interior mutability in mir predecessors cache --- src/librustc/mir/cache.rs | 26 +++++++++++-------- src/librustc/mir/mod.rs | 15 +++++++---- src/librustc_mir/transform/add_call_guards.rs | 2 +- src/librustc_mir/util/liveness.rs | 2 +- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 9b41366741876..52848cc435a62 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -1,5 +1,4 @@ use rustc_index::vec::IndexVec; -use rustc_data_structures::sync::{RwLock, MappedReadGuard, ReadGuard}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use crate::ich::StableHashingContext; @@ -7,7 +6,7 @@ use crate::mir::{Body, BasicBlock}; #[derive(Clone, Debug)] pub struct Cache { - predecessors: RwLock>>> + predecessors: Option>> } @@ -32,24 +31,29 @@ impl<'a> HashStable> for Cache { impl Cache { pub fn new() -> Self { Cache { - predecessors: RwLock::new(None) + predecessors: None } } - pub fn invalidate(&self) { + pub fn invalidate(&mut self) { // FIXME: consider being more fine-grained - *self.predecessors.borrow_mut() = None; + self.predecessors = None; } - pub fn predecessors( - &self, + pub fn predecessors_ref(&self) -> &IndexVec> { + assert!(self.predecessors.is_some()); + self.predecessors.as_ref().unwrap() + } + + pub fn predecessors_mut( + &mut self, body: &Body<'_> - ) -> MappedReadGuard<'_, IndexVec>> { - if self.predecessors.borrow().is_none() { - *self.predecessors.borrow_mut() = Some(calculate_predecessors(body)); + ) -> &mut IndexVec> { + if self.predecessors.is_none() { + self.predecessors = Some(calculate_predecessors(body)); } - ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap()) + self.predecessors.as_mut().unwrap() } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 300b0363e2d3b..396953aa41208 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -25,7 +25,6 @@ use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_index::vec::{Idx, IndexVec}; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::sync::MappedReadGuard; use rustc_macros::HashStable; use rustc_serialize::{Encodable, Decodable}; use smallvec::SmallVec; @@ -218,13 +217,19 @@ impl<'tcx> Body<'tcx> { } #[inline] - pub fn predecessors(&self) -> MappedReadGuard<'_, IndexVec>> { - self.cache.predecessors(self) + pub fn predecessors_ref(&self) -> &IndexVec> { + self.cache.predecessors_ref() } #[inline] - pub fn predecessors_for(&self, bb: BasicBlock) -> MappedReadGuard<'_, Vec> { - MappedReadGuard::map(self.predecessors(), |p| &p[bb]) + pub fn predecessors_mut(&mut self) -> &mut IndexVec> { + // TODO(nashenas88) figure out a way to get rid of this clone + self.cache.predecessors_mut(&self.clone()) + } + + #[inline] + pub fn predecessors_for(&self, bb: BasicBlock) -> &Vec { + &self.predecessors_ref()[bb] } #[inline] diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index bf3df1ae2fd84..bc54f48e578e4 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -39,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { impl AddCallGuards { pub fn add_call_guards(&self, body: &mut Body<'_>) { let pred_count: IndexVec<_, _> = - body.predecessors().iter().map(|ps| ps.len()).collect(); + body.predecessors_mut().iter().map(|ps| ps.len()).collect(); // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 63e4af0a56a75..4b67abca0f06d 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -94,7 +94,7 @@ pub fn liveness_of_locals( dirty_queue.insert(bb); } - let predecessors = body.predecessors(); + let predecessors = body.predecessors_ref(); while let Some(bb) = dirty_queue.pop() { // bits = use ∪ (bits - def) From b5240596d2c1efbab04509d689fe50e339952ec4 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 24 Sep 2019 21:27:00 -0400 Subject: [PATCH 02/47] Inline cache impl into Body, rename predecessor fns, change output of predecessors_for to slice --- src/librustc/mir/cache.rs | 75 ------------------- src/librustc/mir/mod.rs | 50 +++++++++---- src/librustc_mir/transform/add_call_guards.rs | 2 +- src/librustc_mir/util/liveness.rs | 2 +- 4 files changed, 38 insertions(+), 91 deletions(-) delete mode 100644 src/librustc/mir/cache.rs diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs deleted file mode 100644 index 52848cc435a62..0000000000000 --- a/src/librustc/mir/cache.rs +++ /dev/null @@ -1,75 +0,0 @@ -use rustc_index::vec::IndexVec; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; -use crate::ich::StableHashingContext; -use crate::mir::{Body, BasicBlock}; - -#[derive(Clone, Debug)] -pub struct Cache { - predecessors: Option>> -} - - -impl rustc_serialize::Encodable for Cache { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - Encodable::encode(&(), s) - } -} - -impl rustc_serialize::Decodable for Cache { - fn decode(d: &mut D) -> Result { - Decodable::decode(d).map(|_v: ()| Self::new()) - } -} - -impl<'a> HashStable> for Cache { - fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - // Do nothing. - } -} - -impl Cache { - pub fn new() -> Self { - Cache { - predecessors: None - } - } - - pub fn invalidate(&mut self) { - // FIXME: consider being more fine-grained - self.predecessors = None; - } - - pub fn predecessors_ref(&self) -> &IndexVec> { - assert!(self.predecessors.is_some()); - self.predecessors.as_ref().unwrap() - } - - pub fn predecessors_mut( - &mut self, - body: &Body<'_> - ) -> &mut IndexVec> { - if self.predecessors.is_none() { - self.predecessors = Some(calculate_predecessors(body)); - } - - self.predecessors.as_mut().unwrap() - } -} - -fn calculate_predecessors(body: &Body<'_>) -> IndexVec> { - let mut result = IndexVec::from_elem(vec![], body.basic_blocks()); - for (bb, data) in body.basic_blocks().iter_enumerated() { - if let Some(ref term) = data.terminator { - for &tgt in term.successors() { - result[tgt].push(bb); - } - } - } - - result -} - -CloneTypeFoldableAndLiftImpls! { - Cache, -} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 396953aa41208..30958700b1b6a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -40,7 +40,6 @@ use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -mod cache; pub mod interpret; pub mod mono; pub mod tcx; @@ -155,7 +154,7 @@ pub struct Body<'tcx> { pub span: Span, /// A cache for various calculations. - cache: cache::Cache, + predecessors_cache: Option>>, } impl<'tcx> Body<'tcx> { @@ -192,7 +191,7 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, - cache: cache::Cache::new(), + predecessors_cache: None, control_flow_destroyed, } } @@ -204,7 +203,8 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { - self.cache.invalidate(); + self.predecessors_cache = None; +// self.cache.invalidate(); &mut self.basic_blocks } @@ -212,24 +212,44 @@ impl<'tcx> Body<'tcx> { pub fn basic_blocks_and_local_decls_mut( &mut self, ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { - self.cache.invalidate(); + self.predecessors_cache = None; +// self.cache.invalidate(); (&mut self.basic_blocks, &mut self.local_decls) } #[inline] - pub fn predecessors_ref(&self) -> &IndexVec> { - self.cache.predecessors_ref() + pub fn unwrap_predecessors(&self) -> &IndexVec> { + assert!(self.predecessors_cache.is_some()); + self.predecessors_cache.as_ref().unwrap() } #[inline] - pub fn predecessors_mut(&mut self) -> &mut IndexVec> { + pub fn predecessors(&mut self) -> &IndexVec> { // TODO(nashenas88) figure out a way to get rid of this clone - self.cache.predecessors_mut(&self.clone()) + if self.predecessors_cache.is_none() { + self.predecessors_cache = Some(self.calculate_predecessors()) + } + + self.predecessors_cache.as_ref().unwrap() + } + + fn calculate_predecessors(&self) -> IndexVec> { + let mut result = IndexVec::from_elem(vec![], self.basic_blocks()); + for (bb, data) in self.basic_blocks().iter_enumerated() { + if let Some(ref term) = data.terminator { + for &tgt in term.successors() { + result[tgt].push(bb); + } + } + } + + result } #[inline] - pub fn predecessors_for(&self, bb: BasicBlock) -> &Vec { - &self.predecessors_ref()[bb] + pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { + // TODO(nashenas88) could this be predecessors sometimes too? + &self.unwrap_predecessors()[bb] } #[inline] @@ -1007,6 +1027,8 @@ impl BasicBlock { } } +CloneTypeFoldableAndLiftImpls!{ BasicBlock, } + /////////////////////////////////////////////////////////////////////////// // BasicBlockData and Terminator @@ -2628,7 +2650,7 @@ impl<'tcx> graph::WithPredecessors for Body<'tcx> { &self, node: Self::Node, ) -> >::Iter { - self.predecessors_for(node).clone().into_iter() + self.predecessors_for(node).to_vec().into_iter() } } @@ -2688,13 +2710,13 @@ impl Location { } // If we're in another block, then we want to check that block is a predecessor of `other`. - let mut queue: Vec = body.predecessors_for(other.block).clone(); + let mut queue: Vec = body.predecessors_for(other.block).to_vec(); let mut visited = FxHashSet::default(); while let Some(block) = queue.pop() { // If we haven't visited this block before, then make sure we visit it's predecessors. if visited.insert(block) { - queue.append(&mut body.predecessors_for(block).clone()); + queue.extend(body.predecessors_for(block).iter().cloned()); } else { continue; } diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index bc54f48e578e4..bf3df1ae2fd84 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -39,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { impl AddCallGuards { pub fn add_call_guards(&self, body: &mut Body<'_>) { let pred_count: IndexVec<_, _> = - body.predecessors_mut().iter().map(|ps| ps.len()).collect(); + body.predecessors().iter().map(|ps| ps.len()).collect(); // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 4b67abca0f06d..d313cba6bdf1a 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -94,7 +94,7 @@ pub fn liveness_of_locals( dirty_queue.insert(bb); } - let predecessors = body.predecessors_ref(); + let predecessors = body.unwrap_predecessors(); while let Some(bb) = dirty_queue.pop() { // bits = use ∪ (bits - def) From ce29f43f52af910783b20174522e2e5a2177b2fc Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 24 Sep 2019 21:29:52 -0400 Subject: [PATCH 03/47] Get rid of old comment --- src/librustc/mir/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 30958700b1b6a..d0903e04d16f8 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -225,7 +225,6 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn predecessors(&mut self) -> &IndexVec> { - // TODO(nashenas88) figure out a way to get rid of this clone if self.predecessors_cache.is_none() { self.predecessors_cache = Some(self.calculate_predecessors()) } From f534d9f8c4bc7aceb80dd06803d709b830a68b21 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 27 Sep 2019 09:19:52 -0400 Subject: [PATCH 04/47] Stop invalidating predecessors cache when accessing unique basic block, invalidate cache when accessing unique terminator --- src/librustc/mir/mod.rs | 42 +++++++++-- src/librustc/mir/traversal.rs | 6 +- src/librustc/mir/visit.rs | 1 + src/librustc_codegen_ssa/mir/mod.rs | 2 +- .../borrow_check/error_reporting.rs | 2 +- src/librustc_mir/build/cfg.rs | 2 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 2 +- src/librustc_mir/lints.rs | 2 +- src/librustc_mir/transform/add_call_guards.rs | 9 +-- src/librustc_mir/transform/generator.rs | 12 ++-- src/librustc_mir/transform/inline.rs | 6 +- src/librustc_mir/transform/promote_consts.rs | 17 ++--- .../transform/remove_noop_landing_pads.rs | 4 +- src/librustc_mir/transform/simplify.rs | 70 ++++++++++--------- .../transform/simplify_branches.rs | 4 +- src/librustc_mir/util/patch.rs | 2 +- 17 files changed, 112 insertions(+), 73 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d0903e04d16f8..0d07caa6cda34 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -203,17 +203,38 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { - self.predecessors_cache = None; -// self.cache.invalidate(); &mut self.basic_blocks } + pub fn basic_block_terminator_opt_mut(&mut self, bb: BasicBlock) -> &mut Option> { + self.predecessors_cache = None; + &mut self.basic_blocks[bb].terminator + } + + pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { + self.predecessors_cache = None; +/* + let data = &mut self.basic_blocks[bb]; + if let Some(cache) = self.predecessors_cache.as_mut() { + for successor in data.terminator().successors() { + let successor_vec = &mut cache[*successor]; + for i in (0..successor_vec.len()).rev() { + if successor_vec[i] == bb { + successor_vec.swap_remove(i); + break; + } + } + } + } +*/ + + self.basic_blocks[bb].terminator_mut() + } + #[inline] pub fn basic_blocks_and_local_decls_mut( &mut self, ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { - self.predecessors_cache = None; -// self.cache.invalidate(); (&mut self.basic_blocks, &mut self.local_decls) } @@ -1358,6 +1379,10 @@ impl<'tcx> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator, is_cleanup: false } } + pub fn terminator_opt(&self) -> &Option> { + &self.terminator + } + /// Accessor for terminator. /// /// Terminator may not be None after construction of the basic block is complete. This accessor @@ -1366,10 +1391,17 @@ impl<'tcx> BasicBlockData<'tcx> { self.terminator.as_ref().expect("invalid terminator state") } - pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> { + // This cannot be public since changing the terminator will break the predecessors cache in Body + // To do so outside of this module, use Body::basic_block_terminator_mut(BasicBlock) + fn terminator_mut(&mut self) -> &mut Terminator<'tcx> { self.terminator.as_mut().expect("invalid terminator state") } + // This can be public since changing the kind will not break the predecessors cache in Body + pub fn terminator_kind_mut(&mut self) -> &mut TerminatorKind<'tcx> { + &mut self.terminator_mut().kind + } + pub fn retain_statements(&mut self, mut f: F) where F: FnMut(&mut Statement<'_>) -> bool, diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index f129dd3abeff7..917f1fae52ab6 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { let data = &self.body[idx]; - if let Some(ref term) = data.terminator { + if let Some(ref term) = data.terminator_opt() { self.worklist.extend(term.successors()); } @@ -117,7 +117,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { let data = &po.body[root]; - if let Some(ref term) = data.terminator { + if let Some(ref term) = data.terminator_opt() { po.visited.insert(root); po.visit_stack.push((root, term.successors())); po.traverse_successor(); @@ -186,7 +186,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { }; if self.visited.insert(bb) { - if let Some(term) = &self.body[bb].terminator { + if let Some(term) = &self.body[bb].terminator_opt() { self.visit_stack.push((bb, term.successors())); } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 145593f1c4d4a..fe146528dae8b 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -793,6 +793,7 @@ macro_rules! make_mir_visitor { fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { let basic_block = & $($mutability)? body[location.block]; if basic_block.statements.len() == location.statement_index { + // TODO(nashenas88) how to ensure we clear the cache only in the mutable case... if let Some(ref $($mutability)? terminator) = basic_block.terminator { self.visit_terminator(terminator, location) } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 6041232489d0d..66ebe4095dcfd 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -265,7 +265,7 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let funclet; let ret_llbb; - match mir[bb].terminator.as_ref().map(|t| &t.kind) { + match mir[bb].terminator_opt().as_ref().map(|t| &t.kind) { // This is a basic block that we're aborting the program for, // notably in an `extern` function. These basic blocks are inserted // so that we assert that `extern` functions do indeed not panic, diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a555e0b74c2b7..140ee2583fa9b 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -497,7 +497,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }, .. - }) = bbd.terminator { + }) = bbd.terminator_opt() { if let Some(source) = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx) { diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 3ed6b4ff34678..734135c324a41 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -64,7 +64,7 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, kind: TerminatorKind<'tcx>) { debug!("terminating block {:?} <- {:?}", block, kind); - debug_assert!(self.block_data(block).terminator.is_none(), + debug_assert!(self.block_data(block).terminator_opt().is_none(), "terminate: block {:?}={:?} already has a terminator set", block, self.block_data(block)); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index eb9b401f27208..1e4b94632fac3 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -731,7 +731,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn finish(self) -> Body<'tcx> { for (index, block) in self.cfg.basic_blocks.iter().enumerate() { - if block.terminator.is_none() { + if block.terminator_opt().is_none() { span_bug!(self.fn_span, "no terminator on block {:?}", index); } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 402e5aeacbf24..f2c0b7149614c 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -98,7 +98,7 @@ fn precompute_borrows_out_of_scope<'tcx>( // Add successor BBs to the work list, if necessary. let bb_data = &body[bb]; assert!(hi == bb_data.statements.len()); - for &succ_bb in bb_data.terminator.as_ref().unwrap().successors() { + for &succ_bb in bb_data.terminator().successors() { visited.entry(succ_bb) .and_modify(|lo| { // `succ_bb` has been seen before. If it wasn't diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs index 158b730b9bd43..70c1d12062997 100644 --- a/src/librustc_mir/lints.rs +++ b/src/librustc_mir/lints.rs @@ -79,7 +79,7 @@ fn check_fn_for_unconditional_recursion( let block = &basic_blocks[bb]; - if let Some(ref terminator) = block.terminator { + if let Some(ref terminator) = block.terminator_opt() { match terminator.kind { TerminatorKind::Call { ref func, .. } => { let func_ty = func.ty(body, tcx); diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index bf3df1ae2fd84..46e6df8231807 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -46,8 +46,9 @@ impl AddCallGuards { let cur_len = body.basic_blocks().len(); - for block in body.basic_blocks_mut() { - match block.terminator { + for bb in body.basic_blocks().indices() { + let is_cleanup = body.basic_blocks()[bb].is_cleanup; + match body.basic_block_terminator_opt_mut(bb) { Some(Terminator { kind: TerminatorKind::Call { destination: Some((_, ref mut destination)), @@ -60,9 +61,9 @@ impl AddCallGuards { // It's a critical edge, break it let call_guard = BasicBlockData { statements: vec![], - is_cleanup: block.is_cleanup, + is_cleanup: is_cleanup, terminator: Some(Terminator { - source_info, + source_info: *source_info, kind: TerminatorKind::Goto { target: *destination } }) }; diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 5d88629435bf1..4c090d1b06515 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -368,7 +368,7 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { VariantIdx::new(RETURNED) // state for returned }; data.statements.push(self.set_discr(state, source_info)); - data.terminator.as_mut().unwrap().kind = TerminatorKind::Return; + *data.terminator_kind_mut() = TerminatorKind::Return; } self.super_basic_block_data(block, data); @@ -852,10 +852,10 @@ fn insert_switch<'tcx>( is_cleanup: false, }); - let blocks = body.basic_blocks_mut().iter_mut(); - - for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) { - *target = BasicBlock::new(target.index() + 1); + for bb in body.basic_blocks_mut().indices() { + for target in body.basic_block_terminator_mut(bb).successors_mut() { + *target = BasicBlock::new(target.index() + 1); + } } } @@ -941,7 +941,7 @@ fn create_generator_drop_shim<'tcx>( insert_switch(&mut body, cases, &transform, TerminatorKind::Return); for block in body.basic_blocks_mut() { - let kind = &mut block.terminator_mut().kind; + let kind = block.terminator_kind_mut(); if let TerminatorKind::GeneratorDrop = *kind { *kind = TerminatorKind::Return; } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index ebfadd0cfd3ed..0ae07f081ae33 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -379,7 +379,7 @@ impl Inliner<'tcx> { callsite: CallSite<'tcx>, caller_body: &mut Body<'tcx>, mut callee_body: Body<'tcx>) -> bool { - let terminator = caller_body[callsite.bb].terminator.take().unwrap(); + let terminator = caller_body.basic_block_terminator_opt_mut(callsite.bb).take().unwrap(); match terminator.kind { // FIXME: Handle inlining of diverging calls TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { @@ -496,12 +496,12 @@ impl Inliner<'tcx> { kind: TerminatorKind::Goto { target: BasicBlock::new(bb_len) } }; - caller_body[callsite.bb].terminator = Some(terminator); + *caller_body.basic_block_terminator_opt_mut(callsite.bb) = Some(terminator); true } kind => { - caller_body[callsite.bb].terminator = Some(Terminator { + *caller_body.basic_block_terminator_opt_mut(callsite.bb) = Some(Terminator { source_info: terminator.source_info, kind, }); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 591f3ca44009d..a569dc652283a 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -866,7 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let terminator = if self.keep_original { self.source[loc.block].terminator().clone() } else { - let terminator = self.source[loc.block].terminator_mut(); + let terminator = self.source.basic_block_terminator_mut(loc.block); let target = match terminator.kind { TerminatorKind::Call { destination: Some((_, target)), .. } => target, ref kind => { @@ -891,7 +891,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let last = self.promoted.basic_blocks().last().unwrap(); let new_target = self.new_block(); - *self.promoted[last].terminator_mut() = Terminator { + *self.promoted.basic_block_terminator_mut(last) = Terminator { kind: TerminatorKind::Call { func, args, @@ -976,11 +976,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } }, Candidate::Argument { bb, index } => { - let terminator = blocks[bb].terminator_mut(); - match terminator.kind { + let data = &mut blocks[bb]; + let terminator_span = data.terminator().source_info.span; + match data.terminator_kind_mut() { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); - let span = terminator.source_info.span; + let span = terminator_span; let operand = Operand::Copy(promoted_place(ty, span)); mem::replace(&mut args[index], operand) } @@ -1103,8 +1104,8 @@ pub fn promote_candidates<'tcx>( // Eliminate assignments to, and drops of promoted temps. let promoted = |index: Local| temps[index] == TempState::PromotedOut; - for block in body.basic_blocks_mut() { - block.statements.retain(|statement| { + for bb in body.basic_blocks().indices() { + body.basic_blocks_mut()[bb].statements.retain(|statement| { match &statement.kind { StatementKind::Assign(box(place, _)) => { if let Some(index) = place.as_local() { @@ -1120,7 +1121,7 @@ pub fn promote_candidates<'tcx>( _ => true } }); - let terminator = block.terminator_mut(); + let terminator = body.basic_block_terminator_mut(bb); match &terminator.kind { TerminatorKind::Drop { location: place, target, .. } => { if let Some(index) = place.as_local() { diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 130393e2c4c86..9e0f80dcf9ae4 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -103,7 +103,7 @@ impl RemoveNoopLandingPads { let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); for bb in postorder { debug!(" processing {:?}", bb); - for target in body[bb].terminator_mut().successors_mut() { + for target in body.basic_block_terminator_mut(bb).successors_mut() { if *target != resume_block && nop_landing_pads.contains(*target) { debug!(" folding noop jump to {:?} to resume block", target); *target = resume_block; @@ -111,7 +111,7 @@ impl RemoveNoopLandingPads { } } - match body[bb].terminator_mut().unwind_mut() { + match body.basic_block_terminator_mut(bb).unwind_mut() { Some(unwind) => { if *unwind == Some(resume_block) { debug!(" removing noop landing pad"); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index c9185d14148c1..5f5014d6d4690 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -63,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { } pub struct CfgSimplifier<'a, 'tcx> { - basic_blocks: &'a mut IndexVec>, + body: &'a mut Body<'tcx>, pred_count: IndexVec } @@ -76,21 +76,23 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pred_count[START_BLOCK] = 1; for (_, data) in traversal::preorder(body) { - if let Some(ref term) = data.terminator { + if let Some(ref term) = data.terminator_opt() { for &tgt in term.successors() { pred_count[tgt] += 1; } } } - let basic_blocks = body.basic_blocks_mut(); - CfgSimplifier { - basic_blocks, + body, pred_count, } } + fn basic_blocks(&mut self) -> &mut IndexVec> { + self.body.basic_blocks_mut() + } + pub fn simplify(mut self) { self.strip_nops(); @@ -101,14 +103,14 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { self.collapse_goto_chain(&mut start, &mut changed); - for bb in self.basic_blocks.indices() { + for bb in self.body.basic_blocks().indices() { if self.pred_count[bb] == 0 { continue } debug!("simplifying {:?}", bb); - let mut terminator = self.basic_blocks[bb].terminator.take() + let mut terminator = self.body.basic_block_terminator_opt_mut(bb).take() .expect("invalid terminator state"); for successor in terminator.successors_mut() { @@ -123,9 +125,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator); changed |= inner_changed; } - - self.basic_blocks[bb].statements.extend(new_stmts); - self.basic_blocks[bb].terminator = Some(terminator); + self.basic_blocks()[bb].statements.extend(new_stmts); + *self.body.basic_block_terminator_opt_mut(bb) = Some(terminator); changed |= inner_changed; } @@ -135,17 +136,17 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { if start != START_BLOCK { debug_assert!(self.pred_count[START_BLOCK] == 0); - self.basic_blocks.swap(START_BLOCK, start); + self.basic_blocks().swap(START_BLOCK, start); self.pred_count.swap(START_BLOCK, start); // pred_count == 1 if the start block has no predecessor _blocks_. if self.pred_count[START_BLOCK] > 1 { - for (bb, data) in self.basic_blocks.iter_enumerated_mut() { + for bb in self.basic_blocks().indices() { if self.pred_count[bb] == 0 { continue; } - for target in data.terminator_mut().successors_mut() { + for target in self.body.basic_block_terminator_mut(bb).successors_mut() { if *target == start { *target = START_BLOCK; } @@ -157,7 +158,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { // Collapse a goto chain starting from `start` fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) { - let mut terminator = match self.basic_blocks[*start] { + let mut terminator = match self.basic_blocks()[*start] { BasicBlockData { ref statements, terminator: ref mut terminator @ Some(Terminator { @@ -176,7 +177,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } _ => unreachable!() }; - self.basic_blocks[*start].terminator = terminator; + self.basic_blocks()[*start].terminator = terminator; debug!("collapsing goto chain from {:?} to {:?}", *start, target); @@ -208,7 +209,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { }; debug!("merging block {:?} into {:?}", target, terminator); - *terminator = match self.basic_blocks[target].terminator.take() { + *terminator = match self.body.basic_block_terminator_opt_mut(target).take() { Some(terminator) => terminator, None => { // unreachable loop - this should not be possible, as we @@ -216,7 +217,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { return false } }; - new_stmts.extend(self.basic_blocks[target].statements.drain(..)); + new_stmts.extend(self.basic_blocks()[target].statements.drain(..)); self.pred_count[target] = 0; true @@ -249,7 +250,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } fn strip_nops(&mut self) { - for blk in self.basic_blocks.iter_mut() { + for blk in self.basic_blocks().iter_mut() { blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind { false } else { @@ -265,24 +266,27 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { seen.insert(bb.index()); } - let basic_blocks = body.basic_blocks_mut(); - - let num_blocks = basic_blocks.len(); - let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); - let mut used_blocks = 0; - for alive_index in seen.iter() { - replacements[alive_index] = BasicBlock::new(used_blocks); - if alive_index != used_blocks { - // Swap the next alive block data with the current available slot. Since alive_index is - // non-decreasing this is a valid operation. - basic_blocks.raw.swap(alive_index, used_blocks); + let mut replacements: Vec; + { + let basic_blocks = body.basic_blocks_mut(); + + let num_blocks = basic_blocks.len(); + replacements = (0..num_blocks).map(BasicBlock::new).collect(); + let mut used_blocks = 0; + for alive_index in seen.iter() { + replacements[alive_index] = BasicBlock::new(used_blocks); + if alive_index != used_blocks { + // Swap the next alive block data with the current available slot. Since alive_index is + // non-decreasing this is a valid operation. + basic_blocks.raw.swap(alive_index, used_blocks); + } + used_blocks += 1; } - used_blocks += 1; + basic_blocks.raw.truncate(used_blocks); } - basic_blocks.raw.truncate(used_blocks); - for block in basic_blocks { - for target in block.terminator_mut().successors_mut() { + for bb in body.basic_blocks().indices() { + for target in body.basic_block_terminator_mut(bb).successors_mut() { *target = replacements[target.index()]; } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 0a509666d34ae..1e45ad5d428cf 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -21,8 +21,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(src.def_id()); - for block in body.basic_blocks_mut() { - let terminator = block.terminator_mut(); + for bb in body.basic_blocks().indices() { + let terminator = body.basic_block_terminator_mut(bb); terminator.kind = match terminator.kind { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index a5f7e5401573b..554ae2d3c6b68 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -141,7 +141,7 @@ impl<'tcx> MirPatch<'tcx> { for (src, patch) in self.patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); - body[src].terminator_mut().kind = patch; + body.basic_block_terminator_mut(src).kind = patch; } } From 2b3145606827d1bd2b78004c6012fc060dee3d08 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 28 Sep 2019 10:47:41 -0400 Subject: [PATCH 05/47] Add pass to ensure predecessors cache is generated after optimization --- src/librustc/mir/mod.rs | 18 +++--------------- .../transform/ensure_predecessors_cache.rs | 15 +++++++++++++++ src/librustc_mir/transform/mod.rs | 2 ++ 3 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 src/librustc_mir/transform/ensure_predecessors_cache.rs diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0d07caa6cda34..78764ec8cd6e2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -207,27 +207,14 @@ impl<'tcx> Body<'tcx> { } pub fn basic_block_terminator_opt_mut(&mut self, bb: BasicBlock) -> &mut Option> { + // FIXME we should look into improving the cache invalidation self.predecessors_cache = None; &mut self.basic_blocks[bb].terminator } pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { + // FIXME we should look into improving the cache invalidation self.predecessors_cache = None; -/* - let data = &mut self.basic_blocks[bb]; - if let Some(cache) = self.predecessors_cache.as_mut() { - for successor in data.terminator().successors() { - let successor_vec = &mut cache[*successor]; - for i in (0..successor_vec.len()).rev() { - if successor_vec[i] == bb { - successor_vec.swap_remove(i); - break; - } - } - } - } -*/ - self.basic_blocks[bb].terminator_mut() } @@ -245,6 +232,7 @@ impl<'tcx> Body<'tcx> { } #[inline] + /// This will recompute the predecessors cache if it is not available pub fn predecessors(&mut self) -> &IndexVec> { if self.predecessors_cache.is_none() { self.predecessors_cache = Some(self.calculate_predecessors()) diff --git a/src/librustc_mir/transform/ensure_predecessors_cache.rs b/src/librustc_mir/transform/ensure_predecessors_cache.rs new file mode 100644 index 0000000000000..ed5b26d7b0593 --- /dev/null +++ b/src/librustc_mir/transform/ensure_predecessors_cache.rs @@ -0,0 +1,15 @@ +use rustc::mir::Body; +use rustc::ty::TyCtxt; +use crate::transform::{MirPass, MirSource}; + +pub struct EnsurePredecessorsCache; + +impl<'tcx> MirPass<'tcx> for EnsurePredecessorsCache { + fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + // predecessors is lazily calculated. We want to ensure that the cache is properly filled + // before the next stages of compilation, since thise following stages will only be allowed + // to read the cache and not generate it. If the cache is already up to date, this line is + // a nop. + let _predecessors = body.predecessors(); + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 2b2b52971ef0f..096fe82ae9952 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -20,6 +20,7 @@ pub mod check_unsafety; pub mod simplify_branches; pub mod simplify_try; pub mod simplify; +pub mod ensure_predecessors_cache; pub mod erase_regions; pub mod no_landing_pads; pub mod rustc_peek; @@ -313,6 +314,7 @@ fn run_optimization_passes<'tcx>( &simplify::SimplifyLocals, &add_call_guards::CriticalCallEdges, + &ensure_predecessors_cache::EnsurePredecessorsCache, &dump_mir::Marker("PreCodegen"), ]); } From e1afa519e820a93e4d24a9265f46fa4275b93c2a Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 28 Sep 2019 13:49:48 -0400 Subject: [PATCH 06/47] Fix Mir visitor macro to ensure it calls the proper method to invalidate the predecessors cache --- src/librustc/mir/visit.rs | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index fe146528dae8b..df231ef73e6db 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -789,19 +789,31 @@ macro_rules! make_mir_visitor { } // Convenience methods - - fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { - let basic_block = & $($mutability)? body[location.block]; - if basic_block.statements.len() == location.statement_index { - // TODO(nashenas88) how to ensure we clear the cache only in the mutable case... - if let Some(ref $($mutability)? terminator) = basic_block.terminator { - self.visit_terminator(terminator, location) - } - } else { - let statement = & $($mutability)? - basic_block.statements[location.statement_index]; - self.visit_statement(statement, location) + make_mir_visitor!{@make_visit_location, $($mutability)?} + } + }; + (@make_visit_location, mut) => { + fn visit_location(&mut self, body: &mut Body<'tcx>, location: Location) { + if body[location.block].statements.len() == location.statement_index { + if let Some(ref mut terminator) = body.basic_block_terminator_opt_mut(location.block) { + self.visit_terminator(terminator, location) + } + } else { + let statement = &mut body[location.block].statements[location.statement_index]; + self.visit_statement(statement, location) + } + } + }; + (@make_visit_location, ) => { + fn visit_location(&mut self, body: &Body<'tcx>, location: Location) { + let basic_block = &body[location.block]; + if basic_block.statements.len() == location.statement_index { + if let Some(ref terminator) = basic_block.terminator_opt() { + self.visit_terminator(terminator, location) } + } else { + let statement = &basic_block.statements[location.statement_index]; + self.visit_statement(statement, location) } } } From 570e4182e8377f6194b5c7d3654d5753472f4ef4 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 28 Sep 2019 14:23:42 -0400 Subject: [PATCH 07/47] Address linting errors caught by CI --- src/librustc/mir/mod.rs | 6 ++++-- src/librustc_mir/transform/simplify.rs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 78764ec8cd6e2..41276b90969ad 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -206,7 +206,9 @@ impl<'tcx> Body<'tcx> { &mut self.basic_blocks } - pub fn basic_block_terminator_opt_mut(&mut self, bb: BasicBlock) -> &mut Option> { + pub fn basic_block_terminator_opt_mut( + &mut self, bb: BasicBlock + ) -> &mut Option> { // FIXME we should look into improving the cache invalidation self.predecessors_cache = None; &mut self.basic_blocks[bb].terminator @@ -256,7 +258,7 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { - // TODO(nashenas88) could this be predecessors sometimes too? + // FIXME(nashenas88) could this be predecessors sometimes too? &self.unwrap_predecessors()[bb] } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 5f5014d6d4690..2f98a15e819e1 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -276,8 +276,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { for alive_index in seen.iter() { replacements[alive_index] = BasicBlock::new(used_blocks); if alive_index != used_blocks { - // Swap the next alive block data with the current available slot. Since alive_index is - // non-decreasing this is a valid operation. + // Swap the next alive block data with the current available slot. Since + // alive_index is non-decreasing this is a valid operation. basic_blocks.raw.swap(alive_index, used_blocks); } used_blocks += 1; From 8e8c97e5fde0321da6e706d2f193cb3f395de1b6 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 2 Oct 2019 23:49:04 -0400 Subject: [PATCH 08/47] Ensure predecessors are recomputed at critical points, fixes panics --- src/librustc/mir/mod.rs | 35 ++++++++++--------- src/librustc_mir/shim.rs | 5 ++- .../transform/ensure_predecessors_cache.rs | 17 +++++++-- src/librustc_mir/transform/mod.rs | 5 ++- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 41276b90969ad..d9530ac0791da 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -210,12 +210,14 @@ impl<'tcx> Body<'tcx> { &mut self, bb: BasicBlock ) -> &mut Option> { // FIXME we should look into improving the cache invalidation + debug!("Invalidating predecessors cache through opt terminator for block at : {:?}", self.span.data()); self.predecessors_cache = None; &mut self.basic_blocks[bb].terminator } pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { // FIXME we should look into improving the cache invalidation + debug!("Invalidating predecessors cache through terminator for block at : {:?}", self.span.data()); self.predecessors_cache = None; self.basic_blocks[bb].terminator_mut() } @@ -229,36 +231,35 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn unwrap_predecessors(&self) -> &IndexVec> { - assert!(self.predecessors_cache.is_some()); + assert!(self.predecessors_cache.is_some(), "Expected predecessors_cache to be `Some(...)` for block at: {:?}", self.span.data()); self.predecessors_cache.as_ref().unwrap() } #[inline] - /// This will recompute the predecessors cache if it is not available - pub fn predecessors(&mut self) -> &IndexVec> { + pub fn ensure_predecessors(&mut self) { if self.predecessors_cache.is_none() { - self.predecessors_cache = Some(self.calculate_predecessors()) - } - - self.predecessors_cache.as_ref().unwrap() - } - - fn calculate_predecessors(&self) -> IndexVec> { - let mut result = IndexVec::from_elem(vec![], self.basic_blocks()); - for (bb, data) in self.basic_blocks().iter_enumerated() { - if let Some(ref term) = data.terminator { - for &tgt in term.successors() { - result[tgt].push(bb); + let mut result = IndexVec::from_elem(vec![], self.basic_blocks()); + for (bb, data) in self.basic_blocks().iter_enumerated() { + if let Some(ref term) = data.terminator { + for &tgt in term.successors() { + result[tgt].push(bb); + } } } + + self.predecessors_cache = Some(result) } + } - result + #[inline] + /// This will recompute the predecessors cache if it is not available + pub fn predecessors(&mut self) -> &IndexVec> { + self.ensure_predecessors(); + self.predecessors_cache.as_ref().unwrap() } #[inline] pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { - // FIXME(nashenas88) could this be predecessors sometimes too? &self.unwrap_predecessors()[bb] } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 708686fdcf9f1..6e36764fb807b 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -123,6 +123,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx &add_call_guards::CriticalCallEdges, ]); + result.ensure_predecessors(); + debug!("make_shim({:?}) = {:?}", instance, result); tcx.arena.alloc(result) @@ -909,12 +911,13 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { is_cleanup: false }; - let body = new_body( + let mut body = new_body( IndexVec::from_elem_n(start_block, 1), local_decls, sig.inputs().len(), span, ); + body.ensure_predecessors(); crate::util::dump_mir( tcx, diff --git a/src/librustc_mir/transform/ensure_predecessors_cache.rs b/src/librustc_mir/transform/ensure_predecessors_cache.rs index ed5b26d7b0593..db1ef863351c0 100644 --- a/src/librustc_mir/transform/ensure_predecessors_cache.rs +++ b/src/librustc_mir/transform/ensure_predecessors_cache.rs @@ -2,14 +2,25 @@ use rustc::mir::Body; use rustc::ty::TyCtxt; use crate::transform::{MirPass, MirSource}; -pub struct EnsurePredecessorsCache; +pub struct EnsurePredecessorsCache { + label: String, +} + +impl EnsurePredecessorsCache { + pub fn new>(label: S) -> Self { + Self { + label: label.into(), + } + } +} impl<'tcx> MirPass<'tcx> for EnsurePredecessorsCache { fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + debug!("{}: Ensure predecessors cache: {:?}", self.label, body.span.data()); // predecessors is lazily calculated. We want to ensure that the cache is properly filled - // before the next stages of compilation, since thise following stages will only be allowed + // before the next stages of compilation, since these following stages will only be allowed // to read the cache and not generate it. If the cache is already up to date, this line is // a nop. - let _predecessors = body.predecessors(); + body.ensure_predecessors(); } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 096fe82ae9952..76e89ce5cf204 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -249,6 +249,7 @@ fn mir_validated( // What we need to run borrowck etc. &promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), + &ensure_predecessors_cache::EnsurePredecessorsCache::new("qualify-consts"), ]); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) @@ -296,6 +297,8 @@ fn run_optimization_passes<'tcx>( &uniform_array_move_out::RestoreSubsliceArrayMoveOut::new(tcx), &inline::Inline, + // State transform requires that predecessors have been predefined + &ensure_predecessors_cache::EnsurePredecessorsCache::new("pre-state-transform"), // Lowering generator control-flow and variables // has to happen before we do anything else to them. &generator::StateTransform, @@ -314,7 +317,7 @@ fn run_optimization_passes<'tcx>( &simplify::SimplifyLocals, &add_call_guards::CriticalCallEdges, - &ensure_predecessors_cache::EnsurePredecessorsCache, + &ensure_predecessors_cache::EnsurePredecessorsCache::new("before-opt-dump"), &dump_mir::Marker("PreCodegen"), ]); } From ad734680af76d92f8e490141d72bf2a629e2d5f8 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 4 Oct 2019 00:55:28 -0400 Subject: [PATCH 09/47] Move predecessors cache invalidation back to basic_blocks_mut, add a couple more ensure_predecessors to prevent panics --- src/librustc/mir/mod.rs | 31 +------- src/librustc/mir/traversal.rs | 6 +- src/librustc/mir/visit.rs | 35 +++------ src/librustc_codegen_ssa/mir/mod.rs | 2 +- .../borrow_check/error_reporting.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 5 ++ src/librustc_mir/build/cfg.rs | 2 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/lints.rs | 2 +- src/librustc_mir/shim.rs | 9 +++ src/librustc_mir/transform/add_call_guards.rs | 9 +-- src/librustc_mir/transform/generator.rs | 16 ++-- src/librustc_mir/transform/inline.rs | 6 +- src/librustc_mir/transform/promote_consts.rs | 17 ++--- .../transform/remove_noop_landing_pads.rs | 4 +- src/librustc_mir/transform/simplify.rs | 73 +++++++++---------- .../transform/simplify_branches.rs | 4 +- src/librustc_mir/util/patch.rs | 2 +- 18 files changed, 102 insertions(+), 125 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d9530ac0791da..a91017e880a3b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -203,23 +203,9 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { - &mut self.basic_blocks - } - - pub fn basic_block_terminator_opt_mut( - &mut self, bb: BasicBlock - ) -> &mut Option> { - // FIXME we should look into improving the cache invalidation - debug!("Invalidating predecessors cache through opt terminator for block at : {:?}", self.span.data()); - self.predecessors_cache = None; - &mut self.basic_blocks[bb].terminator - } - - pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { - // FIXME we should look into improving the cache invalidation - debug!("Invalidating predecessors cache through terminator for block at : {:?}", self.span.data()); + debug!("Clearing predecessors cache at: {:?}", self.span.data()); self.predecessors_cache = None; - self.basic_blocks[bb].terminator_mut() + &mut self.basic_blocks } #[inline] @@ -1370,10 +1356,6 @@ impl<'tcx> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator, is_cleanup: false } } - pub fn terminator_opt(&self) -> &Option> { - &self.terminator - } - /// Accessor for terminator. /// /// Terminator may not be None after construction of the basic block is complete. This accessor @@ -1382,17 +1364,10 @@ impl<'tcx> BasicBlockData<'tcx> { self.terminator.as_ref().expect("invalid terminator state") } - // This cannot be public since changing the terminator will break the predecessors cache in Body - // To do so outside of this module, use Body::basic_block_terminator_mut(BasicBlock) - fn terminator_mut(&mut self) -> &mut Terminator<'tcx> { + pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> { self.terminator.as_mut().expect("invalid terminator state") } - // This can be public since changing the kind will not break the predecessors cache in Body - pub fn terminator_kind_mut(&mut self) -> &mut TerminatorKind<'tcx> { - &mut self.terminator_mut().kind - } - pub fn retain_statements(&mut self, mut f: F) where F: FnMut(&mut Statement<'_>) -> bool, diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 917f1fae52ab6..f129dd3abeff7 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { let data = &self.body[idx]; - if let Some(ref term) = data.terminator_opt() { + if let Some(ref term) = data.terminator { self.worklist.extend(term.successors()); } @@ -117,7 +117,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { let data = &po.body[root]; - if let Some(ref term) = data.terminator_opt() { + if let Some(ref term) = data.terminator { po.visited.insert(root); po.visit_stack.push((root, term.successors())); po.traverse_successor(); @@ -186,7 +186,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { }; if self.visited.insert(bb) { - if let Some(term) = &self.body[bb].terminator_opt() { + if let Some(term) = &self.body[bb].terminator { self.visit_stack.push((bb, term.successors())); } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index df231ef73e6db..145593f1c4d4a 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -789,31 +789,18 @@ macro_rules! make_mir_visitor { } // Convenience methods - make_mir_visitor!{@make_visit_location, $($mutability)?} - } - }; - (@make_visit_location, mut) => { - fn visit_location(&mut self, body: &mut Body<'tcx>, location: Location) { - if body[location.block].statements.len() == location.statement_index { - if let Some(ref mut terminator) = body.basic_block_terminator_opt_mut(location.block) { - self.visit_terminator(terminator, location) - } - } else { - let statement = &mut body[location.block].statements[location.statement_index]; - self.visit_statement(statement, location) - } - } - }; - (@make_visit_location, ) => { - fn visit_location(&mut self, body: &Body<'tcx>, location: Location) { - let basic_block = &body[location.block]; - if basic_block.statements.len() == location.statement_index { - if let Some(ref terminator) = basic_block.terminator_opt() { - self.visit_terminator(terminator, location) + + fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { + let basic_block = & $($mutability)? body[location.block]; + if basic_block.statements.len() == location.statement_index { + if let Some(ref $($mutability)? terminator) = basic_block.terminator { + self.visit_terminator(terminator, location) + } + } else { + let statement = & $($mutability)? + basic_block.statements[location.statement_index]; + self.visit_statement(statement, location) } - } else { - let statement = &basic_block.statements[location.statement_index]; - self.visit_statement(statement, location) } } } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 66ebe4095dcfd..6041232489d0d 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -265,7 +265,7 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let funclet; let ret_llbb; - match mir[bb].terminator_opt().as_ref().map(|t| &t.kind) { + match mir[bb].terminator.as_ref().map(|t| &t.kind) { // This is a basic block that we're aborting the program for, // notably in an `extern` function. These basic blocks are inserted // so that we assert that `extern` functions do indeed not panic, diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 140ee2583fa9b..a555e0b74c2b7 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -497,7 +497,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }, .. - }) = bbd.terminator_opt() { + }) = bbd.terminator { if let Some(source) = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx) { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3a783f674e9ae..63a8de5eebacd 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -166,6 +166,11 @@ fn do_mir_borrowck<'a, 'tcx>( let mut promoted: IndexVec> = input_promoted.clone(); let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); + + // Region replacement above very likely invalidated the predecessors cache. It's used later on + // when retrieving the dominators from the body, so we need to ensure it exists before locking + // the body for changes. + body.ensure_predecessors(); let body = &body; // no further changes let location_table = &LocationTable::new(body); diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 734135c324a41..3ed6b4ff34678 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -64,7 +64,7 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, kind: TerminatorKind<'tcx>) { debug!("terminating block {:?} <- {:?}", block, kind); - debug_assert!(self.block_data(block).terminator_opt().is_none(), + debug_assert!(self.block_data(block).terminator.is_none(), "terminate: block {:?}={:?} already has a terminator set", block, self.block_data(block)); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 1e4b94632fac3..eb9b401f27208 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -731,7 +731,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn finish(self) -> Body<'tcx> { for (index, block) in self.cfg.basic_blocks.iter().enumerate() { - if block.terminator_opt().is_none() { + if block.terminator.is_none() { span_bug!(self.fn_span, "no terminator on block {:?}", index); } } diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs index 70c1d12062997..158b730b9bd43 100644 --- a/src/librustc_mir/lints.rs +++ b/src/librustc_mir/lints.rs @@ -79,7 +79,7 @@ fn check_fn_for_unconditional_recursion( let block = &basic_blocks[bb]; - if let Some(ref terminator) = block.terminator_opt() { + if let Some(ref terminator) = block.terminator { match terminator.kind { TerminatorKind::Call { ref func, .. } => { let func_ty = func.ty(body, tcx); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 6e36764fb807b..938d3f8ce9761 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -123,6 +123,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx &add_call_guards::CriticalCallEdges, ]); + // The `ensure_predecessors_cache::EnsurePredecessorsCache` MirPass wasn't used in the + // `run_passes` above because the above pass is not always guaranteed to run. There can be + // instances where, e.g. a `MirPhase::Validated` pass has already been run on a `Body` by the + // time it arrived at this line, and so the above `run_passes` call will NOT run any of the + // passes (They do not run if a same or later pass has already been executed on a `Body`). + // Adding the ensure pass during the `run_passes` for `MirPhase::Validated` would not + // help because the predecessors cache would be invalidated between that pass and this call. + // Having the single ensure outside of the `run_passes` list here guarantees that anyone + // using this `Body` could call `Body::unwrap_predecessors()` without worrying about a panic. result.ensure_predecessors(); debug!("make_shim({:?}) = {:?}", instance, result); diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 46e6df8231807..bf3df1ae2fd84 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -46,9 +46,8 @@ impl AddCallGuards { let cur_len = body.basic_blocks().len(); - for bb in body.basic_blocks().indices() { - let is_cleanup = body.basic_blocks()[bb].is_cleanup; - match body.basic_block_terminator_opt_mut(bb) { + for block in body.basic_blocks_mut() { + match block.terminator { Some(Terminator { kind: TerminatorKind::Call { destination: Some((_, ref mut destination)), @@ -61,9 +60,9 @@ impl AddCallGuards { // It's a critical edge, break it let call_guard = BasicBlockData { statements: vec![], - is_cleanup: is_cleanup, + is_cleanup: block.is_cleanup, terminator: Some(Terminator { - source_info: *source_info, + source_info, kind: TerminatorKind::Goto { target: *destination } }) }; diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 4c090d1b06515..8c11d66fb48c7 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -368,7 +368,7 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { VariantIdx::new(RETURNED) // state for returned }; data.statements.push(self.set_discr(state, source_info)); - *data.terminator_kind_mut() = TerminatorKind::Return; + data.terminator_mut().kind = TerminatorKind::Return; } self.super_basic_block_data(block, data); @@ -852,10 +852,10 @@ fn insert_switch<'tcx>( is_cleanup: false, }); - for bb in body.basic_blocks_mut().indices() { - for target in body.basic_block_terminator_mut(bb).successors_mut() { - *target = BasicBlock::new(target.index() + 1); - } + let blocks = body.basic_blocks_mut().iter_mut(); + + for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) { + *target = BasicBlock::new(target.index() + 1); } } @@ -941,7 +941,7 @@ fn create_generator_drop_shim<'tcx>( insert_switch(&mut body, cases, &transform, TerminatorKind::Return); for block in body.basic_blocks_mut() { - let kind = block.terminator_kind_mut(); + let kind = &mut block.terminator_mut().kind; if let TerminatorKind::GeneratorDrop = *kind { *kind = TerminatorKind::Return; } @@ -1203,6 +1203,10 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // RETURN_PLACE then is a fresh unused local with type ret_ty. let new_ret_local = replace_result_variable(ret_ty, body, tcx); + // Replacing result variables very likely clears the predecessors cache (needed inside of + // compute layout), so we need to ensure the cache exists. + body.ensure_predecessors(); + // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices // `storage_liveness` tells us which locals have live storage at suspension points diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 0ae07f081ae33..1d45c1fe18696 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -379,7 +379,7 @@ impl Inliner<'tcx> { callsite: CallSite<'tcx>, caller_body: &mut Body<'tcx>, mut callee_body: Body<'tcx>) -> bool { - let terminator = caller_body.basic_block_terminator_opt_mut(callsite.bb).take().unwrap(); + let terminator = caller_body[callsite.bb].terminator.take().unwrap(); match terminator.kind { // FIXME: Handle inlining of diverging calls TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { @@ -496,12 +496,12 @@ impl Inliner<'tcx> { kind: TerminatorKind::Goto { target: BasicBlock::new(bb_len) } }; - *caller_body.basic_block_terminator_opt_mut(callsite.bb) = Some(terminator); + caller_body[callsite.bb].terminator= Some(terminator); true } kind => { - *caller_body.basic_block_terminator_opt_mut(callsite.bb) = Some(Terminator { + caller_body[callsite.bb].terminator = Some(Terminator { source_info: terminator.source_info, kind, }); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index a569dc652283a..591f3ca44009d 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -866,7 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let terminator = if self.keep_original { self.source[loc.block].terminator().clone() } else { - let terminator = self.source.basic_block_terminator_mut(loc.block); + let terminator = self.source[loc.block].terminator_mut(); let target = match terminator.kind { TerminatorKind::Call { destination: Some((_, target)), .. } => target, ref kind => { @@ -891,7 +891,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let last = self.promoted.basic_blocks().last().unwrap(); let new_target = self.new_block(); - *self.promoted.basic_block_terminator_mut(last) = Terminator { + *self.promoted[last].terminator_mut() = Terminator { kind: TerminatorKind::Call { func, args, @@ -976,12 +976,11 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } }, Candidate::Argument { bb, index } => { - let data = &mut blocks[bb]; - let terminator_span = data.terminator().source_info.span; - match data.terminator_kind_mut() { + let terminator = blocks[bb].terminator_mut(); + match terminator.kind { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); - let span = terminator_span; + let span = terminator.source_info.span; let operand = Operand::Copy(promoted_place(ty, span)); mem::replace(&mut args[index], operand) } @@ -1104,8 +1103,8 @@ pub fn promote_candidates<'tcx>( // Eliminate assignments to, and drops of promoted temps. let promoted = |index: Local| temps[index] == TempState::PromotedOut; - for bb in body.basic_blocks().indices() { - body.basic_blocks_mut()[bb].statements.retain(|statement| { + for block in body.basic_blocks_mut() { + block.statements.retain(|statement| { match &statement.kind { StatementKind::Assign(box(place, _)) => { if let Some(index) = place.as_local() { @@ -1121,7 +1120,7 @@ pub fn promote_candidates<'tcx>( _ => true } }); - let terminator = body.basic_block_terminator_mut(bb); + let terminator = block.terminator_mut(); match &terminator.kind { TerminatorKind::Drop { location: place, target, .. } => { if let Some(index) = place.as_local() { diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 9e0f80dcf9ae4..130393e2c4c86 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -103,7 +103,7 @@ impl RemoveNoopLandingPads { let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); for bb in postorder { debug!(" processing {:?}", bb); - for target in body.basic_block_terminator_mut(bb).successors_mut() { + for target in body[bb].terminator_mut().successors_mut() { if *target != resume_block && nop_landing_pads.contains(*target) { debug!(" folding noop jump to {:?} to resume block", target); *target = resume_block; @@ -111,7 +111,7 @@ impl RemoveNoopLandingPads { } } - match body.basic_block_terminator_mut(bb).unwind_mut() { + match body[bb].terminator_mut().unwind_mut() { Some(unwind) => { if *unwind == Some(resume_block) { debug!(" removing noop landing pad"); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 2f98a15e819e1..2cd13daf31b4d 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -63,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { } pub struct CfgSimplifier<'a, 'tcx> { - body: &'a mut Body<'tcx>, + basic_blocks: &'a mut IndexVec>, pred_count: IndexVec } @@ -76,23 +76,21 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pred_count[START_BLOCK] = 1; for (_, data) in traversal::preorder(body) { - if let Some(ref term) = data.terminator_opt() { + if let Some(ref term) = data.terminator { for &tgt in term.successors() { pred_count[tgt] += 1; } } } + let basic_blocks = body.basic_blocks_mut(); + CfgSimplifier { - body, + basic_blocks, pred_count, } } - fn basic_blocks(&mut self) -> &mut IndexVec> { - self.body.basic_blocks_mut() - } - pub fn simplify(mut self) { self.strip_nops(); @@ -103,14 +101,14 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { self.collapse_goto_chain(&mut start, &mut changed); - for bb in self.body.basic_blocks().indices() { + for bb in self.basic_blocks.indices() { if self.pred_count[bb] == 0 { continue } debug!("simplifying {:?}", bb); - let mut terminator = self.body.basic_block_terminator_opt_mut(bb).take() + let mut terminator = self.basic_blocks[bb].terminator.take() .expect("invalid terminator state"); for successor in terminator.successors_mut() { @@ -125,8 +123,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator); changed |= inner_changed; } - self.basic_blocks()[bb].statements.extend(new_stmts); - *self.body.basic_block_terminator_opt_mut(bb) = Some(terminator); + + { + let data = &mut self.basic_blocks[bb]; + data.statements.extend(new_stmts); + data.terminator = Some(terminator); + } changed |= inner_changed; } @@ -136,17 +138,17 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { if start != START_BLOCK { debug_assert!(self.pred_count[START_BLOCK] == 0); - self.basic_blocks().swap(START_BLOCK, start); + self.basic_blocks.swap(START_BLOCK, start); self.pred_count.swap(START_BLOCK, start); // pred_count == 1 if the start block has no predecessor _blocks_. if self.pred_count[START_BLOCK] > 1 { - for bb in self.basic_blocks().indices() { + for (bb, data) in self.basic_blocks.iter_enumerated_mut() { if self.pred_count[bb] == 0 { continue; } - for target in self.body.basic_block_terminator_mut(bb).successors_mut() { + for target in data.terminator_mut().successors_mut() { if *target == start { *target = START_BLOCK; } @@ -158,7 +160,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { // Collapse a goto chain starting from `start` fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) { - let mut terminator = match self.basic_blocks()[*start] { + let mut terminator = match self.basic_blocks[*start] { BasicBlockData { ref statements, terminator: ref mut terminator @ Some(Terminator { @@ -177,7 +179,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } _ => unreachable!() }; - self.basic_blocks()[*start].terminator = terminator; + self.basic_blocks[*start].terminator = terminator; debug!("collapsing goto chain from {:?} to {:?}", *start, target); @@ -209,7 +211,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { }; debug!("merging block {:?} into {:?}", target, terminator); - *terminator = match self.body.basic_block_terminator_opt_mut(target).take() { + *terminator = match self.basic_blocks[target].terminator.take() { Some(terminator) => terminator, None => { // unreachable loop - this should not be possible, as we @@ -217,7 +219,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { return false } }; - new_stmts.extend(self.basic_blocks()[target].statements.drain(..)); + new_stmts.extend(self.basic_blocks[target].statements.drain(..)); self.pred_count[target] = 0; true @@ -250,7 +252,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } fn strip_nops(&mut self) { - for blk in self.basic_blocks().iter_mut() { + for blk in self.basic_blocks.iter_mut() { blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind { false } else { @@ -266,27 +268,24 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { seen.insert(bb.index()); } - let mut replacements: Vec; - { - let basic_blocks = body.basic_blocks_mut(); - - let num_blocks = basic_blocks.len(); - replacements = (0..num_blocks).map(BasicBlock::new).collect(); - let mut used_blocks = 0; - for alive_index in seen.iter() { - replacements[alive_index] = BasicBlock::new(used_blocks); - if alive_index != used_blocks { - // Swap the next alive block data with the current available slot. Since - // alive_index is non-decreasing this is a valid operation. - basic_blocks.raw.swap(alive_index, used_blocks); - } - used_blocks += 1; + let basic_blocks = body.basic_blocks_mut(); + + let num_blocks = basic_blocks.len(); + let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); + let mut used_blocks = 0; + for alive_index in seen.iter() { + replacements[alive_index] = BasicBlock::new(used_blocks); + if alive_index != used_blocks { + // Swap the next alive block data with the current available slot. Since + // alive_index is non-decreasing this is a valid operation. + basic_blocks.raw.swap(alive_index, used_blocks); } - basic_blocks.raw.truncate(used_blocks); + used_blocks += 1; } + basic_blocks.raw.truncate(used_blocks); - for bb in body.basic_blocks().indices() { - for target in body.basic_block_terminator_mut(bb).successors_mut() { + for block in basic_blocks { + for target in block.terminator_mut().successors_mut() { *target = replacements[target.index()]; } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 1e45ad5d428cf..0a509666d34ae 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -21,8 +21,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(src.def_id()); - for bb in body.basic_blocks().indices() { - let terminator = body.basic_block_terminator_mut(bb); + for block in body.basic_blocks_mut() { + let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, .. diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 554ae2d3c6b68..a5f7e5401573b 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -141,7 +141,7 @@ impl<'tcx> MirPatch<'tcx> { for (src, patch) in self.patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); - body.basic_block_terminator_mut(src).kind = patch; + body[src].terminator_mut().kind = patch; } } From 94414ac7bba05377468ef0b7c775df6e87535ddd Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 4 Oct 2019 01:01:01 -0400 Subject: [PATCH 10/47] Address excessive line length that was triggering warning during linting --- src/librustc/mir/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a91017e880a3b..940f35cf49830 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -217,7 +217,11 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn unwrap_predecessors(&self) -> &IndexVec> { - assert!(self.predecessors_cache.is_some(), "Expected predecessors_cache to be `Some(...)` for block at: {:?}", self.span.data()); + assert!( + self.predecessors_cache.is_some(), + "Expected predecessors_cache to be `Some(...)` for block at: {:?}", + self.span.data() + ); self.predecessors_cache.as_ref().unwrap() } From 52cc85f0084d335e67765e385b9a4c35cda87a48 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 4 Oct 2019 09:44:24 -0400 Subject: [PATCH 11/47] Address nits and remove unneeded pass --- src/librustc_mir/transform/inline.rs | 2 +- src/librustc_mir/transform/mod.rs | 2 -- src/librustc_mir/transform/simplify.rs | 8 +++----- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 1d45c1fe18696..ebfadd0cfd3ed 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -496,7 +496,7 @@ impl Inliner<'tcx> { kind: TerminatorKind::Goto { target: BasicBlock::new(bb_len) } }; - caller_body[callsite.bb].terminator= Some(terminator); + caller_body[callsite.bb].terminator = Some(terminator); true } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 76e89ce5cf204..156ef4c3b8a9b 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -297,8 +297,6 @@ fn run_optimization_passes<'tcx>( &uniform_array_move_out::RestoreSubsliceArrayMoveOut::new(tcx), &inline::Inline, - // State transform requires that predecessors have been predefined - &ensure_predecessors_cache::EnsurePredecessorsCache::new("pre-state-transform"), // Lowering generator control-flow and variables // has to happen before we do anything else to them. &generator::StateTransform, diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 2cd13daf31b4d..040bc5c309a9b 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -124,11 +124,9 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { changed |= inner_changed; } - { - let data = &mut self.basic_blocks[bb]; - data.statements.extend(new_stmts); - data.terminator = Some(terminator); - } + let data = &mut self.basic_blocks[bb]; + data.statements.extend(new_stmts); + data.terminator = Some(terminator); changed |= inner_changed; } From 22bc8a01c19b88ecd0b60081322f4ec60032f78f Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 4 Oct 2019 11:46:01 -0400 Subject: [PATCH 12/47] Add back cache invalidation to basic_blocks_and_local_decls_mut --- src/librustc/mir/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 940f35cf49830..ea9de2fdae820 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -203,7 +203,7 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { - debug!("Clearing predecessors cache at: {:?}", self.span.data()); + debug!("bbm: Clearing predecessors cache for body at: {:?}", self.span.data()); self.predecessors_cache = None; &mut self.basic_blocks } @@ -212,6 +212,8 @@ impl<'tcx> Body<'tcx> { pub fn basic_blocks_and_local_decls_mut( &mut self, ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { + debug!("bbaldm: Clearing predecessors cache for body at: {:?}", self.span.data()); + self.predecessors_cache = None; (&mut self.basic_blocks, &mut self.local_decls) } From 9b335ce1a64048dbdf930deef9ca1851b7412e86 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 7 Oct 2019 16:08:57 -0400 Subject: [PATCH 13/47] Move predecessors cache back to its own type This ensures that the cache can be properly ignored during encoding and decoding. Fix panics that arose due to lack of encoding --- src/librustc/mir/cache.rs | 47 ++++++++++++++++++++++++++ src/librustc/mir/mod.rs | 23 ++++++------- src/librustc_metadata/rmeta/decoder.rs | 2 +- src/librustc_mir/transform/mod.rs | 3 +- 4 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 src/librustc/mir/cache.rs diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs new file mode 100644 index 0000000000000..8dac356c0a299 --- /dev/null +++ b/src/librustc/mir/cache.rs @@ -0,0 +1,47 @@ +use rustc_index::vec::IndexVec; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +use crate::ich::StableHashingContext; +use crate::mir::BasicBlock; + +#[derive(Clone, Debug)] +pub(in crate::mir) struct Cache { + pub(in crate::mir) predecessors: Option>> +} + + +impl rustc_serialize::Encodable for Cache { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + Encodable::encode(&(), s) + } +} + +impl rustc_serialize::Decodable for Cache { + fn decode(d: &mut D) -> Result { + Decodable::decode(d).map(|_v: ()| Self::new()) + } +} + +impl<'a> HashStable> for Cache { + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + // Do nothing. + } +} + +impl Cache { + pub fn new() -> Self { + Cache { + predecessors: None + } + } + + #[inline] + pub fn invalidate_predecessors(&mut self) { + // FIXME: consider being more fine-grained + self.predecessors = None; + } +} + +CloneTypeFoldableAndLiftImpls! { + Cache, +} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ea9de2fdae820..fb5ee211de2e2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -40,6 +40,7 @@ use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; +mod cache; pub mod interpret; pub mod mono; pub mod tcx; @@ -154,7 +155,7 @@ pub struct Body<'tcx> { pub span: Span, /// A cache for various calculations. - predecessors_cache: Option>>, + cache: cache::Cache, } impl<'tcx> Body<'tcx> { @@ -191,7 +192,7 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, - predecessors_cache: None, + cache: cache::Cache::new(), control_flow_destroyed, } } @@ -204,7 +205,7 @@ impl<'tcx> Body<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { debug!("bbm: Clearing predecessors cache for body at: {:?}", self.span.data()); - self.predecessors_cache = None; + self.cache.invalidate_predecessors(); &mut self.basic_blocks } @@ -213,23 +214,23 @@ impl<'tcx> Body<'tcx> { &mut self, ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { debug!("bbaldm: Clearing predecessors cache for body at: {:?}", self.span.data()); - self.predecessors_cache = None; + self.cache.invalidate_predecessors(); (&mut self.basic_blocks, &mut self.local_decls) } #[inline] pub fn unwrap_predecessors(&self) -> &IndexVec> { assert!( - self.predecessors_cache.is_some(), - "Expected predecessors_cache to be `Some(...)` for block at: {:?}", + self.cache.predecessors.is_some(), + "Expected cache.predecessors to be `Some(...)` for block at: {:?}", self.span.data() ); - self.predecessors_cache.as_ref().unwrap() + self.cache.predecessors.as_ref().unwrap() } #[inline] pub fn ensure_predecessors(&mut self) { - if self.predecessors_cache.is_none() { + if self.cache.predecessors.is_none() { let mut result = IndexVec::from_elem(vec![], self.basic_blocks()); for (bb, data) in self.basic_blocks().iter_enumerated() { if let Some(ref term) = data.terminator { @@ -239,7 +240,7 @@ impl<'tcx> Body<'tcx> { } } - self.predecessors_cache = Some(result) + self.cache.predecessors = Some(result) } } @@ -247,7 +248,7 @@ impl<'tcx> Body<'tcx> { /// This will recompute the predecessors cache if it is not available pub fn predecessors(&mut self) -> &IndexVec> { self.ensure_predecessors(); - self.predecessors_cache.as_ref().unwrap() + self.cache.predecessors.as_ref().unwrap() } #[inline] @@ -1030,8 +1031,6 @@ impl BasicBlock { } } -CloneTypeFoldableAndLiftImpls!{ BasicBlock, } - /////////////////////////////////////////////////////////////////////////// // BasicBlockData and Terminator diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 820783bab6d27..bbf28418f11a6 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> CrateMetadata { fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { self.root.per_def.mir.get(self, id) - .filter(|_| !self.is_proc_macro(id)) + self.entry_unless_proc_macro(id) .unwrap_or_else(|| { bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 156ef4c3b8a9b..e80fb93617075 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -249,8 +249,9 @@ fn mir_validated( // What we need to run borrowck etc. &promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), - &ensure_predecessors_cache::EnsurePredecessorsCache::new("qualify-consts"), ]); + + body.ensure_predecessors(); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } From c0592faa67a1fe8fb7425f24899c5538dec23ee1 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 9 Oct 2019 23:22:58 -0400 Subject: [PATCH 14/47] Move predecessor cache outside of Body, use wrapper types to manage Cache and Body (WIP, amend this commit) --- src/librustc/mir/cache.rs | 258 ++++++++++++++++-- src/librustc/mir/mod.rs | 124 +-------- src/librustc/mir/visit.rs | 26 +- .../graph/dominators/mod.rs | 17 +- src/librustc_data_structures/graph/mod.rs | 2 +- .../graph/reference.rs | 34 ++- 6 files changed, 300 insertions(+), 161 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 8dac356c0a299..4300a5acba4f8 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -1,47 +1,255 @@ use rustc_index::vec::IndexVec; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; -use crate::ich::StableHashingContext; -use crate::mir::BasicBlock; +//use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +//use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +//use crate::ich::StableHashingContext; +use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors}; +use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; +use rustc_data_structures::graph::dominators::{dominators, Dominators}; +use std::iter; +use std::ops::{Index, IndexMut}; +use std::vec::IntoIter; #[derive(Clone, Debug)] -pub(in crate::mir) struct Cache { - pub(in crate::mir) predecessors: Option>> +pub struct Cache { + predecessors: Option>>, } -impl rustc_serialize::Encodable for Cache { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - Encodable::encode(&(), s) +//impl<'tcx, T> rustc_serialize::Encodable for Cache<'tcx, T> { +// fn encode(&self, s: &mut S) -> Result<(), S::Error> { +// Encodable::encode(&(), s) +// } +//} +// +//impl<'tcx, T> rustc_serialize::Decodable for Cache<'tcx, T> { +// fn decode(d: &mut D) -> Result { +// Decodable::decode(d).map(|_v: ()| Self::new()) +// } +//} +// +//impl<'a, 'tcx, T> HashStable> for Cache<'tcx, T> { +// fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { +// // Do nothing. +// } +//} + +impl Cache { + pub fn new() -> Self { + Self { + predecessors: None, + } + } + + #[inline] + pub fn invalidate_predecessors(&mut self) { + // FIXME: consider being more fine-grained + self.predecessors = None; + } + + #[inline] + /// This will recompute the predecessors cache if it is not available + pub fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec> { + if self.predecessors.is_none() { + let mut result = IndexVec::from_elem(vec![], body.basic_blocks()); + for (bb, data) in body.basic_blocks().iter_enumerated() { + if let Some(ref term) = data.terminator { + for &tgt in term.successors() { + result[tgt].push(bb); + } + } + } + + self.predecessors = Some(result) + } + + self.predecessors.as_ref().unwrap() + } + + #[inline] + pub fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] { + &self.predecessors(body)[bb] + } + + #[inline] + pub fn predecessor_locations<'a>(&'a mut self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { + let if_zero_locations = if loc.statement_index == 0 { + let predecessor_blocks = self.predecessors_for(loc.block, body); + let num_predecessor_blocks = predecessor_blocks.len(); + Some( + (0..num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| body.terminator_loc(bb)), + ) + } else { + None + }; + + let if_not_zero_locations = if loc.statement_index == 0 { + None + } else { + Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) + }; + + if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) + } + + #[inline] + pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec> { + debug!("bbm: Clearing predecessors cache for body at: {:?}", body.span.data()); + self.invalidate_predecessors(); + &mut body.basic_blocks + } + + #[inline] + pub fn basic_blocks_and_local_decls_mut<'a, 'tcx>( + &mut self, + body: &'a mut Body<'tcx> + ) -> (&'a mut IndexVec>, &'a mut LocalDecls<'tcx>) { + debug!("bbaldm: Clearing predecessors cache for body at: {:?}", body.span.data()); + self.invalidate_predecessors(); + (&mut body.basic_blocks, &mut body.local_decls) + } +} + +pub struct OwningCache<'tcx> { + cache: Cache, + body: Body<'tcx>, +} + +impl<'tcx> OwningCache<'tcx> { + pub fn borrow(&mut self) -> BorrowedCache<'_, 'tcx> { + BorrowedCache { + cache: &mut self.cache, + body: &self.body, + } + } + + pub fn borrow_mut(&mut self) -> MutCache<'_, 'tcx> { + MutCache { + cache: &mut self.cache, + body: &mut self.body, + } + } +} + +pub struct BorrowedCache<'a, 'tcx> { + cache: &'a mut Cache, + body: &'a Body<'tcx> +} + +impl<'a, 'tcx> BorrowedCache<'a, 'tcx> { + #[inline] + pub fn predecessors_for(&mut self, bb: BasicBlock) -> &[BasicBlock] { + self.cache.predecessors_for(bb, self.body) + } + + #[inline] + pub fn body(&self) -> &Body<'tcx> { + self.body + } + + #[inline] + pub fn basic_blocks(&self) -> &IndexVec> { + &self.body.basic_blocks + } + + #[inline] + pub fn dominators(&mut self) -> Dominators { + dominators(self) } } -impl rustc_serialize::Decodable for Cache { - fn decode(d: &mut D) -> Result { - Decodable::decode(d).map(|_v: ()| Self::new()) +impl<'a, 'tcx> Index for BorrowedCache<'a, 'tcx> { + type Output = BasicBlockData<'tcx>; + + #[inline] + fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { + &self.body[index] } } -impl<'a> HashStable> for Cache { - fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - // Do nothing. +impl<'a, 'tcx> graph::DirectedGraph for BorrowedCache<'a, 'tcx> { + type Node = BasicBlock; +} + +impl<'a, 'graph, 'tcx> graph::GraphPredecessors<'graph> for BorrowedCache<'a, 'tcx> { + type Item = BasicBlock; + type Iter = IntoIter; +} + +impl<'a, 'tcx> graph::WithPredecessors for BorrowedCache<'a, 'tcx> { + fn predecessors( + &mut self, + node: Self::Node, + ) -> >::Iter { + self.predecessors_for(node).to_vec().into_iter() } } -impl Cache { - pub fn new() -> Self { - Cache { - predecessors: None - } +impl<'a, 'tcx> graph::WithNumNodes for BorrowedCache<'a, 'tcx> { + fn num_nodes(&self) -> usize { + self.body.num_nodes() } +} +impl<'a, 'tcx> graph::WithStartNode for BorrowedCache<'a, 'tcx> { + fn start_node(&self) -> Self::Node { + self.body.start_node() + } +} + +impl<'a, 'tcx> graph::WithSuccessors for BorrowedCache<'a, 'tcx> { + fn successors( + &self, + node: Self::Node, + ) -> >::Iter { + self.body.successors(node) + } +} + +impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for BorrowedCache<'a, 'tcx> { + type Item = BasicBlock; + type Iter = iter::Cloned>; +} + +pub struct MutCache<'a, 'tcx> { + cache: &'a mut Cache, + body: &'a mut Body<'tcx>, +} + +impl<'a, 'tcx> MutCache<'a, 'tcx> { #[inline] - pub fn invalidate_predecessors(&mut self) { - // FIXME: consider being more fine-grained - self.predecessors = None; + pub fn body(&mut self) -> &mut Body<'tcx> { + self.body + } + + #[inline] + pub fn basic_blocks(&self) -> &IndexVec> { + &self.body.basic_blocks + } + + #[inline] + pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { + self.cache.basic_blocks_mut(&mut self.body) } } -CloneTypeFoldableAndLiftImpls! { - Cache, +impl<'a, 'tcx> Index for MutCache<'a, 'tcx> { + type Output = BasicBlockData<'tcx>; + + #[inline] + fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { + &self.body[index] + } } + +impl<'a, 'tcx> IndexMut for MutCache<'a, 'tcx> { + fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output { + self.cache.invalidate_predecessors(); + &mut self.body.basic_blocks[index] + } +} + +//CloneTypeFoldableAndLiftImpls! { +// Cache, +//} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index fb5ee211de2e2..fa435b9a51b8a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -21,8 +21,8 @@ use crate::ty::{ use polonius_engine::Atom; use rustc_index::bit_set::BitMatrix; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::graph::dominators::{dominators, Dominators}; -use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; +use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::graph::{self, GraphSuccessors}; use rustc_index::vec::{Idx, IndexVec}; use rustc_data_structures::sync::Lrc; use rustc_macros::HashStable; @@ -30,9 +30,8 @@ use rustc_serialize::{Encodable, Decodable}; use smallvec::SmallVec; use std::borrow::Cow; use std::fmt::{self, Debug, Display, Formatter, Write}; -use std::ops::{Index, IndexMut}; +use std::ops::Index; use std::slice; -use std::vec::IntoIter; use std::{iter, mem, option, u32}; use syntax::ast::Name; use syntax::symbol::Symbol; @@ -40,7 +39,7 @@ use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -mod cache; +pub mod cache; pub mod interpret; pub mod mono; pub mod tcx; @@ -153,9 +152,6 @@ pub struct Body<'tcx> { /// A span representing this MIR, for error reporting. pub span: Span, - - /// A cache for various calculations. - cache: cache::Cache, } impl<'tcx> Body<'tcx> { @@ -192,7 +188,6 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, - cache: cache::Cache::new(), control_flow_destroyed, } } @@ -202,88 +197,6 @@ impl<'tcx> Body<'tcx> { &self.basic_blocks } - #[inline] - pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { - debug!("bbm: Clearing predecessors cache for body at: {:?}", self.span.data()); - self.cache.invalidate_predecessors(); - &mut self.basic_blocks - } - - #[inline] - pub fn basic_blocks_and_local_decls_mut( - &mut self, - ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { - debug!("bbaldm: Clearing predecessors cache for body at: {:?}", self.span.data()); - self.cache.invalidate_predecessors(); - (&mut self.basic_blocks, &mut self.local_decls) - } - - #[inline] - pub fn unwrap_predecessors(&self) -> &IndexVec> { - assert!( - self.cache.predecessors.is_some(), - "Expected cache.predecessors to be `Some(...)` for block at: {:?}", - self.span.data() - ); - self.cache.predecessors.as_ref().unwrap() - } - - #[inline] - pub fn ensure_predecessors(&mut self) { - if self.cache.predecessors.is_none() { - let mut result = IndexVec::from_elem(vec![], self.basic_blocks()); - for (bb, data) in self.basic_blocks().iter_enumerated() { - if let Some(ref term) = data.terminator { - for &tgt in term.successors() { - result[tgt].push(bb); - } - } - } - - self.cache.predecessors = Some(result) - } - } - - #[inline] - /// This will recompute the predecessors cache if it is not available - pub fn predecessors(&mut self) -> &IndexVec> { - self.ensure_predecessors(); - self.cache.predecessors.as_ref().unwrap() - } - - #[inline] - pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { - &self.unwrap_predecessors()[bb] - } - - #[inline] - pub fn predecessor_locations(&self, loc: Location) -> impl Iterator + '_ { - let if_zero_locations = if loc.statement_index == 0 { - let predecessor_blocks = self.predecessors_for(loc.block); - let num_predecessor_blocks = predecessor_blocks.len(); - Some( - (0..num_predecessor_blocks) - .map(move |i| predecessor_blocks[i]) - .map(move |bb| self.terminator_loc(bb)), - ) - } else { - None - }; - - let if_not_zero_locations = if loc.statement_index == 0 { - None - } else { - Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) - }; - - if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) - } - - #[inline] - pub fn dominators(&self) -> Dominators { - dominators(self) - } - /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the /// `START_BLOCK`. pub fn is_cfg_cyclic(&self) -> bool { @@ -384,7 +297,7 @@ impl<'tcx> Body<'tcx> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// invalidating statement indices in `Location`s. pub fn make_statement_nop(&mut self, location: Location) { - let block = &mut self[location.block]; + let block = &mut self.basic_blocks[location.block]; debug_assert!(location.statement_index < block.statements.len()); block.statements[location.statement_index].make_nop() } @@ -444,13 +357,6 @@ impl<'tcx> Index for Body<'tcx> { } } -impl<'tcx> IndexMut for Body<'tcx> { - #[inline] - fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> { - &mut self.basic_blocks_mut()[index] - } -} - #[derive(Copy, Clone, Debug, HashStable, TypeFoldable)] pub enum ClearCrossCrate { Clear, @@ -2647,15 +2553,6 @@ impl<'tcx> graph::WithStartNode for Body<'tcx> { } } -impl<'tcx> graph::WithPredecessors for Body<'tcx> { - fn predecessors( - &self, - node: Self::Node, - ) -> >::Iter { - self.predecessors_for(node).to_vec().into_iter() - } -} - impl<'tcx> graph::WithSuccessors for Body<'tcx> { fn successors( &self, @@ -2665,11 +2562,6 @@ impl<'tcx> graph::WithSuccessors for Body<'tcx> { } } -impl<'a, 'b> graph::GraphPredecessors<'b> for Body<'a> { - type Item = BasicBlock; - type Iter = IntoIter; -} - impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { type Item = BasicBlock; type Iter = iter::Cloned>; @@ -2704,7 +2596,7 @@ impl Location { } /// Returns `true` if `other` is earlier in the control flow graph than `self`. - pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool { + pub fn is_predecessor_of<'tcx>(&self, other: Location, mut body_cache: cache::BorrowedCache<'_, 'tcx>) -> bool { // If we are in the same block as the other location and are an earlier statement // then we are a predecessor of `other`. if self.block == other.block && self.statement_index < other.statement_index { @@ -2712,13 +2604,13 @@ impl Location { } // If we're in another block, then we want to check that block is a predecessor of `other`. - let mut queue: Vec = body.predecessors_for(other.block).to_vec(); + let mut queue: Vec = body_cache.predecessors_for(other.block).to_vec(); let mut visited = FxHashSet::default(); while let Some(block) = queue.pop() { // If we haven't visited this block before, then make sure we visit it's predecessors. if visited.insert(block) { - queue.extend(body.predecessors_for(block).iter().cloned()); + queue.extend(body_cache.predecessors_for(block).iter().cloned()); } else { continue; } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 145593f1c4d4a..fbcfe10483958 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,6 +1,7 @@ use crate::ty::subst::SubstsRef; use crate::ty::{CanonicalUserTypeAnnotation, Ty}; use crate::mir::*; +use crate::mir::cache::*; use syntax_pos::Span; // # The MIR Visitor @@ -71,8 +72,8 @@ macro_rules! make_mir_visitor { // Override these, and call `self.super_xxx` to revert back to the // default behavior. - fn visit_body(&mut self, body: & $($mutability)? Body<'tcx>) { - self.super_body(body); + fn visit_body(&mut self, body_cache: & $($mutability)? cache_type!('tcx $($mutability)?)) { + self.super_body(body_cache); } fn visit_basic_block_data(&mut self, @@ -241,10 +242,11 @@ macro_rules! make_mir_visitor { // not meant to be overridden. fn super_body(&mut self, - body: & $($mutability)? Body<'tcx>) { - if let Some(yield_ty) = &$($mutability)? body.yield_ty { + body_cache: & $($mutability)? cache_type!('tcx $($mutability)?)) { + let span = body_cache.body().span; + if let Some(yield_ty) = &$($mutability)? body_cache.body().yield_ty { self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo { - span: body.span, + span, scope: OUTERMOST_SOURCE_SCOPE, })); } @@ -253,13 +255,14 @@ macro_rules! make_mir_visitor { // than a for-loop, to avoid calling `body::Body::invalidate` for // each basic block. macro_rules! basic_blocks { - (mut) => (body.basic_blocks_mut().iter_enumerated_mut()); - () => (body.basic_blocks().iter_enumerated()); + (mut) => (body_cache.basic_blocks_mut().iter_enumerated_mut()); + () => (body_cache.basic_blocks().iter_enumerated()); }; for (bb, data) in basic_blocks!($($mutability)?) { self.visit_basic_block_data(bb, data); } + let body = body_cache.body(); for scope in &$($mutability)? body.source_scopes { self.visit_source_scope_data(scope); } @@ -790,8 +793,8 @@ macro_rules! make_mir_visitor { // Convenience methods - fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { - let basic_block = & $($mutability)? body[location.block]; + fn visit_location(&mut self, body_cache: & $($mutability)? cache_type!('tcx $($mutability)?), location: Location) { + let basic_block = & $($mutability)? body_cache[location.block]; if basic_block.statements.len() == location.statement_index { if let Some(ref $($mutability)? terminator) = basic_block.terminator { self.visit_terminator(terminator, location) @@ -806,6 +809,11 @@ macro_rules! make_mir_visitor { } } +macro_rules! cache_type { + ($tcx:lifetime mut) => {MutCache<'_, $tcx>}; + ($tcx:lifetime) => {BorrowedCache<'_, $tcx>}; +} + macro_rules! visit_place_fns { (mut) => ( fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs index 444463c08e557..5fb58eea3819d 100644 --- a/src/librustc_data_structures/graph/dominators/mod.rs +++ b/src/librustc_data_structures/graph/dominators/mod.rs @@ -7,32 +7,33 @@ use rustc_index::vec::{Idx, IndexVec}; use super::iterate::reverse_post_order; use super::ControlFlowGraph; +use std::borrow::BorrowMut; #[cfg(test)] mod tests; -pub fn dominators(graph: &G) -> Dominators { +pub fn dominators(graph: G) -> Dominators { let start_node = graph.start_node(); - let rpo = reverse_post_order(graph, start_node); + let rpo = reverse_post_order(&graph, start_node); dominators_given_rpo(graph, &rpo) } -fn dominators_given_rpo( - graph: &G, +fn dominators_given_rpo>( + mut graph: G, rpo: &[G::Node], ) -> Dominators { - let start_node = graph.start_node(); + let start_node = graph.borrow().start_node(); assert_eq!(rpo[0], start_node); // compute the post order index (rank) for each node let mut post_order_rank: IndexVec = - (0..graph.num_nodes()).map(|_| 0).collect(); + (0..graph.borrow().num_nodes()).map(|_| 0).collect(); for (index, node) in rpo.iter().rev().cloned().enumerate() { post_order_rank[node] = index; } let mut immediate_dominators: IndexVec> = - (0..graph.num_nodes()).map(|_| None).collect(); + (0..graph.borrow().num_nodes()).map(|_| None).collect(); immediate_dominators[start_node] = Some(start_node); let mut changed = true; @@ -41,7 +42,7 @@ fn dominators_given_rpo( for &node in &rpo[1..] { let mut new_idom = None; - for pred in graph.predecessors(node) { + for pred in graph.borrow_mut().predecessors(node) { if immediate_dominators[pred].is_some() { // (*) dominators for `pred` have been calculated new_idom = Some(if let Some(new_idom) = new_idom { diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 37335799d19af..9ce60d207ad0e 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -50,7 +50,7 @@ where Self: for<'graph> GraphPredecessors<'graph, Item = ::Node>, { fn predecessors( - &self, + &mut self, node: Self::Node, ) -> >::Iter; } diff --git a/src/librustc_data_structures/graph/reference.rs b/src/librustc_data_structures/graph/reference.rs index 9442bb3cdec3b..bc4458334d57f 100644 --- a/src/librustc_data_structures/graph/reference.rs +++ b/src/librustc_data_structures/graph/reference.rs @@ -4,11 +4,20 @@ impl<'graph, G: DirectedGraph> DirectedGraph for &'graph G { type Node = G::Node; } +impl<'graph, G: DirectedGraph> DirectedGraph for &'graph mut G { + type Node = G::Node; +} + impl<'graph, G: WithNumNodes> WithNumNodes for &'graph G { fn num_nodes(&self) -> usize { (**self).num_nodes() } } +impl<'graph, G: WithNumNodes> WithNumNodes for &'graph mut G { + fn num_nodes(&self) -> usize { + (**self).num_nodes() + } +} impl<'graph, G: WithStartNode> WithStartNode for &'graph G { fn start_node(&self) -> Self::Node { @@ -16,14 +25,25 @@ impl<'graph, G: WithStartNode> WithStartNode for &'graph G { } } +impl<'graph, G: WithStartNode> WithStartNode for &'graph mut G { + fn start_node(&self) -> Self::Node { + (**self).start_node() + } +} + impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G { fn successors(&self, node: Self::Node) -> >::Iter { (**self).successors(node) } } +impl<'graph, G: WithSuccessors> WithSuccessors for &'graph mut G { + fn successors(&self, node: Self::Node) -> >::Iter { + (**self).successors(node) + } +} -impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G { - fn predecessors(&self, +impl<'graph, G: WithPredecessors> WithPredecessors for &'graph mut G { + fn predecessors(&mut self, node: Self::Node) -> >::Iter { (**self).predecessors(node) @@ -35,7 +55,17 @@ impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph G type Iter = >::Iter; } +impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph mut G { + type Item = G::Node; + type Iter = >::Iter; +} + impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph G { type Item = G::Node; type Iter = >::Iter; } + +impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph mut G { + type Item = G::Node; + type Iter = >::Iter; +} From 649c73f96d8969f05000a071007bcd050fa8d466 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 10 Oct 2019 23:16:44 -0400 Subject: [PATCH 15/47] Simplify Cache wrapper to single type, impl Deref on it, fix all compilation errors in librustc_codegen_ssa --- src/librustc/mir/cache.rs | 82 +++++++++---------- src/librustc/mir/mod.rs | 7 +- src/librustc/mir/visit.rs | 23 +++--- src/librustc_codegen_ssa/base.rs | 5 +- src/librustc_codegen_ssa/mir/analyze.rs | 40 +++++---- src/librustc_codegen_ssa/mir/block.rs | 12 +-- src/librustc_codegen_ssa/mir/mod.rs | 16 ++-- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +- src/librustc_mir/borrow_check/mod.rs | 48 +++++------ .../borrow_check/nll/type_check/mod.rs | 8 +- src/librustc_mir/shim.rs | 12 --- .../transform/ensure_predecessors_cache.rs | 26 ------ src/librustc_mir/transform/generator.rs | 4 - src/librustc_mir/transform/mod.rs | 3 - 15 files changed, 132 insertions(+), 162 deletions(-) delete mode 100644 src/librustc_mir/transform/ensure_predecessors_cache.rs diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 4300a5acba4f8..e218931b74916 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -6,7 +6,7 @@ use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Success use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use std::iter; -use std::ops::{Index, IndexMut}; +use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::vec::IntoIter; #[derive(Clone, Debug)] @@ -111,33 +111,21 @@ impl Cache { } } -pub struct OwningCache<'tcx> { +pub struct BodyCache { cache: Cache, - body: Body<'tcx>, + body: T, } -impl<'tcx> OwningCache<'tcx> { - pub fn borrow(&mut self) -> BorrowedCache<'_, 'tcx> { - BorrowedCache { - cache: &mut self.cache, - body: &self.body, - } - } - - pub fn borrow_mut(&mut self) -> MutCache<'_, 'tcx> { - MutCache { - cache: &mut self.cache, - body: &mut self.body, +impl BodyCache { + pub fn new(body: T) -> Self { + Self { + cache: Cache::new(), + body } } } -pub struct BorrowedCache<'a, 'tcx> { - cache: &'a mut Cache, - body: &'a Body<'tcx> -} - -impl<'a, 'tcx> BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> { #[inline] pub fn predecessors_for(&mut self, bb: BasicBlock) -> &[BasicBlock] { self.cache.predecessors_for(bb, self.body) @@ -159,7 +147,14 @@ impl<'a, 'tcx> BorrowedCache<'a, 'tcx> { } } -impl<'a, 'tcx> Index for BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> Deref for BodyCache<&'a Body<'tcx>> { + type Target = Body<'tcx>; + fn deref(&self) -> &Body<'tcx> { + self.body + } +} + +impl<'a, 'tcx> Index for BodyCache<&'a Body<'tcx>> { type Output = BasicBlockData<'tcx>; #[inline] @@ -168,16 +163,16 @@ impl<'a, 'tcx> Index for BorrowedCache<'a, 'tcx> { } } -impl<'a, 'tcx> graph::DirectedGraph for BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> graph::DirectedGraph for BodyCache<&'a Body<'tcx>> { type Node = BasicBlock; } -impl<'a, 'graph, 'tcx> graph::GraphPredecessors<'graph> for BorrowedCache<'a, 'tcx> { +impl<'a, 'graph, 'tcx> graph::GraphPredecessors<'graph> for BodyCache<&'a Body<'tcx>> { type Item = BasicBlock; type Iter = IntoIter; } -impl<'a, 'tcx> graph::WithPredecessors for BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> graph::WithPredecessors for BodyCache<&'a Body<'tcx>> { fn predecessors( &mut self, node: Self::Node, @@ -186,19 +181,19 @@ impl<'a, 'tcx> graph::WithPredecessors for BorrowedCache<'a, 'tcx> { } } -impl<'a, 'tcx> graph::WithNumNodes for BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> graph::WithNumNodes for BodyCache<&'a Body<'tcx>> { fn num_nodes(&self) -> usize { self.body.num_nodes() } } -impl<'a, 'tcx> graph::WithStartNode for BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> graph::WithStartNode for BodyCache<&'a Body<'tcx>> { fn start_node(&self) -> Self::Node { self.body.start_node() } } -impl<'a, 'tcx> graph::WithSuccessors for BorrowedCache<'a, 'tcx> { +impl<'a, 'tcx> graph::WithSuccessors for BodyCache<&'a Body<'tcx>> { fn successors( &self, node: Self::Node, @@ -207,17 +202,12 @@ impl<'a, 'tcx> graph::WithSuccessors for BorrowedCache<'a, 'tcx> { } } -impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for BorrowedCache<'a, 'tcx> { +impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for BodyCache<&'a Body<'tcx>> { type Item = BasicBlock; type Iter = iter::Cloned>; } -pub struct MutCache<'a, 'tcx> { - cache: &'a mut Cache, - body: &'a mut Body<'tcx>, -} - -impl<'a, 'tcx> MutCache<'a, 'tcx> { +impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> { #[inline] pub fn body(&mut self) -> &mut Body<'tcx> { self.body @@ -234,7 +224,21 @@ impl<'a, 'tcx> MutCache<'a, 'tcx> { } } -impl<'a, 'tcx> Index for MutCache<'a, 'tcx> { +impl<'a, 'tcx> Deref for BodyCache<&'a mut Body<'tcx>> { + type Target = Body<'tcx>; + + fn deref(&self) -> &Body<'tcx> { + self.body + } +} + +impl<'a, 'tcx> DerefMut for BodyCache<&'a mut Body<'tcx>> { + fn deref_mut(&mut self) -> &mut Body<'tcx> { + self.body + } +} + +impl<'a, 'tcx> Index for BodyCache<&'a mut Body<'tcx>> { type Output = BasicBlockData<'tcx>; #[inline] @@ -243,13 +247,9 @@ impl<'a, 'tcx> Index for MutCache<'a, 'tcx> { } } -impl<'a, 'tcx> IndexMut for MutCache<'a, 'tcx> { +impl<'a, 'tcx> IndexMut for BodyCache<&'a mut Body<'tcx>> { fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output { self.cache.invalidate_predecessors(); &mut self.body.basic_blocks[index] } } - -//CloneTypeFoldableAndLiftImpls! { -// Cache, -//} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index fa435b9a51b8a..9f71840576382 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -38,6 +38,7 @@ use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; +pub use crate::mir::cache::BodyCache; pub mod cache; pub mod interpret; @@ -2596,7 +2597,11 @@ impl Location { } /// Returns `true` if `other` is earlier in the control flow graph than `self`. - pub fn is_predecessor_of<'tcx>(&self, other: Location, mut body_cache: cache::BorrowedCache<'_, 'tcx>) -> bool { + pub fn is_predecessor_of<'tcx>( + &self, + other: Location, + mut body_cache: BodyCache<&'_ Body<'tcx>> + ) -> bool { // If we are in the same block as the other location and are an earlier statement // then we are a predecessor of `other`. if self.block == other.block && self.statement_index < other.statement_index { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index fbcfe10483958..5803663bbecdd 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,7 +1,6 @@ use crate::ty::subst::SubstsRef; use crate::ty::{CanonicalUserTypeAnnotation, Ty}; use crate::mir::*; -use crate::mir::cache::*; use syntax_pos::Span; // # The MIR Visitor @@ -72,7 +71,10 @@ macro_rules! make_mir_visitor { // Override these, and call `self.super_xxx` to revert back to the // default behavior. - fn visit_body(&mut self, body_cache: & $($mutability)? cache_type!('tcx $($mutability)?)) { + fn visit_body( + &mut self, + body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>> + ) { self.super_body(body_cache); } @@ -241,8 +243,10 @@ macro_rules! make_mir_visitor { // The `super_xxx` methods comprise the default behavior and are // not meant to be overridden. - fn super_body(&mut self, - body_cache: & $($mutability)? cache_type!('tcx $($mutability)?)) { + fn super_body( + &mut self, + body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>> + ) { let span = body_cache.body().span; if let Some(yield_ty) = &$($mutability)? body_cache.body().yield_ty { self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo { @@ -793,7 +797,11 @@ macro_rules! make_mir_visitor { // Convenience methods - fn visit_location(&mut self, body_cache: & $($mutability)? cache_type!('tcx $($mutability)?), location: Location) { + fn visit_location( + &mut self, + body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>>, + location: Location + ) { let basic_block = & $($mutability)? body_cache[location.block]; if basic_block.statements.len() == location.statement_index { if let Some(ref $($mutability)? terminator) = basic_block.terminator { @@ -809,11 +817,6 @@ macro_rules! make_mir_visitor { } } -macro_rules! cache_type { - ($tcx:lifetime mut) => {MutCache<'_, $tcx>}; - ($tcx:lifetime) => {BorrowedCache<'_, $tcx>}; -} - macro_rules! visit_place_fns { (mut) => ( fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 22693beb855d2..d67a9d3799eab 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,6 +31,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; +use rustc::mir::BodyCache; use rustc::mir::mono::{CodegenUnitNameBuilder, CodegenUnit, MonoItem}; use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; @@ -374,7 +375,9 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let lldecl = cx.get_fn(instance); let mir = cx.tcx().instance_mir(instance.def); - mir::codegen_mir::(cx, lldecl, &mir, instance, sig); + // TODO(nashenas88) move this into instance_mir before merging PR + let mut mir = BodyCache::new(mir); + mir::codegen_mir::(cx, lldecl, &mut mir, instance, sig); } /// Creates the `main` function which will initialize the rust runtime and call diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index e44551fcbcdfe..7a2940a8e673b 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -4,7 +4,7 @@ use rustc_index::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::vec::{Idx, IndexVec}; -use rustc::mir::{self, Location, TerminatorKind}; +use rustc::mir::{self, Body, BodyCache, Location, TerminatorKind}; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext, NonUseContext, }; @@ -17,10 +17,10 @@ use super::FunctionCx; use crate::traits::*; pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - fx: &FunctionCx<'a, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, ) -> BitSet { - let mir = fx.mir; - let mut analyzer = LocalAnalyzer::new(fx); + let mir = fx.mir.take().unwrap(); + let mut analyzer = LocalAnalyzer::new(fx, mir); analyzer.visit_body(mir); @@ -54,11 +54,14 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } - analyzer.non_ssa_locals + let (mir, non_ssa_locals) = analyzer.finalize(); + fx.mir = Some(mir); + non_ssa_locals } struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { fx: &'mir FunctionCx<'a, 'tcx, Bx>, + mir: &'a mut BodyCache<&'a Body<'tcx>>, dominators: Dominators, non_ssa_locals: BitSet, // The location of the first visited direct assignment to each @@ -67,27 +70,32 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { } impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self { + fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>, mir: &'a mut BodyCache<&'a Body<'tcx>>) -> Self { let invalid_location = - mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); + mir::BasicBlock::new(mir.basic_blocks().len()).start_location(); let mut analyzer = LocalAnalyzer { fx, - dominators: fx.mir.dominators(), - non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()), - first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls) + dominators: mir.dominators(), + mir, + non_ssa_locals: BitSet::new_empty(mir.local_decls.len()), + first_assignment: IndexVec::from_elem(invalid_location, &mir.local_decls) }; // Arguments get assigned to by means of the function being called - for arg in fx.mir.args_iter() { + for arg in mir.args_iter() { analyzer.first_assignment[arg] = mir::START_BLOCK.start_location(); } analyzer } + fn finalize(self) -> (&'a mut BodyCache<&'a Body<'tcx>>, BitSet) { + (self.mir, self.non_ssa_locals) + } + fn first_assignment(&self, local: mir::Local) -> Option { let location = self.first_assignment[local]; - if location.block.index() < self.fx.mir.basic_blocks().len() { + if location.block.index() < self.mir.basic_blocks().len() { Some(location) } else { None @@ -130,7 +138,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, self.mir.body(), cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. @@ -139,7 +147,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { .ty; let elem_ty = self.fx.monomorphize(&elem_ty); let span = if let mir::PlaceBase::Local(index) = place_ref.base { - self.fx.mir.local_decls[*index].source_info.span + self.mir.local_decls[*index].source_info.span } else { DUMMY_SP }; @@ -243,7 +251,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> if let Some(index) = place.as_local() { self.assign(index, location); - let decl_span = self.fx.mir.local_decls[index].source_info.span; + let decl_span = self.mir.local_decls[index].source_info.span; if !self.fx.rvalue_creates_operand(rvalue, decl_span) { self.not_ssa(index); } @@ -348,7 +356,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } PlaceContext::MutatingUse(MutatingUseContext::Drop) => { - let ty = self.fx.mir.local_decls[local].ty; + let ty = self.mir.local_decls[local].ty; let ty = self.fx.monomorphize(&ty); // Only need the place if we're actually dropping it. diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index d76392f7570b4..d09ff0160db17 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } else { let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, llret); - if fx.mir[*self.bb].is_cleanup { + if fx.mir.unwrap()[*self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested // struct, there are "symmetry" issues that cause @@ -324,7 +324,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(self.mir, bx.tcx()).ty; + let ty = location.ty(self.mir.unwrap().body(), bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); @@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); + let op_ty = op_arg.ty(self.mir.unwrap().body(), bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); @@ -791,7 +791,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bb: mir::BasicBlock, ) { let mut bx = self.build_block(bb); - let data = &self.mir[bb]; + let data = &self.mir.unwrap()[bb]; debug!("codegen_block({:?}={:?})", bb, data); @@ -1053,7 +1053,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { target_bb: Bx::BasicBlock ) -> Bx::BasicBlock { if base::wants_msvc_seh(self.cx.sess()) { - span_bug!(self.mir.span, "landing pad was not inserted?") + span_bug!(self.mir.unwrap().span, "landing pad was not inserted?") } let mut bx = self.new_block("cleanup"); @@ -1154,7 +1154,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // // If someone changes that, please update this code path // to create a temporary. - span_bug!(self.mir.span, "can't directly store to unaligned value"); + span_bug!(self.mir.unwrap().span, "can't directly store to unaligned value"); } llargs.push(dest.llval); ReturnDest::Nothing diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 6041232489d0d..8b12786723802 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -1,6 +1,6 @@ use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, Body}; +use rustc::mir::{self, Body, BodyCache}; use rustc_target::abi::call::{FnAbi, PassMode}; use crate::base; use crate::traits::*; @@ -21,7 +21,7 @@ use self::operand::{OperandRef, OperandValue}; pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: &'a mir::Body<'tcx>, + mir: Option<&'a mut BodyCache<&'a mir::Body<'tcx>>>, debug_context: Option>, @@ -122,7 +122,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, llfn: Bx::Function, - mir: &'a Body<'tcx>, + mir: &'a mut BodyCache<&'a Body<'tcx>>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, ) { @@ -159,7 +159,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut fx = FunctionCx { instance, - mir, + mir: Some(mir), llfn, fn_abi, cx, @@ -174,7 +174,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), }; - let memory_locals = analyze::non_ssa_locals(&fx); + let memory_locals = analyze::non_ssa_locals(&mut fx); // Allocate variable and temp allocas fx.locals = { @@ -327,10 +327,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut idx = 0; let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - mir.args_iter().enumerate().map(|(arg_index, local)| { - let arg_decl = &mir.local_decls[local]; + mir.unwrap().args_iter().enumerate().map(|(arg_index, local)| { + let arg_decl = &mir.unwrap().local_decls[local]; - if Some(local) == mir.spread_arg { + if Some(local) == mir.unwrap().spread_arg { // This argument (e.g., the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 4df5bce95377b..8f3c1de9c6440 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -591,7 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir, tcx); + let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir.unwrap().body(), tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index f7fb4a571401c..c1519b6106dfc 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(&*self.mir, bx.tcx()); + let discr_ty = rvalue.ty(self.mir.unwrap().body(), bx.tcx()); let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { @@ -513,7 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(self.mir, self.cx.tcx()); + let ty = rvalue.ty(self.mir.unwrap().body(), self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -710,7 +710,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(self.mir, self.cx.tcx()); + let ty = rvalue.ty(self.mir.unwrap().body(), self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 63a8de5eebacd..f861a423ae266 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -9,8 +9,8 @@ use rustc::lint::builtin::UNUSED_MUT; use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT}; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ - ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceElem, - PlaceRef, Static, StaticKind + ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase, + PlaceElem, PlaceRef, Static, StaticKind }; use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -167,16 +167,12 @@ fn do_mir_borrowck<'a, 'tcx>( let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); - // Region replacement above very likely invalidated the predecessors cache. It's used later on - // when retrieving the dominators from the body, so we need to ensure it exists before locking - // the body for changes. - body.ensure_predecessors(); - let body = &body; // no further changes - let location_table = &LocationTable::new(body); + let body_cache = &BodyCache::new(&body); // no further changes + let location_table = &LocationTable::new(body_cache); let mut errors_buffer = Vec::new(); let (move_data, move_errors): (MoveData<'tcx>, Option, MoveError<'tcx>)>>) = - match MoveData::gather_moves(body, tcx) { + match MoveData::gather_moves(body_cache, tcx) { Ok(move_data) => (move_data, None), Err((move_data, move_errors)) => (move_data, Some(move_errors)), }; @@ -186,27 +182,27 @@ fn do_mir_borrowck<'a, 'tcx>( param_env, }; - let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, - body, + body_cache, def_id, &attributes, &dead_unwinds, - MaybeInitializedPlaces::new(tcx, body, &mdpe), + MaybeInitializedPlaces::new(tcx, body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build( - tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); + tcx, body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( infcx, def_id, free_regions, - body, + body_cache, &promoted, &local_names, &upvars, @@ -227,29 +223,29 @@ fn do_mir_borrowck<'a, 'tcx>( let flow_borrows = FlowAtLocation::new(do_dataflow( tcx, - body, + body_cache, def_id, &attributes, &dead_unwinds, - Borrows::new(tcx, body, param_env, regioncx.clone(), &borrow_set), + Borrows::new(tcx, body_cache, param_env, regioncx.clone(), &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); let flow_uninits = FlowAtLocation::new(do_dataflow( tcx, - body, + body_cache, def_id, &attributes, &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, body, &mdpe), + MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, - body, + body_cache, def_id, &attributes, &dead_unwinds, - EverInitializedPlaces::new(tcx, body, &mdpe), + EverInitializedPlaces::new(tcx, body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); @@ -261,11 +257,11 @@ fn do_mir_borrowck<'a, 'tcx>( _ => true, }; - let dominators = body.dominators(); + let dominators = body_cache.dominators(); let mut mbcx = MirBorrowckCtxt { infcx, - body, + body_cache, mir_def_id: def_id, param_env, move_data: &mdpe.move_data, @@ -403,7 +399,7 @@ fn do_mir_borrowck<'a, 'tcx>( crate struct MirBorrowckCtxt<'cx, 'tcx> { crate infcx: &'cx InferCtxt<'cx, 'tcx>, - body: &'cx Body<'tcx>, + body_cache: BodyCache<&'cx Body<'tcx>>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, move_data: &'cx MoveData<'tcx>, @@ -494,7 +490,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx type FlowState = Flows<'cx, 'tcx>; fn body(&self) -> &'cx Body<'tcx> { - self.body + self.body_cache } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { @@ -644,7 +640,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx let tcx = self.infcx.tcx; // Compute the type with accurate region information. - let drop_place_ty = drop_place.ty(self.body, self.infcx.tcx); + let drop_place_ty = drop_place.ty(self.body_cache, self.infcx.tcx); // Erase the regions. let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; @@ -988,7 +984,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut error_reported = false; let tcx = self.infcx.tcx; - let body = self.body; + let body = self.body_cache; let param_env = self.param_env; let location_table = self.location_table.start_index(location); let borrow_set = self.borrow_set.clone(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 99bcfa9bc2599..4f95aa4a7b003 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -385,15 +385,15 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - fn visit_body(&mut self, body: &Body<'tcx>) { - self.sanitize_type(&"return type", body.return_ty()); - for local_decl in &body.local_decls { + fn visit_body(&mut self, body_cache: &BodyCache<&'_ Body<'tcx>>) { + self.sanitize_type(&"return type", body_cache.return_ty()); + for local_decl in &body_cache.local_decls { self.sanitize_type(local_decl, local_decl.ty); } if self.errors_reported { return; } - self.super_body(body); + self.super_body(body_cache); } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 938d3f8ce9761..734e1a5972e45 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -123,17 +123,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx &add_call_guards::CriticalCallEdges, ]); - // The `ensure_predecessors_cache::EnsurePredecessorsCache` MirPass wasn't used in the - // `run_passes` above because the above pass is not always guaranteed to run. There can be - // instances where, e.g. a `MirPhase::Validated` pass has already been run on a `Body` by the - // time it arrived at this line, and so the above `run_passes` call will NOT run any of the - // passes (They do not run if a same or later pass has already been executed on a `Body`). - // Adding the ensure pass during the `run_passes` for `MirPhase::Validated` would not - // help because the predecessors cache would be invalidated between that pass and this call. - // Having the single ensure outside of the `run_passes` list here guarantees that anyone - // using this `Body` could call `Body::unwrap_predecessors()` without worrying about a panic. - result.ensure_predecessors(); - debug!("make_shim({:?}) = {:?}", instance, result); tcx.arena.alloc(result) @@ -926,7 +915,6 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { sig.inputs().len(), span, ); - body.ensure_predecessors(); crate::util::dump_mir( tcx, diff --git a/src/librustc_mir/transform/ensure_predecessors_cache.rs b/src/librustc_mir/transform/ensure_predecessors_cache.rs deleted file mode 100644 index db1ef863351c0..0000000000000 --- a/src/librustc_mir/transform/ensure_predecessors_cache.rs +++ /dev/null @@ -1,26 +0,0 @@ -use rustc::mir::Body; -use rustc::ty::TyCtxt; -use crate::transform::{MirPass, MirSource}; - -pub struct EnsurePredecessorsCache { - label: String, -} - -impl EnsurePredecessorsCache { - pub fn new>(label: S) -> Self { - Self { - label: label.into(), - } - } -} - -impl<'tcx> MirPass<'tcx> for EnsurePredecessorsCache { - fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { - debug!("{}: Ensure predecessors cache: {:?}", self.label, body.span.data()); - // predecessors is lazily calculated. We want to ensure that the cache is properly filled - // before the next stages of compilation, since these following stages will only be allowed - // to read the cache and not generate it. If the cache is already up to date, this line is - // a nop. - body.ensure_predecessors(); - } -} diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 8c11d66fb48c7..37205e65a0a42 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1203,10 +1203,6 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // RETURN_PLACE then is a fresh unused local with type ret_ty. let new_ret_local = replace_result_variable(ret_ty, body, tcx); - // Replacing result variables very likely clears the predecessors cache (needed inside of - // compute layout), so we need to ensure the cache exists. - body.ensure_predecessors(); - // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices // `storage_liveness` tells us which locals have live storage at suspension points diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index e80fb93617075..1eac40fc591a0 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -20,7 +20,6 @@ pub mod check_unsafety; pub mod simplify_branches; pub mod simplify_try; pub mod simplify; -pub mod ensure_predecessors_cache; pub mod erase_regions; pub mod no_landing_pads; pub mod rustc_peek; @@ -251,7 +250,6 @@ fn mir_validated( &simplify::SimplifyCfg::new("qualify-consts"), ]); - body.ensure_predecessors(); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } @@ -316,7 +314,6 @@ fn run_optimization_passes<'tcx>( &simplify::SimplifyLocals, &add_call_guards::CriticalCallEdges, - &ensure_predecessors_cache::EnsurePredecessorsCache::new("before-opt-dump"), &dump_mir::Marker("PreCodegen"), ]); } From 30b1d9e79861dcc40cfcfcf7faf5a890369f9693 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 12 Oct 2019 16:51:05 -0400 Subject: [PATCH 16/47] Remove Body from FunctionCx, pass it along during librustc_codegen_ssa --- src/librustc_codegen_ssa/base.rs | 4 +- src/librustc_codegen_ssa/mir/analyze.rs | 35 ++--- src/librustc_codegen_ssa/mir/block.rs | 171 ++++++++++++---------- src/librustc_codegen_ssa/mir/mod.rs | 28 ++-- src/librustc_codegen_ssa/mir/operand.rs | 10 +- src/librustc_codegen_ssa/mir/place.rs | 13 +- src/librustc_codegen_ssa/mir/rvalue.rs | 59 ++++---- src/librustc_codegen_ssa/mir/statement.rs | 23 +-- 8 files changed, 184 insertions(+), 159 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index d67a9d3799eab..f50be08c15c1d 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -376,8 +376,8 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let mir = cx.tcx().instance_mir(instance.def); // TODO(nashenas88) move this into instance_mir before merging PR - let mut mir = BodyCache::new(mir); - mir::codegen_mir::(cx, lldecl, &mut mir, instance, sig); + let mir = BodyCache::new(mir); + mir::codegen_mir::(cx, lldecl, mir, instance, sig); } /// Creates the `main` function which will initialize the rust runtime and call diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 7a2940a8e673b..68d5eec9b255e 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -4,7 +4,7 @@ use rustc_index::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::vec::{Idx, IndexVec}; -use rustc::mir::{self, Body, BodyCache, Location, TerminatorKind}; +use rustc::mir::{self, BasicBlock, Body, BodyCache, Location, TerminatorKind}; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext, NonUseContext, }; @@ -16,11 +16,12 @@ use syntax_pos::DUMMY_SP; use super::FunctionCx; use crate::traits::*; -pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub fn non_ssa_locals<'b, 'a: 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &mut FunctionCx<'a, 'tcx, Bx>, + mir: &'b mut BodyCache<&'a Body<'tcx>>, ) -> BitSet { - let mir = fx.mir.take().unwrap(); - let mut analyzer = LocalAnalyzer::new(fx, mir); + let dominators = mir.dominators(); + let mut analyzer = LocalAnalyzer::new(fx, mir, dominators); analyzer.visit_body(mir); @@ -54,14 +55,12 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } - let (mir, non_ssa_locals) = analyzer.finalize(); - fx.mir = Some(mir); - non_ssa_locals + analyzer.non_ssa_locals } -struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { +struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { fx: &'mir FunctionCx<'a, 'tcx, Bx>, - mir: &'a mut BodyCache<&'a Body<'tcx>>, + mir: &'b Body<'tcx>, dominators: Dominators, non_ssa_locals: BitSet, // The location of the first visited direct assignment to each @@ -69,14 +68,14 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { first_assignment: IndexVec, } -impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>, mir: &'a mut BodyCache<&'a Body<'tcx>>) -> Self { +impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { + fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>, mir: &'b Body<'tcx>, dominators: Dominators) -> Self { let invalid_location = mir::BasicBlock::new(mir.basic_blocks().len()).start_location(); let mut analyzer = LocalAnalyzer { fx, - dominators: mir.dominators(), mir, + dominators, non_ssa_locals: BitSet::new_empty(mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &mir.local_decls) }; @@ -89,10 +88,6 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { analyzer } - fn finalize(self) -> (&'a mut BodyCache<&'a Body<'tcx>>, BitSet) { - (self.mir, self.non_ssa_locals) - } - fn first_assignment(&self, local: mir::Local) -> Option { let location = self.first_assignment[local]; if location.block.index() < self.mir.basic_blocks().len() { @@ -138,7 +133,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, self.mir.body(), cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, self.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. @@ -240,8 +235,8 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { } -impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> - for LocalAnalyzer<'mir, 'a, 'tcx, Bx> +impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> + for LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { fn visit_assign(&mut self, place: &mir::Place<'tcx>, @@ -252,7 +247,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> if let Some(index) = place.as_local() { self.assign(index, location); let decl_span = self.mir.local_decls[index].source_info.span; - if !self.fx.rvalue_creates_operand(rvalue, decl_span) { + if !self.fx.rvalue_creates_operand(rvalue, decl_span, self.mir) { self.not_ssa(index); } } else { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index d09ff0160db17..e0be162984aaf 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -2,7 +2,7 @@ use rustc_index::vec::Idx; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, PlaceBase, Static, StaticKind}; +use rustc::mir::{self, Body, PlaceBase, Static, StaticKind}; use rustc::mir::interpret::PanicInfo; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::abi::Abi; @@ -46,7 +46,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - target: mir::BasicBlock, + mir: &Body<'tcx>, + target: mir::BasicBlock ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; let lltarget = fx.blocks[target]; @@ -56,9 +57,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => (lltarget, false), // jump *into* cleanup - need a landing pad if GNU - (None, Some(_)) => (fx.landing_pad_to(target), false), + (None, Some(_)) => (fx.landing_pad_to(target, mir), false), (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), - (Some(_), Some(_)) => (fx.landing_pad_to(target), true), + (Some(_), Some(_)) => (fx.landing_pad_to(target, mir), true), } } @@ -66,9 +67,10 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - target: mir::BasicBlock, + mir: &Body<'tcx>, + target: mir::BasicBlock ) -> Bx::BasicBlock { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); + let (lltarget, is_cleanupret) = self.lltarget(fx, mir, target); if is_cleanupret { // MSVC cross-funclet jump - need a trampoline @@ -86,10 +88,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + mir: &Body<'tcx>, bx: &mut Bx, target: mir::BasicBlock, ) { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); + let (lltarget, is_cleanupret) = self.lltarget(fx, mir, target); if is_cleanupret { // micro-optimization: generate a `ret` rather than a jump // to a trampoline. @@ -104,6 +107,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + mir: &Body<'tcx>, bx: &mut Bx, fn_abi: FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, @@ -120,19 +124,19 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { let invokeret = bx.invoke(fn_ptr, &llargs, ret_bx, - self.llblock(fx, cleanup), + self.llblock(fx, mir, cleanup), self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, invokeret); if let Some((ret_dest, target)) = destination { let mut ret_bx = fx.build_block(target); - fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); + fx.set_debug_loc(&mut ret_bx, self.terminator.source_info, mir); fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); } } else { let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, llret); - if fx.mir.unwrap()[*self.bb].is_cleanup { + if mir[*self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested // struct, there are "symmetry" issues that cause @@ -142,7 +146,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { if let Some((ret_dest, target)) = destination { fx.store_return(bx, ret_dest, &fn_abi.ret, llret); - self.funclet_br(fx, bx, target); + self.funclet_br(fx, mir, bx, target); } else { bx.unreachable(); } @@ -204,19 +208,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn codegen_switchint_terminator<'b>( &mut self, helper: TerminatorCodegenHelper<'b, 'tcx>, + mir: &Body<'tcx>, mut bx: Bx, discr: &mir::Operand<'tcx>, switch_ty: Ty<'tcx>, values: &Cow<'tcx, [u128]>, targets: &Vec, ) { - let discr = self.codegen_operand(&mut bx, &discr); + let discr = self.codegen_operand(mir, &mut bx, &discr); if targets.len() == 2 { // If there are two targets, emit br instead of switch - let lltrue = helper.llblock(self, targets[0]); - let llfalse = helper.llblock(self, targets[1]); + let lltrue = helper.llblock(self, mir, targets[0]); + let llfalse = helper.llblock(self, mir, targets[1]); if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool if let [0] = values[..] { bx.cond_br(discr.immediate(), llfalse, lltrue); @@ -238,15 +243,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), - helper.llblock(self, *otherwise), + helper.llblock(self, mir, *otherwise), values.iter().zip(targets).map(|(&value, target)| { - (value, helper.llblock(self, *target)) + (value, helper.llblock(self, mir, *target)) }) ); } } - fn codegen_return_terminator(&mut self, mut bx: Bx) { + fn codegen_return_terminator(&mut self, mir: &Body<'tcx>, mut bx: Bx) { // Call `va_end` if this is the definition of a C-variadic function. if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. @@ -273,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { PassMode::Direct(_) | PassMode::Pair(..) => { let op = - self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); + self.codegen_consume(mir, &mut bx, &mir::Place::return_place().as_ref()); if let Ref(llval, _, align) = op.val { bx.load(llval, align) } else { @@ -319,23 +324,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn codegen_drop_terminator<'b>( &mut self, helper: TerminatorCodegenHelper<'b, 'tcx>, + mir: &Body<'tcx>, mut bx: Bx, location: &mir::Place<'tcx>, target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(self.mir.unwrap().body(), bx.tcx()).ty; + let ty = location.ty(mir, bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, mir, &mut bx, target); return } - let place = self.codegen_place(&mut bx, &location.as_ref()); + let place = self.codegen_place(mir, &mut bx, &location.as_ref()); let (args1, args2); let mut args = if let Some(llextra) = place.llextra { args2 = [place.llval, llextra]; @@ -361,8 +367,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { FnAbi::of_instance(&bx, drop_fn)) } }; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.do_call(self, &mut bx, fn_abi, drop_fn, args, + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); } @@ -370,6 +376,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn codegen_assert_terminator<'b>( &mut self, helper: TerminatorCodegenHelper<'b, 'tcx>, + mir: &Body<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, cond: &mir::Operand<'tcx>, @@ -379,7 +386,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cleanup: Option, ) { let span = terminator.source_info.span; - let cond = self.codegen_operand(&mut bx, cond).immediate(); + let cond = self.codegen_operand(mir, &mut bx, cond).immediate(); let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1); // This case can currently arise only from functions marked @@ -397,8 +404,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Don't codegen the panic block if success if known. if const_cond == Some(expected) { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, mir, &mut bx, target); return; } @@ -406,9 +413,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cond = bx.expect(cond, expected); // Create the failure block and the conditional branch to it. - let lltarget = helper.llblock(self, target); + let lltarget = helper.llblock(self, mir, target); let panic_block = self.new_block("panic"); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(mir, &mut bx, &[target]); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -417,7 +424,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // After this point, bx is the block for the call to panic. bx = panic_block; - self.set_debug_loc(&mut bx, terminator.source_info); + self.set_debug_loc(&mut bx, terminator.source_info, mir); // Get the location information. let location = self.get_caller_location(&mut bx, span).immediate(); @@ -425,8 +432,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Put together the arguments to the panic entry point. let (lang_item, args) = match msg { PanicInfo::BoundsCheck { ref len, ref index } => { - let len = self.codegen_operand(&mut bx, len).immediate(); - let index = self.codegen_operand(&mut bx, index).immediate(); + let len = self.codegen_operand(mir, &mut bx, len).immediate(); + let index = self.codegen_operand(mir, &mut bx, index).immediate(); (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) } _ => { @@ -443,12 +450,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. - helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); + helper.do_call(self, mir, &mut bx, fn_abi, llfn, &args, None, cleanup); } fn codegen_call_terminator<'b>( &mut self, helper: TerminatorCodegenHelper<'b, 'tcx>, + mir: &Body<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, @@ -458,7 +466,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) { let span = terminator.source_info.span; // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. - let callee = self.codegen_operand(&mut bx, func); + let callee = self.codegen_operand(mir, &mut bx, func); let (instance, mut llfn) = match callee.layout.ty.kind { ty::FnDef(def_id, substs) => { @@ -492,9 +500,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if intrinsic == Some("transmute") { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; - self.codegen_transmute(&mut bx, &args[0], dest); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + self.codegen_transmute(mir, &mut bx, &args[0], dest); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, mir, &mut bx, target); } else { // If we are trying to transmute to an uninhabited type, // it is likely there is no allotted destination. In fact, @@ -510,7 +518,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir.unwrap().body(), bx.tcx()); + let op_ty = op_arg.ty(mir, bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); @@ -521,8 +529,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(ty::InstanceDef::DropGlue(_, None)) => { // Empty drop glue; a no-op. let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, mir, &mut bx, target); return; } _ => FnAbi::new(&bx, sig, &extra_args) @@ -558,6 +566,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Codegen the actual panic invoke/call. helper.do_call( self, + mir, &mut bx, fn_abi, llfn, @@ -568,8 +577,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { // a NOP let target = destination.as_ref().unwrap().1; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) } return; } @@ -582,7 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ret_dest = if let Some((ref dest, _)) = *destination { let is_intrinsic = intrinsic.is_some(); self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, - is_intrinsic) + is_intrinsic, mir) } else { ReturnDest::Nothing }; @@ -671,7 +680,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - self.codegen_operand(&mut bx, arg) + self.codegen_operand(mir, &mut bx, arg) }).collect(); @@ -683,8 +692,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } if let Some((_, target)) = *destination { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, mir, &mut bx, target); } else { bx.unreachable(); } @@ -701,7 +710,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; 'make_args: for (i, arg) in first_args.iter().enumerate() { - let mut op = self.codegen_operand(&mut bx, arg); + let mut op = self.codegen_operand(mir, &mut bx, arg); if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { if let Pair(..) = op.val { @@ -766,7 +775,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]); } if let Some(tup) = untuple { - self.codegen_arguments_untupled(&mut bx, tup, &mut llargs, + self.codegen_arguments_untupled(mir, &mut bx, tup, &mut llargs, &fn_abi.args[first_args.len()..]) } @@ -777,9 +786,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + helper.maybe_sideeffect(mir, &mut bx, &[*target]); } - helper.do_call(self, &mut bx, fn_abi, fn_ptr, &llargs, + helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), cleanup); } @@ -789,24 +798,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_block( &mut self, bb: mir::BasicBlock, + mir: &Body<'tcx>, ) { let mut bx = self.build_block(bb); - let data = &self.mir.unwrap()[bb]; + let data = &mir[bb]; debug!("codegen_block({:?}={:?})", bb, data); for statement in &data.statements { - bx = self.codegen_statement(bx, statement); + bx = self.codegen_statement(mir, bx, statement); } - self.codegen_terminator(bx, bb, data.terminator()); + self.codegen_terminator(bx, bb, data.terminator(), mir); } fn codegen_terminator( &mut self, mut bx: Bx, bb: mir::BasicBlock, - terminator: &mir::Terminator<'tcx> + terminator: &mir::Terminator<'tcx>, + mir: &Body<'tcx> ) { debug!("codegen_terminator: {:?}", terminator); @@ -816,7 +827,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bb: &bb, terminator, funclet_bb }; - self.set_debug_loc(&mut bx, terminator.source_info); + self.set_debug_loc(&mut bx, terminator.source_info, mir); match terminator.kind { mir::TerminatorKind::Resume => { self.codegen_resume_terminator(helper, bx) @@ -828,19 +839,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.funclet_br(self, mir, &mut bx, target); } mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { - self.codegen_switchint_terminator(helper, bx, discr, switch_ty, + self.codegen_switchint_terminator(helper, mir, bx, discr, switch_ty, values, targets); } mir::TerminatorKind::Return => { - self.codegen_return_terminator(bx); + self.codegen_return_terminator(mir, bx); } mir::TerminatorKind::Unreachable => { @@ -848,11 +859,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Drop { ref location, target, unwind } => { - self.codegen_drop_terminator(helper, bx, location, target, unwind); + self.codegen_drop_terminator(helper, mir, bx, location, target, unwind); } mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => { - self.codegen_assert_terminator(helper, bx, terminator, cond, + self.codegen_assert_terminator(helper, mir, bx, terminator, cond, expected, msg, target, cleanup); } @@ -867,7 +878,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cleanup, from_hir_call: _ } => { - self.codegen_call_terminator(helper, bx, terminator, func, + self.codegen_call_terminator(helper, mir, bx, terminator, func, args, destination, cleanup); } mir::TerminatorKind::GeneratorDrop | @@ -972,12 +983,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn codegen_arguments_untupled( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, operand: &mir::Operand<'tcx>, llargs: &mut Vec, args: &[ArgAbi<'tcx, Ty<'tcx>>] ) { - let tuple = self.codegen_operand(bx, operand); + let tuple = self.codegen_operand(mir, bx, operand); // Handle both by-ref and immediate tuples. if let Ref(llval, None, align) = tuple.val { @@ -1036,24 +1048,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// No-op in MSVC SEH scheme. fn landing_pad_to( &mut self, - target_bb: mir::BasicBlock + target_bb: mir::BasicBlock, + mir: &Body<'tcx> ) -> Bx::BasicBlock { if let Some(block) = self.landing_pads[target_bb] { return block; } let block = self.blocks[target_bb]; - let landing_pad = self.landing_pad_uncached(block); + let landing_pad = self.landing_pad_uncached(block, mir); self.landing_pads[target_bb] = Some(landing_pad); landing_pad } fn landing_pad_uncached( &mut self, - target_bb: Bx::BasicBlock + target_bb: Bx::BasicBlock, + mir: &Body<'tcx> ) -> Bx::BasicBlock { if base::wants_msvc_seh(self.cx.sess()) { - span_bug!(self.mir.unwrap().span, "landing pad was not inserted?") + span_bug!(mir.span, "landing pad was not inserted?") } let mut bx = self.new_block("cleanup"); @@ -1105,7 +1119,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, dest: &mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, - llargs: &mut Vec, is_intrinsic: bool + llargs: &mut Vec, is_intrinsic: bool, + mir: &Body<'tcx> ) -> ReturnDest<'tcx, Bx::Value> { // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { @@ -1141,7 +1156,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - self.codegen_place(bx, &mir::PlaceRef { + self.codegen_place(mir, bx, &mir::PlaceRef { base: &dest.base, projection: &dest.projection, }) @@ -1154,7 +1169,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // // If someone changes that, please update this code path // to create a temporary. - span_bug!(self.mir.unwrap().span, "can't directly store to unaligned value"); + span_bug!(mir.span, "can't directly store to unaligned value"); } llargs.push(dest.llval); ReturnDest::Nothing @@ -1165,20 +1180,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn codegen_transmute( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, src: &mir::Operand<'tcx>, dst: &mir::Place<'tcx> ) { if let Some(index) = dst.as_local() { match self.locals[index] { - LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), + LocalRef::Place(place) => self.codegen_transmute_into(mir, bx, src, place), LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), LocalRef::Operand(None) => { - let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); + let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref(), mir)); assert!(!dst_layout.ty.has_erasable_regions()); let place = PlaceRef::alloca(bx, dst_layout); place.storage_live(bx); - self.codegen_transmute_into(bx, src, place); + self.codegen_transmute_into(mir, bx, src, place); let op = bx.load_operand(place); place.storage_dead(bx); self.locals[index] = LocalRef::Operand(Some(op)); @@ -1189,18 +1205,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - let dst = self.codegen_place(bx, &dst.as_ref()); - self.codegen_transmute_into(bx, src, dst); + let dst = self.codegen_place(mir, bx, &dst.as_ref()); + self.codegen_transmute_into(mir, bx, src, dst); } } fn codegen_transmute_into( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, src: &mir::Operand<'tcx>, dst: PlaceRef<'tcx, Bx::Value> ) { - let src = self.codegen_operand(bx, src); + let src = self.codegen_operand(mir, bx, src); let llty = bx.backend_type(src.layout); let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); let align = src.layout.align.abi.min(dst.align); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 8b12786723802..cfc5a468f95d3 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -21,7 +21,7 @@ use self::operand::{OperandRef, OperandValue}; pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: Option<&'a mut BodyCache<&'a mir::Body<'tcx>>>, +// mir: Option<&'a mut BodyCache<&'a mir::Body<'tcx>>>, debug_context: Option>, @@ -122,7 +122,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, llfn: Bx::Function, - mir: &'a mut BodyCache<&'a Body<'tcx>>, + mut mir: BodyCache<&'a Body<'tcx>>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, ) { @@ -132,7 +132,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( debug!("fn_abi: {:?}", fn_abi); let debug_context = - cx.create_function_debug_context(instance, sig, llfn, mir); + cx.create_function_debug_context(instance, sig, llfn, &mir); let mut bx = Bx::new_block(cx, llfn, "start"); @@ -155,11 +155,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } }).collect(); - let (landing_pads, funclets) = create_funclets(mir, &mut bx, &cleanup_kinds, &block_bxs); + let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); let mut fx = FunctionCx { instance, - mir: Some(mir), +// mir: Some(mir), llfn, fn_abi, cx, @@ -174,11 +174,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), }; - let memory_locals = analyze::non_ssa_locals(&mut fx); + let memory_locals = analyze::non_ssa_locals(&mut fx, &mut mir); // Allocate variable and temp allocas fx.locals = { - let args = arg_local_refs(&mut bx, &fx, &memory_locals); + let args = arg_local_refs(&mut bx, &fx, &mir, &memory_locals); let mut allocate_local = |local| { let decl = &mir.local_decls[local]; @@ -232,7 +232,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Codegen the body of each block using reverse postorder for (bb, _) in rpo { visited.insert(bb.index()); - fx.codegen_block(bb); + fx.codegen_block(bb, &mir); } // Remove blocks that haven't been visited, or have no @@ -248,8 +248,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - mir: &'a Body<'tcx>, +fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + mir: &'b Body<'tcx>, bx: &mut Bx, cleanup_kinds: &IndexVec, block_bxs: &IndexVec, @@ -321,16 +321,16 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, fx: &FunctionCx<'a, 'tcx, Bx>, + mir: &Body<'tcx>, memory_locals: &BitSet, ) -> Vec> { - let mir = fx.mir; let mut idx = 0; let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - mir.unwrap().args_iter().enumerate().map(|(arg_index, local)| { - let arg_decl = &mir.unwrap().local_decls[local]; + mir.args_iter().enumerate().map(|(arg_index, local)| { + let arg_decl = &mir.local_decls[local]; - if Some(local) == mir.unwrap().spread_arg { + if Some(local) == mir.spread_arg { // This argument (e.g., the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 310b8aeb4db09..f51af31910a53 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -7,7 +7,7 @@ use crate::glue; use crate::traits::*; use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; -use rustc::mir; +use rustc::mir::{self, Body}; use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size}; @@ -428,12 +428,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_consume( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, place_ref: &mir::PlaceRef<'_, 'tcx> ) -> OperandRef<'tcx, Bx::Value> { debug!("codegen_consume(place_ref={:?})", place_ref); - let ty = self.monomorphized_place_ty(place_ref); + let ty = self.monomorphized_place_ty(place_ref, mir); let layout = bx.cx().layout_of(ty); // ZSTs don't require any actual memory access. @@ -447,12 +448,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // for most places, to consume them we just load them // out from their home - let place = self.codegen_place(bx, place_ref); + let place = self.codegen_place(mir, bx, place_ref); bx.load_operand(place) } pub fn codegen_operand( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, operand: &mir::Operand<'tcx> ) -> OperandRef<'tcx, Bx::Value> { @@ -461,7 +463,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *operand { mir::Operand::Copy(ref place) | mir::Operand::Move(ref place) => { - self.codegen_consume(bx, &place.as_ref()) + self.codegen_consume(mir, bx, &place.as_ref()) } mir::Operand::Constant(ref constant) => { diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 8f3c1de9c6440..82efcf161aabe 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -8,7 +8,7 @@ use crate::traits::*; use rustc::ty::{self, Instance, Ty}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; -use rustc::mir; +use rustc::mir::{self, Body}; use rustc::mir::tcx::PlaceTy; #[derive(Copy, Clone, Debug)] @@ -438,6 +438,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_place( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, place_ref: &mir::PlaceRef<'_, 'tcx> ) -> PlaceRef<'tcx, Bx::Value> { @@ -518,7 +519,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { projection: [proj_base @ .., mir::ProjectionElem::Deref], } => { // Load the pointer from its location. - self.codegen_consume(bx, &mir::PlaceRef { + self.codegen_consume(mir, bx, &mir::PlaceRef { base, projection: proj_base, }).deref(bx.cx()) @@ -528,7 +529,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { projection: [proj_base @ .., elem], } => { // FIXME turn this recursion into iteration - let cg_base = self.codegen_place(bx, &mir::PlaceRef { + let cg_base = self.codegen_place(mir, bx, &mir::PlaceRef { base, projection: proj_base, }); @@ -542,7 +543,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let index = &mir::Operand::Copy( mir::Place::from(*index) ); - let index = self.codegen_operand(bx, index); + let index = self.codegen_operand(mir, bx, index); let llindex = index.immediate(); cg_base.project_index(bx, llindex) } @@ -589,9 +590,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { result } - pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { + pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>, mir: &Body<'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir.unwrap().body(), tcx); + let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, mir, tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index c1519b6106dfc..2b45e3f8d63fe 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -10,7 +10,7 @@ use crate::traits::*; use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; -use rustc::mir; +use rustc::mir::{self, Body}; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; use syntax::symbol::sym; @@ -21,6 +21,7 @@ use std::{u128, i128}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_rvalue( &mut self, + mir: &Body<'tcx>, mut bx: Bx, dest: PlaceRef<'tcx, Bx::Value>, rvalue: &mir::Rvalue<'tcx> @@ -30,7 +31,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *rvalue { mir::Rvalue::Use(ref operand) => { - let cg_operand = self.codegen_operand(&mut bx, operand); + let cg_operand = self.codegen_operand(mir, &mut bx, operand); // FIXME: consider not copying constants through stack. (Fixable by codegen'ing // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?) cg_operand.val.store(&mut bx, dest); @@ -43,7 +44,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if bx.cx().is_backend_scalar_pair(dest.layout) { // Into-coerce of a thin pointer to a fat pointer -- just // use the operand path. - let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue); + let (mut bx, temp) = self.codegen_rvalue_operand(mir, bx, rvalue); temp.val.store(&mut bx, dest); return bx; } @@ -52,7 +53,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // this to be eliminated by MIR building, but // `CoerceUnsized` can be passed by a where-clause, // so the (generic) MIR may not be able to expand it. - let operand = self.codegen_operand(&mut bx, source); + let operand = self.codegen_operand(mir, &mut bx, source); match operand.val { OperandValue::Pair(..) | OperandValue::Immediate(_) => { @@ -81,7 +82,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Repeat(ref elem, count) => { - let cg_elem = self.codegen_operand(&mut bx, elem); + let cg_elem = self.codegen_operand(mir, &mut bx, elem); // Do not generate the loop for zero-sized elements or empty arrays. if dest.layout.is_zst() { @@ -124,7 +125,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => (dest, None) }; for (i, operand) in operands.iter().enumerate() { - let op = self.codegen_operand(&mut bx, operand); + let op = self.codegen_operand(mir, &mut bx, operand); // Do not generate stores and GEPis for zero-sized fields. if !op.layout.is_zst() { let field_index = active_field_index.unwrap_or(i); @@ -136,8 +137,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => { - assert!(self.rvalue_creates_operand(rvalue, DUMMY_SP)); - let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue); + assert!(self.rvalue_creates_operand(rvalue, DUMMY_SP, mir)); + let (mut bx, temp) = self.codegen_rvalue_operand(mir, bx, rvalue); temp.val.store(&mut bx, dest); bx } @@ -146,6 +147,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_rvalue_unsized( &mut self, + mir: &Body<'tcx>, mut bx: Bx, indirect_dest: PlaceRef<'tcx, Bx::Value>, rvalue: &mir::Rvalue<'tcx>, @@ -155,7 +157,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *rvalue { mir::Rvalue::Use(ref operand) => { - let cg_operand = self.codegen_operand(&mut bx, operand); + let cg_operand = self.codegen_operand(mir, &mut bx, operand); cg_operand.val.store_unsized(&mut bx, indirect_dest); bx } @@ -166,18 +168,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_rvalue_operand( &mut self, + mir: &Body<'tcx>, mut bx: Bx, rvalue: &mir::Rvalue<'tcx> ) -> (Bx, OperandRef<'tcx, Bx::Value>) { assert!( - self.rvalue_creates_operand(rvalue, DUMMY_SP), + self.rvalue_creates_operand(rvalue, DUMMY_SP, mir), "cannot codegen {:?} to operand", rvalue, ); match *rvalue { mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => { - let operand = self.codegen_operand(&mut bx, source); + let operand = self.codegen_operand(mir, &mut bx, source); debug!("cast operand is {:?}", operand); let cast = bx.cx().layout_of(self.monomorphize(&mir_cast_ty)); @@ -370,7 +373,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Ref(_, bk, ref place) => { - let cg_place = self.codegen_place(&mut bx, &place.as_ref()); + let cg_place = self.codegen_place(mir, &mut bx, &place.as_ref()); let ty = cg_place.layout.ty; @@ -391,7 +394,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Len(ref place) => { - let size = self.evaluate_array_len(&mut bx, place); + let size = self.evaluate_array_len(mir, &mut bx, place); let operand = OperandRef { val: OperandValue::Immediate(size), layout: bx.cx().layout_of(bx.tcx().types.usize), @@ -400,8 +403,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => { - let lhs = self.codegen_operand(&mut bx, lhs); - let rhs = self.codegen_operand(&mut bx, rhs); + let lhs = self.codegen_operand(mir, &mut bx, lhs); + let rhs = self.codegen_operand(mir, &mut bx, rhs); let llresult = match (lhs.val, rhs.val) { (OperandValue::Pair(lhs_addr, lhs_extra), OperandValue::Pair(rhs_addr, rhs_extra)) => { @@ -426,8 +429,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (bx, operand) } mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => { - let lhs = self.codegen_operand(&mut bx, lhs); - let rhs = self.codegen_operand(&mut bx, rhs); + let lhs = self.codegen_operand(mir, &mut bx, lhs); + let rhs = self.codegen_operand(mir, &mut bx, rhs); let result = self.codegen_scalar_checked_binop(&mut bx, op, lhs.immediate(), rhs.immediate(), lhs.layout.ty); @@ -442,7 +445,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::UnaryOp(op, ref operand) => { - let operand = self.codegen_operand(&mut bx, operand); + let operand = self.codegen_operand(mir, &mut bx, operand); let lloperand = operand.immediate(); let is_float = operand.layout.ty.is_floating_point(); let llval = match op { @@ -460,8 +463,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(self.mir.unwrap().body(), bx.tcx()); - let discr = self.codegen_place(&mut bx, &place.as_ref()) + let discr_ty = rvalue.ty(mir, bx.tcx()); + let discr = self.codegen_place(mir, &mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { val: OperandValue::Immediate(discr), @@ -506,14 +509,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (bx, operand) } mir::Rvalue::Use(ref operand) => { - let operand = self.codegen_operand(&mut bx, operand); + let operand = self.codegen_operand(mir, &mut bx, operand); (bx, operand) } mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(self.mir.unwrap().body(), self.cx.tcx()); + let ty = rvalue.ty(mir, self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -525,6 +528,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn evaluate_array_len( &mut self, + mir: &Body<'tcx>, bx: &mut Bx, place: &mir::Place<'tcx>, ) -> Bx::Value { @@ -539,7 +543,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } // use common size calculation for non zero-sized types - let cg_value = self.codegen_place(bx, &place.as_ref()); + let cg_value = self.codegen_place(mir, bx, &place.as_ref()); cg_value.len(bx.cx()) } @@ -696,7 +700,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { + pub fn rvalue_creates_operand( + &self, + rvalue: &mir::Rvalue<'tcx>, + span: Span, + mir: &Body<'tcx> + ) -> bool { match *rvalue { mir::Rvalue::Ref(..) | mir::Rvalue::Len(..) | @@ -710,7 +719,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(self.mir.unwrap().body(), self.cx.tcx()); + let ty = rvalue.ty(mir, self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 0b82edea15790..cee5f4f9bdba6 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -1,4 +1,4 @@ -use rustc::mir; +use rustc::mir::{self, Body}; use crate::traits::BuilderMethods; use super::FunctionCx; @@ -11,24 +11,25 @@ use rustc_error_codes::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_statement( &mut self, + mir: &Body<'tcx>, mut bx: Bx, statement: &mir::Statement<'tcx> ) -> Bx { debug!("codegen_statement(statement={:?})", statement); - self.set_debug_loc(&mut bx, statement.source_info); + self.set_debug_loc(&mut bx, statement.source_info, mir); match statement.kind { mir::StatementKind::Assign(box(ref place, ref rvalue)) => { if let Some(index) = place.as_local() { match self.locals[index] { LocalRef::Place(cg_dest) => { - self.codegen_rvalue(bx, cg_dest, rvalue) + self.codegen_rvalue(mir, bx, cg_dest, rvalue) } LocalRef::UnsizedPlace(cg_indirect_dest) => { - self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue) + self.codegen_rvalue_unsized(mir, bx, cg_indirect_dest, rvalue) } LocalRef::Operand(None) => { - let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue); + let (mut bx, operand) = self.codegen_rvalue_operand(mir, bx, rvalue); self.locals[index] = LocalRef::Operand(Some(operand)); self.debug_introduce_local(&mut bx, index); bx @@ -42,16 +43,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // If the type is zero-sized, it's already been set here, // but we still need to make sure we codegen the operand - self.codegen_rvalue_operand(bx, rvalue).0 + self.codegen_rvalue_operand(mir, bx, rvalue).0 } } } else { - let cg_dest = self.codegen_place(&mut bx, &place.as_ref()); - self.codegen_rvalue(bx, cg_dest, rvalue) + let cg_dest = self.codegen_place(mir, &mut bx, &place.as_ref()); + self.codegen_rvalue(mir, bx, cg_dest, rvalue) } } mir::StatementKind::SetDiscriminant{box ref place, variant_index} => { - self.codegen_place(&mut bx, &place.as_ref()) + self.codegen_place(mir, &mut bx, &place.as_ref()) .codegen_set_discr(&mut bx, variant_index); bx } @@ -73,12 +74,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::StatementKind::InlineAsm(ref asm) => { let outputs = asm.outputs.iter().map(|output| { - self.codegen_place(&mut bx, &output.as_ref()) + self.codegen_place(mir, &mut bx, &output.as_ref()) }).collect(); let input_vals = asm.inputs.iter() .fold(Vec::with_capacity(asm.inputs.len()), |mut acc, (span, input)| { - let op = self.codegen_operand(&mut bx, input); + let op = self.codegen_operand(mir, &mut bx, input); if let OperandValue::Immediate(_) = op.val { acc.push(op.immediate()); } else { From 3d68f5f3e775b5854c40e1ad1433a8a7c8c53e1f Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 14 Oct 2019 00:46:56 -0400 Subject: [PATCH 17/47] Improved BodyCache body impl so it only returns a sharable ref, add new body_mut method, fix visit macros, simplify usage in codegen_ssa analyzer --- src/librustc/mir/cache.rs | 14 ++++++++++---- src/librustc/mir/visit.rs | 8 ++++++-- src/librustc_codegen_ssa/mir/analyze.rs | 13 +++++++------ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index e218931b74916..103b24ecf6169 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> { } #[inline] - pub fn body(&self) -> &Body<'tcx> { + pub fn body(&self) -> &'a Body<'tcx> { self.body } @@ -149,7 +149,8 @@ impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> { impl<'a, 'tcx> Deref for BodyCache<&'a Body<'tcx>> { type Target = Body<'tcx>; - fn deref(&self) -> &Body<'tcx> { + + fn deref(&self) -> &Self::Target { self.body } } @@ -209,7 +210,12 @@ impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for BodyCache<&'a Body<'tcx>> { impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> { #[inline] - pub fn body(&mut self) -> &mut Body<'tcx> { + pub fn body(&self) -> &Body<'tcx> { + self.body + } + + #[inline] + pub fn body_mut(&mut self) -> &mut Body<'tcx> { self.body } @@ -227,7 +233,7 @@ impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> { impl<'a, 'tcx> Deref for BodyCache<&'a mut Body<'tcx>> { type Target = Body<'tcx>; - fn deref(&self) -> &Body<'tcx> { + fn deref(&self) -> &Self::Target { self.body } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 5803663bbecdd..aa3aeb36e063e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -247,8 +247,12 @@ macro_rules! make_mir_visitor { &mut self, body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>> ) { + macro_rules! body { + (mut) => (body_cache.body_mut()); + () => (body_cache.body()); + } let span = body_cache.body().span; - if let Some(yield_ty) = &$($mutability)? body_cache.body().yield_ty { + if let Some(yield_ty) = &$($mutability)? body!($($mutability)?).yield_ty { self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE, @@ -266,7 +270,7 @@ macro_rules! make_mir_visitor { self.visit_basic_block_data(bb, data); } - let body = body_cache.body(); + let body = body!($($mutability)?); for scope in &$($mutability)? body.source_scopes { self.visit_source_scope_data(scope); } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 68d5eec9b255e..2f45bf0ae74d1 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -4,7 +4,7 @@ use rustc_index::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::vec::{Idx, IndexVec}; -use rustc::mir::{self, BasicBlock, Body, BodyCache, Location, TerminatorKind}; +use rustc::mir::{self, Body, BodyCache, Location, TerminatorKind}; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext, NonUseContext, }; @@ -20,8 +20,7 @@ pub fn non_ssa_locals<'b, 'a: 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &mut FunctionCx<'a, 'tcx, Bx>, mir: &'b mut BodyCache<&'a Body<'tcx>>, ) -> BitSet { - let dominators = mir.dominators(); - let mut analyzer = LocalAnalyzer::new(fx, mir, dominators); + let mut analyzer = LocalAnalyzer::new(fx, mir); analyzer.visit_body(mir); @@ -68,13 +67,15 @@ struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { first_assignment: IndexVec, } -impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>, mir: &'b Body<'tcx>, dominators: Dominators) -> Self { +impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { + fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>, mir: &'c mut BodyCache<&'b Body<'tcx>>) -> Self { let invalid_location = mir::BasicBlock::new(mir.basic_blocks().len()).start_location(); + let dominators = mir.dominators(); + let body = mir.body(); let mut analyzer = LocalAnalyzer { fx, - mir, + mir: body, dominators, non_ssa_locals: BitSet::new_empty(mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &mir.local_decls) From 16952cce01578e935aff02d12ab2d95821d7aed2 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 14 Oct 2019 01:12:48 -0400 Subject: [PATCH 18/47] Add Body back as field of FunctionCx, but under a different lifetime --- src/librustc_codegen_ssa/mir/analyze.rs | 25 ++++++------ src/librustc_codegen_ssa/mir/block.rs | 46 +++++++++++------------ src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 12 +++--- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 4 +- src/librustc_codegen_ssa/mir/statement.rs | 2 +- 8 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 2f45bf0ae74d1..69e26cf3b43a1 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -16,9 +16,9 @@ use syntax_pos::DUMMY_SP; use super::FunctionCx; use crate::traits::*; -pub fn non_ssa_locals<'b, 'a: 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - fx: &mut FunctionCx<'a, 'tcx, Bx>, - mir: &'b mut BodyCache<&'a Body<'tcx>>, +pub fn non_ssa_locals<'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + fx: &mut FunctionCx<'a, 'b, 'tcx, Bx>, + mir: &'c mut BodyCache<&'b Body<'tcx>>, ) -> BitSet { let mut analyzer = LocalAnalyzer::new(fx, mir); @@ -58,8 +58,7 @@ pub fn non_ssa_locals<'b, 'a: 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { - fx: &'mir FunctionCx<'a, 'tcx, Bx>, - mir: &'b Body<'tcx>, + fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>, dominators: Dominators, non_ssa_locals: BitSet, // The location of the first visited direct assignment to each @@ -68,14 +67,12 @@ struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { } impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>, mir: &'c mut BodyCache<&'b Body<'tcx>>) -> Self { + fn new(fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>, mir: &'c mut BodyCache<&'b Body<'tcx>>) -> Self { let invalid_location = mir::BasicBlock::new(mir.basic_blocks().len()).start_location(); let dominators = mir.dominators(); - let body = mir.body(); let mut analyzer = LocalAnalyzer { fx, - mir: body, dominators, non_ssa_locals: BitSet::new_empty(mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &mir.local_decls) @@ -91,7 +88,7 @@ impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, ' fn first_assignment(&self, local: mir::Local) -> Option { let location = self.first_assignment[local]; - if location.block.index() < self.mir.basic_blocks().len() { + if location.block.index() < self.fx.mir.basic_blocks().len() { Some(location) } else { None @@ -134,7 +131,7 @@ impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, ' }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, self.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. @@ -143,7 +140,7 @@ impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, ' .ty; let elem_ty = self.fx.monomorphize(&elem_ty); let span = if let mir::PlaceBase::Local(index) = place_ref.base { - self.mir.local_decls[*index].source_info.span + self.fx.mir.local_decls[*index].source_info.span } else { DUMMY_SP }; @@ -247,8 +244,8 @@ impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> if let Some(index) = place.as_local() { self.assign(index, location); - let decl_span = self.mir.local_decls[index].source_info.span; - if !self.fx.rvalue_creates_operand(rvalue, decl_span, self.mir) { + let decl_span = self.fx.mir.local_decls[index].source_info.span; + if !self.fx.rvalue_creates_operand(rvalue, decl_span, self.fx.mir) { self.not_ssa(index); } } else { @@ -352,7 +349,7 @@ impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } PlaceContext::MutatingUse(MutatingUseContext::Drop) => { - let ty = self.mir.local_decls[local].ty; + let ty = self.fx.mir.local_decls[local].ty; let ty = self.fx.monomorphize(&ty); // Only need the place if we're actually dropping it. diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index e0be162984aaf..ba86576dd32b4 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -33,19 +33,19 @@ struct TerminatorCodegenHelper<'a, 'tcx> { impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Returns the associated funclet from `FunctionCx::funclets` for the /// `funclet_bb` member if it is not `None`. - fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - ) -> Option<&'c Bx::Funclet> { + fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, + ) -> Option<&'d Bx::Funclet> { match self.funclet_bb { Some(funcl) => fx.funclets[funcl].as_ref(), None => None, } } - fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( + fn lltarget<'b, 'c, 'd, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, mir: &Body<'tcx>, target: mir::BasicBlock ) -> (Bx::BasicBlock, bool) { @@ -64,9 +64,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } /// Create a basic block. - fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn llblock<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, mir: &Body<'tcx>, target: mir::BasicBlock ) -> Bx::BasicBlock { @@ -85,9 +85,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } } - fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet_br<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, mir: &Body<'tcx>, bx: &mut Bx, target: mir::BasicBlock, @@ -104,9 +104,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional /// return destination `destination` and the cleanup function `cleanup`. - fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn do_call<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, mir: &Body<'tcx>, bx: &mut Bx, fn_abi: FnAbi<'tcx, Ty<'tcx>>, @@ -175,11 +175,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } /// Codegen implementations for some terminator variants. -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { /// Generates code for a `Resume` terminator. - fn codegen_resume_terminator<'b>( + fn codegen_resume_terminator<'c>( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'c, 'tcx>, mut bx: Bx, ) { if let Some(funclet) = helper.funclet(self) { @@ -205,9 +205,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - fn codegen_switchint_terminator<'b>( + fn codegen_switchint_terminator<'c>( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'c, 'tcx>, mir: &Body<'tcx>, mut bx: Bx, discr: &mir::Operand<'tcx>, @@ -321,9 +321,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } - fn codegen_drop_terminator<'b>( + fn codegen_drop_terminator<'c>( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'c, 'tcx>, mir: &Body<'tcx>, mut bx: Bx, location: &mir::Place<'tcx>, @@ -373,9 +373,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { unwind); } - fn codegen_assert_terminator<'b>( + fn codegen_assert_terminator<'c>( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'c, 'tcx>, mir: &Body<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, @@ -453,9 +453,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper.do_call(self, mir, &mut bx, fn_abi, llfn, &args, None, cleanup); } - fn codegen_call_terminator<'b>( + fn codegen_call_terminator<'c>( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'c, 'tcx>, mir: &Body<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, @@ -794,7 +794,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_block( &mut self, bb: mir::BasicBlock, diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 27891be6b82c5..71d0abf2bff80 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -9,7 +9,7 @@ use crate::mir::operand::OperandRef; use super::FunctionCx; -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn eval_mir_constant_to_operand( &mut self, bx: &mut Bx, diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index cfc5a468f95d3..7a3cf699f58a4 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -18,10 +18,10 @@ use rustc::mir::traversal; use self::operand::{OperandRef, OperandValue}; /// Master context for codegenning from MIR. -pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { +pub struct FunctionCx<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, -// mir: Option<&'a mut BodyCache<&'a mir::Body<'tcx>>>, + mir: &'b mir::Body<'tcx>, debug_context: Option>, @@ -79,7 +79,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { per_local_var_debug_info: Option>>>, } -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn monomorphize(&self, value: &T) -> T where T: TypeFoldable<'tcx> { @@ -159,7 +159,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut fx = FunctionCx { instance, -// mir: Some(mir), + mir: mir.body(), llfn, fn_abi, cx, @@ -318,9 +318,9 @@ fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// Produces, for each argument, a `Value` pointing at the /// argument's value. As arguments are places, these are always /// indirect. -fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +fn arg_local_refs<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, - fx: &FunctionCx<'a, 'tcx, Bx>, + fx: &FunctionCx<'a, 'b, 'tcx, Bx>, mir: &Body<'tcx>, memory_locals: &BitSet, ) -> Vec> { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index f51af31910a53..9c4bf14c833d5 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -377,7 +377,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { } } -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn maybe_codegen_consume_direct( &mut self, bx: &mut Bx, diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 82efcf161aabe..50c7fabc22537 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -435,7 +435,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } } -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_place( &mut self, mir: &Body<'tcx>, diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 2b45e3f8d63fe..8a296b29de7a0 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -18,7 +18,7 @@ use syntax::source_map::{DUMMY_SP, Span}; use std::{u128, i128}; -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_rvalue( &mut self, mir: &Body<'tcx>, @@ -699,7 +699,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn rvalue_creates_operand( &self, rvalue: &mir::Rvalue<'tcx>, diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index cee5f4f9bdba6..05c88a316ff37 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -8,7 +8,7 @@ use crate::traits::*; use rustc_error_codes::*; -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_statement( &mut self, mir: &Body<'tcx>, From 66279d12f9cad1d47e4d6ed458dcbb7505b65b55 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 14 Oct 2019 01:38:38 -0400 Subject: [PATCH 19/47] Revert back to using FunctionCx's Body --- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 153 ++++++++++------------ src/librustc_codegen_ssa/mir/mod.rs | 11 +- src/librustc_codegen_ssa/mir/operand.rs | 10 +- src/librustc_codegen_ssa/mir/place.rs | 13 +- src/librustc_codegen_ssa/mir/rvalue.rs | 53 ++++---- src/librustc_codegen_ssa/mir/statement.rs | 23 ++-- 7 files changed, 118 insertions(+), 147 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 69e26cf3b43a1..171e3c840fbf7 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -245,7 +245,7 @@ impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> if let Some(index) = place.as_local() { self.assign(index, location); let decl_span = self.fx.mir.local_decls[index].source_info.span; - if !self.fx.rvalue_creates_operand(rvalue, decl_span, self.fx.mir) { + if !self.fx.rvalue_creates_operand(rvalue, decl_span) { self.not_ssa(index); } } else { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ba86576dd32b4..53bffc794d770 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -2,7 +2,7 @@ use rustc_index::vec::Idx; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, Body, PlaceBase, Static, StaticKind}; +use rustc::mir::{self, PlaceBase, Static, StaticKind}; use rustc::mir::interpret::PanicInfo; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::abi::Abi; @@ -46,7 +46,6 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn lltarget<'b, 'c, 'd, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, - mir: &Body<'tcx>, target: mir::BasicBlock ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; @@ -57,9 +56,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => (lltarget, false), // jump *into* cleanup - need a landing pad if GNU - (None, Some(_)) => (fx.landing_pad_to(target, mir), false), + (None, Some(_)) => (fx.landing_pad_to(target), false), (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), - (Some(_), Some(_)) => (fx.landing_pad_to(target, mir), true), + (Some(_), Some(_)) => (fx.landing_pad_to(target), true), } } @@ -67,10 +66,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn llblock<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, - mir: &Body<'tcx>, target: mir::BasicBlock ) -> Bx::BasicBlock { - let (lltarget, is_cleanupret) = self.lltarget(fx, mir, target); + let (lltarget, is_cleanupret) = self.lltarget(fx, target); if is_cleanupret { // MSVC cross-funclet jump - need a trampoline @@ -88,11 +86,10 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn funclet_br<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, - mir: &Body<'tcx>, bx: &mut Bx, target: mir::BasicBlock, ) { - let (lltarget, is_cleanupret) = self.lltarget(fx, mir, target); + let (lltarget, is_cleanupret) = self.lltarget(fx, target); if is_cleanupret { // micro-optimization: generate a `ret` rather than a jump // to a trampoline. @@ -107,7 +104,6 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn do_call<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, - mir: &Body<'tcx>, bx: &mut Bx, fn_abi: FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, @@ -124,19 +120,19 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { let invokeret = bx.invoke(fn_ptr, &llargs, ret_bx, - self.llblock(fx, mir, cleanup), + self.llblock(fx, cleanup), self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, invokeret); if let Some((ret_dest, target)) = destination { let mut ret_bx = fx.build_block(target); - fx.set_debug_loc(&mut ret_bx, self.terminator.source_info, mir); + fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); } } else { let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, llret); - if mir[*self.bb].is_cleanup { + if fx.mir[*self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested // struct, there are "symmetry" issues that cause @@ -146,7 +142,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { if let Some((ret_dest, target)) = destination { fx.store_return(bx, ret_dest, &fn_abi.ret, llret); - self.funclet_br(fx, mir, bx, target); + self.funclet_br(fx, bx, target); } else { bx.unreachable(); } @@ -208,20 +204,19 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn codegen_switchint_terminator<'c>( &mut self, helper: TerminatorCodegenHelper<'c, 'tcx>, - mir: &Body<'tcx>, mut bx: Bx, discr: &mir::Operand<'tcx>, switch_ty: Ty<'tcx>, values: &Cow<'tcx, [u128]>, targets: &Vec, ) { - let discr = self.codegen_operand(mir, &mut bx, &discr); + let discr = self.codegen_operand(&mut bx, &discr); if targets.len() == 2 { // If there are two targets, emit br instead of switch - let lltrue = helper.llblock(self, mir, targets[0]); - let llfalse = helper.llblock(self, mir, targets[1]); + let lltrue = helper.llblock(self, targets[0]); + let llfalse = helper.llblock(self, targets[1]); if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool if let [0] = values[..] { bx.cond_br(discr.immediate(), llfalse, lltrue); @@ -243,15 +238,15 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), - helper.llblock(self, mir, *otherwise), + helper.llblock(self, *otherwise), values.iter().zip(targets).map(|(&value, target)| { - (value, helper.llblock(self, mir, *target)) + (value, helper.llblock(self, *target)) }) ); } } - fn codegen_return_terminator(&mut self, mir: &Body<'tcx>, mut bx: Bx) { + fn codegen_return_terminator(&mut self, mut bx: Bx) { // Call `va_end` if this is the definition of a C-variadic function. if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. @@ -278,7 +273,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { PassMode::Direct(_) | PassMode::Pair(..) => { let op = - self.codegen_consume(mir, &mut bx, &mir::Place::return_place().as_ref()); + self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); if let Ref(llval, _, align) = op.val { bx.load(llval, align) } else { @@ -324,24 +319,23 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn codegen_drop_terminator<'c>( &mut self, helper: TerminatorCodegenHelper<'c, 'tcx>, - mir: &Body<'tcx>, mut bx: Bx, location: &mir::Place<'tcx>, target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(mir, bx.tcx()).ty; + let ty = location.ty(self.mir, bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. - helper.maybe_sideeffect(mir, &mut bx, &[target]); - helper.funclet_br(self, mir, &mut bx, target); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); return } - let place = self.codegen_place(mir, &mut bx, &location.as_ref()); + let place = self.codegen_place(&mut bx, &location.as_ref()); let (args1, args2); let mut args = if let Some(llextra) = place.llextra { args2 = [place.llval, llextra]; @@ -367,7 +361,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { FnAbi::of_instance(&bx, drop_fn)) } }; - helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); @@ -376,7 +370,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn codegen_assert_terminator<'c>( &mut self, helper: TerminatorCodegenHelper<'c, 'tcx>, - mir: &Body<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, cond: &mir::Operand<'tcx>, @@ -386,7 +379,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { cleanup: Option, ) { let span = terminator.source_info.span; - let cond = self.codegen_operand(mir, &mut bx, cond).immediate(); + let cond = self.codegen_operand(&mut bx, cond).immediate(); let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1); // This case can currently arise only from functions marked @@ -404,8 +397,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Don't codegen the panic block if success if known. if const_cond == Some(expected) { - helper.maybe_sideeffect(mir, &mut bx, &[target]); - helper.funclet_br(self, mir, &mut bx, target); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); return; } @@ -413,9 +406,9 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let cond = bx.expect(cond, expected); // Create the failure block and the conditional branch to it. - let lltarget = helper.llblock(self, mir, target); + let lltarget = helper.llblock(self, target); let panic_block = self.new_block("panic"); - helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -424,7 +417,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // After this point, bx is the block for the call to panic. bx = panic_block; - self.set_debug_loc(&mut bx, terminator.source_info, mir); + self.set_debug_loc(&mut bx, terminator.source_info); // Get the location information. let location = self.get_caller_location(&mut bx, span).immediate(); @@ -432,8 +425,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Put together the arguments to the panic entry point. let (lang_item, args) = match msg { PanicInfo::BoundsCheck { ref len, ref index } => { - let len = self.codegen_operand(mir, &mut bx, len).immediate(); - let index = self.codegen_operand(mir, &mut bx, index).immediate(); + let len = self.codegen_operand(&mut bx, len).immediate(); + let index = self.codegen_operand(&mut bx, index).immediate(); (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) } _ => { @@ -450,13 +443,12 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. - helper.do_call(self, mir, &mut bx, fn_abi, llfn, &args, None, cleanup); + helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); } fn codegen_call_terminator<'c>( &mut self, helper: TerminatorCodegenHelper<'c, 'tcx>, - mir: &Body<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, @@ -466,7 +458,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { ) { let span = terminator.source_info.span; // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. - let callee = self.codegen_operand(mir, &mut bx, func); + let callee = self.codegen_operand(&mut bx, func); let (instance, mut llfn) = match callee.layout.ty.kind { ty::FnDef(def_id, substs) => { @@ -500,9 +492,9 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { if intrinsic == Some("transmute") { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; - self.codegen_transmute(mir, &mut bx, &args[0], dest); - helper.maybe_sideeffect(mir, &mut bx, &[target]); - helper.funclet_br(self, mir, &mut bx, target); + self.codegen_transmute(&mut bx, &args[0], dest); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); } else { // If we are trying to transmute to an uninhabited type, // it is likely there is no allotted destination. In fact, @@ -518,7 +510,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(mir, bx.tcx()); + let op_ty = op_arg.ty(self.mir, bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); @@ -529,8 +521,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { Some(ty::InstanceDef::DropGlue(_, None)) => { // Empty drop glue; a no-op. let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(mir, &mut bx, &[target]); - helper.funclet_br(self, mir, &mut bx, target); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); return; } _ => FnAbi::new(&bx, sig, &extra_args) @@ -566,7 +558,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Codegen the actual panic invoke/call. helper.do_call( self, - mir, &mut bx, fn_abi, llfn, @@ -590,8 +581,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Prepare the return value destination let ret_dest = if let Some((ref dest, _)) = *destination { let is_intrinsic = intrinsic.is_some(); - self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, - is_intrinsic, mir) + self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, is_intrinsic) } else { ReturnDest::Nothing }; @@ -680,7 +670,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } } - self.codegen_operand(mir, &mut bx, arg) + self.codegen_operand(&mut bx, arg) }).collect(); @@ -692,8 +682,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } if let Some((_, target)) = *destination { - helper.maybe_sideeffect(mir, &mut bx, &[target]); - helper.funclet_br(self, mir, &mut bx, target); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); } else { bx.unreachable(); } @@ -710,7 +700,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { }; 'make_args: for (i, arg) in first_args.iter().enumerate() { - let mut op = self.codegen_operand(mir, &mut bx, arg); + let mut op = self.codegen_operand(&mut bx, arg); if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { if let Pair(..) = op.val { @@ -775,7 +765,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]); } if let Some(tup) = untuple { - self.codegen_arguments_untupled(mir, &mut bx, tup, &mut llargs, + self.codegen_arguments_untupled(&mut bx, tup, &mut llargs, &fn_abi.args[first_args.len()..]) } @@ -786,7 +776,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { }; if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(mir, &mut bx, &[*target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); } helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), @@ -798,18 +788,17 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_block( &mut self, bb: mir::BasicBlock, - mir: &Body<'tcx>, ) { let mut bx = self.build_block(bb); - let data = &mir[bb]; + let data = &self.mir[bb]; debug!("codegen_block({:?}={:?})", bb, data); for statement in &data.statements { - bx = self.codegen_statement(mir, bx, statement); + bx = self.codegen_statement(bx, statement); } - self.codegen_terminator(bx, bb, data.terminator(), mir); + self.codegen_terminator(bx, bb, data.terminator()); } fn codegen_terminator( @@ -817,7 +806,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { mut bx: Bx, bb: mir::BasicBlock, terminator: &mir::Terminator<'tcx>, - mir: &Body<'tcx> ) { debug!("codegen_terminator: {:?}", terminator); @@ -827,7 +815,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { bb: &bb, terminator, funclet_bb }; - self.set_debug_loc(&mut bx, terminator.source_info, mir); + self.set_debug_loc(&mut bx, terminator.source_info); match terminator.kind { mir::TerminatorKind::Resume => { self.codegen_resume_terminator(helper, bx) @@ -839,19 +827,18 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - helper.maybe_sideeffect(mir, &mut bx, &[target]); - helper.funclet_br(self, mir, &mut bx, target); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); } mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { - self.codegen_switchint_terminator(helper, mir, bx, discr, switch_ty, - values, targets); + self.codegen_switchint_terminator(helper, bx, discr, switch_ty, values, targets); } mir::TerminatorKind::Return => { - self.codegen_return_terminator(mir, bx); + self.codegen_return_terminator(bx); } mir::TerminatorKind::Unreachable => { @@ -859,11 +846,11 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::TerminatorKind::Drop { ref location, target, unwind } => { - self.codegen_drop_terminator(helper, mir, bx, location, target, unwind); + self.codegen_drop_terminator(helper, bx, location, target, unwind); } mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => { - self.codegen_assert_terminator(helper, mir, bx, terminator, cond, + self.codegen_assert_terminator(helper, bx, terminator, cond, expected, msg, target, cleanup); } @@ -878,7 +865,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { cleanup, from_hir_call: _ } => { - self.codegen_call_terminator(helper, mir, bx, terminator, func, + self.codegen_call_terminator(helper, bx, terminator, func, args, destination, cleanup); } mir::TerminatorKind::GeneratorDrop | @@ -983,13 +970,12 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn codegen_arguments_untupled( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, operand: &mir::Operand<'tcx>, llargs: &mut Vec, args: &[ArgAbi<'tcx, Ty<'tcx>>] ) { - let tuple = self.codegen_operand(mir, bx, operand); + let tuple = self.codegen_operand(bx, operand); // Handle both by-ref and immediate tuples. if let Ref(llval, None, align) = tuple.val { @@ -1049,14 +1035,13 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn landing_pad_to( &mut self, target_bb: mir::BasicBlock, - mir: &Body<'tcx> ) -> Bx::BasicBlock { if let Some(block) = self.landing_pads[target_bb] { return block; } let block = self.blocks[target_bb]; - let landing_pad = self.landing_pad_uncached(block, mir); + let landing_pad = self.landing_pad_uncached(block); self.landing_pads[target_bb] = Some(landing_pad); landing_pad } @@ -1064,10 +1049,9 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn landing_pad_uncached( &mut self, target_bb: Bx::BasicBlock, - mir: &Body<'tcx> ) -> Bx::BasicBlock { if base::wants_msvc_seh(self.cx.sess()) { - span_bug!(mir.span, "landing pad was not inserted?") + span_bug!(self.mir.span, "landing pad was not inserted?") } let mut bx = self.new_block("cleanup"); @@ -1120,7 +1104,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { dest: &mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, is_intrinsic: bool, - mir: &Body<'tcx> ) -> ReturnDest<'tcx, Bx::Value> { // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { @@ -1156,7 +1139,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } } } else { - self.codegen_place(mir, bx, &mir::PlaceRef { + self.codegen_place(bx, &mir::PlaceRef { base: &dest.base, projection: &dest.projection, }) @@ -1169,7 +1152,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // // If someone changes that, please update this code path // to create a temporary. - span_bug!(mir.span, "can't directly store to unaligned value"); + span_bug!(self.mir.span, "can't directly store to unaligned value"); } llargs.push(dest.llval); ReturnDest::Nothing @@ -1180,21 +1163,20 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn codegen_transmute( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, src: &mir::Operand<'tcx>, dst: &mir::Place<'tcx> ) { if let Some(index) = dst.as_local() { match self.locals[index] { - LocalRef::Place(place) => self.codegen_transmute_into(mir, bx, src, place), + LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), LocalRef::Operand(None) => { - let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref(), mir)); + let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); assert!(!dst_layout.ty.has_erasable_regions()); let place = PlaceRef::alloca(bx, dst_layout); place.storage_live(bx); - self.codegen_transmute_into(mir, bx, src, place); + self.codegen_transmute_into(bx, src, place); let op = bx.load_operand(place); place.storage_dead(bx); self.locals[index] = LocalRef::Operand(Some(op)); @@ -1205,19 +1187,18 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } } } else { - let dst = self.codegen_place(mir, bx, &dst.as_ref()); - self.codegen_transmute_into(mir, bx, src, dst); + let dst = self.codegen_place(bx, &dst.as_ref()); + self.codegen_transmute_into(bx, src, dst); } } fn codegen_transmute_into( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, src: &mir::Operand<'tcx>, dst: PlaceRef<'tcx, Bx::Value> ) { - let src = self.codegen_operand(mir, bx, src); + let src = self.codegen_operand(bx, src); let llty = bx.backend_type(src.layout); let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); let align = src.layout.align.abi.min(dst.align); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 7a3cf699f58a4..64129f4b5e48d 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -178,7 +178,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Allocate variable and temp allocas fx.locals = { - let args = arg_local_refs(&mut bx, &fx, &mir, &memory_locals); + let args = arg_local_refs(&mut bx, &fx, &memory_locals); let mut allocate_local = |local| { let decl = &mir.local_decls[local]; @@ -232,7 +232,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Codegen the body of each block using reverse postorder for (bb, _) in rpo { visited.insert(bb.index()); - fx.codegen_block(bb, &mir); + fx.codegen_block(bb); } // Remove blocks that haven't been visited, or have no @@ -321,16 +321,15 @@ fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fn arg_local_refs<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, fx: &FunctionCx<'a, 'b, 'tcx, Bx>, - mir: &Body<'tcx>, memory_locals: &BitSet, ) -> Vec> { let mut idx = 0; let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - mir.args_iter().enumerate().map(|(arg_index, local)| { - let arg_decl = &mir.local_decls[local]; + fx.mir.args_iter().enumerate().map(|(arg_index, local)| { + let arg_decl = &fx.mir.local_decls[local]; - if Some(local) == mir.spread_arg { + if Some(local) == fx.mir.spread_arg { // This argument (e.g., the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 9c4bf14c833d5..947dc2df87d20 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -7,7 +7,7 @@ use crate::glue; use crate::traits::*; use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; -use rustc::mir::{self, Body}; +use rustc::mir; use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size}; @@ -428,13 +428,12 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_consume( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, place_ref: &mir::PlaceRef<'_, 'tcx> ) -> OperandRef<'tcx, Bx::Value> { debug!("codegen_consume(place_ref={:?})", place_ref); - let ty = self.monomorphized_place_ty(place_ref, mir); + let ty = self.monomorphized_place_ty(place_ref); let layout = bx.cx().layout_of(ty); // ZSTs don't require any actual memory access. @@ -448,13 +447,12 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // for most places, to consume them we just load them // out from their home - let place = self.codegen_place(mir, bx, place_ref); + let place = self.codegen_place(bx, place_ref); bx.load_operand(place) } pub fn codegen_operand( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, operand: &mir::Operand<'tcx> ) -> OperandRef<'tcx, Bx::Value> { @@ -463,7 +461,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { match *operand { mir::Operand::Copy(ref place) | mir::Operand::Move(ref place) => { - self.codegen_consume(mir, bx, &place.as_ref()) + self.codegen_consume(bx, &place.as_ref()) } mir::Operand::Constant(ref constant) => { diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 50c7fabc22537..245998bd87d9b 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -8,7 +8,7 @@ use crate::traits::*; use rustc::ty::{self, Instance, Ty}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; -use rustc::mir::{self, Body}; +use rustc::mir; use rustc::mir::tcx::PlaceTy; #[derive(Copy, Clone, Debug)] @@ -438,7 +438,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_place( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, place_ref: &mir::PlaceRef<'_, 'tcx> ) -> PlaceRef<'tcx, Bx::Value> { @@ -519,7 +518,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { projection: [proj_base @ .., mir::ProjectionElem::Deref], } => { // Load the pointer from its location. - self.codegen_consume(mir, bx, &mir::PlaceRef { + self.codegen_consume(bx, &mir::PlaceRef { base, projection: proj_base, }).deref(bx.cx()) @@ -529,7 +528,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { projection: [proj_base @ .., elem], } => { // FIXME turn this recursion into iteration - let cg_base = self.codegen_place(mir, bx, &mir::PlaceRef { + let cg_base = self.codegen_place(bx, &mir::PlaceRef { base, projection: proj_base, }); @@ -543,7 +542,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let index = &mir::Operand::Copy( mir::Place::from(*index) ); - let index = self.codegen_operand(mir, bx, index); + let index = self.codegen_operand(bx, index); let llindex = index.immediate(); cg_base.project_index(bx, llindex) } @@ -590,9 +589,9 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { result } - pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>, mir: &Body<'tcx>) -> Ty<'tcx> { + pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, mir, tcx); + let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir, tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 8a296b29de7a0..5180f4376a67e 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -10,7 +10,7 @@ use crate::traits::*; use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; -use rustc::mir::{self, Body}; +use rustc::mir; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; use syntax::symbol::sym; @@ -21,7 +21,6 @@ use std::{u128, i128}; impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_rvalue( &mut self, - mir: &Body<'tcx>, mut bx: Bx, dest: PlaceRef<'tcx, Bx::Value>, rvalue: &mir::Rvalue<'tcx> @@ -31,7 +30,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { match *rvalue { mir::Rvalue::Use(ref operand) => { - let cg_operand = self.codegen_operand(mir, &mut bx, operand); + let cg_operand = self.codegen_operand(&mut bx, operand); // FIXME: consider not copying constants through stack. (Fixable by codegen'ing // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?) cg_operand.val.store(&mut bx, dest); @@ -44,7 +43,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { if bx.cx().is_backend_scalar_pair(dest.layout) { // Into-coerce of a thin pointer to a fat pointer -- just // use the operand path. - let (mut bx, temp) = self.codegen_rvalue_operand(mir, bx, rvalue); + let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue); temp.val.store(&mut bx, dest); return bx; } @@ -53,7 +52,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // this to be eliminated by MIR building, but // `CoerceUnsized` can be passed by a where-clause, // so the (generic) MIR may not be able to expand it. - let operand = self.codegen_operand(mir, &mut bx, source); + let operand = self.codegen_operand(&mut bx, source); match operand.val { OperandValue::Pair(..) | OperandValue::Immediate(_) => { @@ -82,7 +81,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::Repeat(ref elem, count) => { - let cg_elem = self.codegen_operand(mir, &mut bx, elem); + let cg_elem = self.codegen_operand(&mut bx, elem); // Do not generate the loop for zero-sized elements or empty arrays. if dest.layout.is_zst() { @@ -125,7 +124,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { _ => (dest, None) }; for (i, operand) in operands.iter().enumerate() { - let op = self.codegen_operand(mir, &mut bx, operand); + let op = self.codegen_operand(&mut bx, operand); // Do not generate stores and GEPis for zero-sized fields. if !op.layout.is_zst() { let field_index = active_field_index.unwrap_or(i); @@ -137,8 +136,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } _ => { - assert!(self.rvalue_creates_operand(rvalue, DUMMY_SP, mir)); - let (mut bx, temp) = self.codegen_rvalue_operand(mir, bx, rvalue); + assert!(self.rvalue_creates_operand(rvalue, DUMMY_SP)); + let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue); temp.val.store(&mut bx, dest); bx } @@ -147,7 +146,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_rvalue_unsized( &mut self, - mir: &Body<'tcx>, mut bx: Bx, indirect_dest: PlaceRef<'tcx, Bx::Value>, rvalue: &mir::Rvalue<'tcx>, @@ -157,7 +155,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { match *rvalue { mir::Rvalue::Use(ref operand) => { - let cg_operand = self.codegen_operand(mir, &mut bx, operand); + let cg_operand = self.codegen_operand(&mut bx, operand); cg_operand.val.store_unsized(&mut bx, indirect_dest); bx } @@ -168,19 +166,18 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_rvalue_operand( &mut self, - mir: &Body<'tcx>, mut bx: Bx, rvalue: &mir::Rvalue<'tcx> ) -> (Bx, OperandRef<'tcx, Bx::Value>) { assert!( - self.rvalue_creates_operand(rvalue, DUMMY_SP, mir), + self.rvalue_creates_operand(rvalue, DUMMY_SP), "cannot codegen {:?} to operand", rvalue, ); match *rvalue { mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => { - let operand = self.codegen_operand(mir, &mut bx, source); + let operand = self.codegen_operand(&mut bx, source); debug!("cast operand is {:?}", operand); let cast = bx.cx().layout_of(self.monomorphize(&mir_cast_ty)); @@ -373,7 +370,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::Ref(_, bk, ref place) => { - let cg_place = self.codegen_place(mir, &mut bx, &place.as_ref()); + let cg_place = self.codegen_place(&mut bx, &place.as_ref()); let ty = cg_place.layout.ty; @@ -394,7 +391,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::Len(ref place) => { - let size = self.evaluate_array_len(mir, &mut bx, place); + let size = self.evaluate_array_len(&mut bx, place); let operand = OperandRef { val: OperandValue::Immediate(size), layout: bx.cx().layout_of(bx.tcx().types.usize), @@ -403,8 +400,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => { - let lhs = self.codegen_operand(mir, &mut bx, lhs); - let rhs = self.codegen_operand(mir, &mut bx, rhs); + let lhs = self.codegen_operand(&mut bx, lhs); + let rhs = self.codegen_operand(&mut bx, rhs); let llresult = match (lhs.val, rhs.val) { (OperandValue::Pair(lhs_addr, lhs_extra), OperandValue::Pair(rhs_addr, rhs_extra)) => { @@ -429,8 +426,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { (bx, operand) } mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => { - let lhs = self.codegen_operand(mir, &mut bx, lhs); - let rhs = self.codegen_operand(mir, &mut bx, rhs); + let lhs = self.codegen_operand(&mut bx, lhs); + let rhs = self.codegen_operand(&mut bx, rhs); let result = self.codegen_scalar_checked_binop(&mut bx, op, lhs.immediate(), rhs.immediate(), lhs.layout.ty); @@ -445,7 +442,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::UnaryOp(op, ref operand) => { - let operand = self.codegen_operand(mir, &mut bx, operand); + let operand = self.codegen_operand(&mut bx, operand); let lloperand = operand.immediate(); let is_float = operand.layout.ty.is_floating_point(); let llval = match op { @@ -463,8 +460,8 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(mir, bx.tcx()); - let discr = self.codegen_place(mir, &mut bx, &place.as_ref()) + let discr_ty = rvalue.ty(self.mir, bx.tcx()); + let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { val: OperandValue::Immediate(discr), @@ -509,14 +506,14 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { (bx, operand) } mir::Rvalue::Use(ref operand) => { - let operand = self.codegen_operand(mir, &mut bx, operand); + let operand = self.codegen_operand(&mut bx, operand); (bx, operand) } mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(mir, self.cx.tcx()); + let ty = rvalue.ty(self.mir, self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -528,7 +525,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { fn evaluate_array_len( &mut self, - mir: &Body<'tcx>, bx: &mut Bx, place: &mir::Place<'tcx>, ) -> Bx::Value { @@ -543,7 +539,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } } // use common size calculation for non zero-sized types - let cg_value = self.codegen_place(mir, bx, &place.as_ref()); + let cg_value = self.codegen_place(bx, &place.as_ref()); cg_value.len(bx.cx()) } @@ -704,7 +700,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { &self, rvalue: &mir::Rvalue<'tcx>, span: Span, - mir: &Body<'tcx> ) -> bool { match *rvalue { mir::Rvalue::Ref(..) | @@ -719,7 +714,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(mir, self.cx.tcx()); + let ty = rvalue.ty(self.mir, self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 05c88a316ff37..5307108f8571c 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -1,4 +1,4 @@ -use rustc::mir::{self, Body}; +use rustc::mir; use crate::traits::BuilderMethods; use super::FunctionCx; @@ -11,25 +11,24 @@ use rustc_error_codes::*; impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn codegen_statement( &mut self, - mir: &Body<'tcx>, mut bx: Bx, statement: &mir::Statement<'tcx> ) -> Bx { debug!("codegen_statement(statement={:?})", statement); - self.set_debug_loc(&mut bx, statement.source_info, mir); + self.set_debug_loc(&mut bx, statement.source_info); match statement.kind { mir::StatementKind::Assign(box(ref place, ref rvalue)) => { if let Some(index) = place.as_local() { match self.locals[index] { LocalRef::Place(cg_dest) => { - self.codegen_rvalue(mir, bx, cg_dest, rvalue) + self.codegen_rvalue(bx, cg_dest, rvalue) } LocalRef::UnsizedPlace(cg_indirect_dest) => { - self.codegen_rvalue_unsized(mir, bx, cg_indirect_dest, rvalue) + self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue) } LocalRef::Operand(None) => { - let (mut bx, operand) = self.codegen_rvalue_operand(mir, bx, rvalue); + let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue); self.locals[index] = LocalRef::Operand(Some(operand)); self.debug_introduce_local(&mut bx, index); bx @@ -43,16 +42,16 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // If the type is zero-sized, it's already been set here, // but we still need to make sure we codegen the operand - self.codegen_rvalue_operand(mir, bx, rvalue).0 + self.codegen_rvalue_operand(bx, rvalue).0 } } } else { - let cg_dest = self.codegen_place(mir, &mut bx, &place.as_ref()); - self.codegen_rvalue(mir, bx, cg_dest, rvalue) + let cg_dest = self.codegen_place(&mut bx, &place.as_ref()); + self.codegen_rvalue(bx, cg_dest, rvalue) } } mir::StatementKind::SetDiscriminant{box ref place, variant_index} => { - self.codegen_place(mir, &mut bx, &place.as_ref()) + self.codegen_place(&mut bx, &place.as_ref()) .codegen_set_discr(&mut bx, variant_index); bx } @@ -74,12 +73,12 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::StatementKind::InlineAsm(ref asm) => { let outputs = asm.outputs.iter().map(|output| { - self.codegen_place(mir, &mut bx, &output.as_ref()) + self.codegen_place(&mut bx, &output.as_ref()) }).collect(); let input_vals = asm.inputs.iter() .fold(Vec::with_capacity(asm.inputs.len()), |mut acc, (span, input)| { - let op = self.codegen_operand(mir, &mut bx, input); + let op = self.codegen_operand(&mut bx, input); if let OperandValue::Immediate(_) = op.val { acc.push(op.immediate()); } else { From c8c266a0fb4c83136cad45aaa0201594b9bd50db Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 14 Oct 2019 01:48:32 -0400 Subject: [PATCH 20/47] Convert &mut to & since the reference didn't need to be mutable --- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 171e3c840fbf7..6b405ed28274c 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -17,7 +17,7 @@ use super::FunctionCx; use crate::traits::*; pub fn non_ssa_locals<'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - fx: &mut FunctionCx<'a, 'b, 'tcx, Bx>, + fx: &FunctionCx<'a, 'b, 'tcx, Bx>, mir: &'c mut BodyCache<&'b Body<'tcx>>, ) -> BitSet { let mut analyzer = LocalAnalyzer::new(fx, mir); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 64129f4b5e48d..db7d0bfa6be3d 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -174,7 +174,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), }; - let memory_locals = analyze::non_ssa_locals(&mut fx, &mut mir); + let memory_locals = analyze::non_ssa_locals(&fx, &mut mir); // Allocate variable and temp allocas fx.locals = { From 2eed90a621f40aa3a2d56eda16f25315d17c4ca8 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 23 Oct 2019 13:46:23 -0400 Subject: [PATCH 21/47] Account for new maybe_sideeffect helper that requires predecessors --- src/librustc/mir/cache.rs | 165 ++++++++++++------ src/librustc/mir/mod.rs | 4 +- src/librustc/mir/visit.rs | 13 +- src/librustc_codegen_ssa/mir/analyze.rs | 29 ++- src/librustc_codegen_ssa/mir/block.rs | 34 ++-- src/librustc_codegen_ssa/mir/mod.rs | 19 +- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +- src/librustc_data_structures/graph/mod.rs | 2 +- .../graph/reference.rs | 35 +--- 10 files changed, 176 insertions(+), 133 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 103b24ecf6169..63d8eba971bb5 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -47,8 +47,7 @@ impl Cache { } #[inline] - /// This will recompute the predecessors cache if it is not available - pub fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec> { + pub fn ensure_predecessors(&mut self, body: &Body<'_>) { if self.predecessors.is_none() { let mut result = IndexVec::from_elem(vec![], body.basic_blocks()); for (bb, data) in body.basic_blocks().iter_enumerated() { @@ -61,7 +60,12 @@ impl Cache { self.predecessors = Some(result) } + } + #[inline] + /// This will recompute the predecessors cache if it is not available + pub fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec> { + self.ensure_predecessors(body); self.predecessors.as_ref().unwrap() } @@ -70,6 +74,11 @@ impl Cache { &self.predecessors(body)[bb] } + #[inline] + fn unwrap_predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { + &self.predecessors.as_ref().unwrap()[bb] + } + #[inline] pub fn predecessor_locations<'a>(&'a mut self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { let if_zero_locations = if loc.statement_index == 0 { @@ -137,13 +146,17 @@ impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> { } #[inline] - pub fn basic_blocks(&self) -> &IndexVec> { - &self.body.basic_blocks + pub fn read_only(mut self) -> ReadOnlyBodyCache<'a, 'tcx> { + self.cache.ensure_predecessors(self.body); + ReadOnlyBodyCache { + cache: self.cache, + body: self.body, + } } #[inline] - pub fn dominators(&mut self) -> Dominators { - dominators(self) + pub fn basic_blocks(&self) -> &IndexVec> { + &self.body.basic_blocks } } @@ -164,50 +177,6 @@ impl<'a, 'tcx> Index for BodyCache<&'a Body<'tcx>> { } } -impl<'a, 'tcx> graph::DirectedGraph for BodyCache<&'a Body<'tcx>> { - type Node = BasicBlock; -} - -impl<'a, 'graph, 'tcx> graph::GraphPredecessors<'graph> for BodyCache<&'a Body<'tcx>> { - type Item = BasicBlock; - type Iter = IntoIter; -} - -impl<'a, 'tcx> graph::WithPredecessors for BodyCache<&'a Body<'tcx>> { - fn predecessors( - &mut self, - node: Self::Node, - ) -> >::Iter { - self.predecessors_for(node).to_vec().into_iter() - } -} - -impl<'a, 'tcx> graph::WithNumNodes for BodyCache<&'a Body<'tcx>> { - fn num_nodes(&self) -> usize { - self.body.num_nodes() - } -} - -impl<'a, 'tcx> graph::WithStartNode for BodyCache<&'a Body<'tcx>> { - fn start_node(&self) -> Self::Node { - self.body.start_node() - } -} - -impl<'a, 'tcx> graph::WithSuccessors for BodyCache<&'a Body<'tcx>> { - fn successors( - &self, - node: Self::Node, - ) -> >::Iter { - self.body.successors(node) - } -} - -impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for BodyCache<&'a Body<'tcx>> { - type Item = BasicBlock; - type Iter = iter::Cloned>; -} - impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> { #[inline] pub fn body(&self) -> &Body<'tcx> { @@ -259,3 +228,99 @@ impl<'a, 'tcx> IndexMut for BodyCache<&'a mut Body<'tcx>> { &mut self.body.basic_blocks[index] } } + +pub struct ReadOnlyBodyCache<'a, 'tcx> { + cache: Cache, + body: &'a Body<'tcx>, +} + +impl ReadOnlyBodyCache<'a, 'tcx> { + #[inline] + pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { + self.cache.unwrap_predecessors_for(bb) + } + + #[inline] + pub fn body(&self) -> &'a Body<'tcx> { + self.body + } + + #[inline] + pub fn basic_blocks(&self) -> &IndexVec> { + &self.body.basic_blocks + } + + #[inline] + pub fn dominators(&self) -> Dominators { + dominators(self) + } + + pub fn to_owned(self) -> BodyCache<&'a Body<'tcx>> { + BodyCache { + cache: self.cache, + body: self.body, + } + } +} + +impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> { + type Node = BasicBlock; +} + +impl graph::GraphPredecessors<'graph> for ReadOnlyBodyCache<'a, 'tcx> { + type Item = BasicBlock; + type Iter = IntoIter; +} + +impl graph::WithPredecessors for ReadOnlyBodyCache<'a, 'tcx> { + fn predecessors( + &self, + node: Self::Node, + ) -> >::Iter { + self.cache.unwrap_predecessors_for(node).to_vec().into_iter() + } +} + +impl graph::WithNumNodes for ReadOnlyBodyCache<'a, 'tcx> { + fn num_nodes(&self) -> usize { + self.body.num_nodes() + } +} + +impl graph::WithStartNode for ReadOnlyBodyCache<'a, 'tcx> { + fn start_node(&self) -> Self::Node { + self.body.start_node() + } +} + +impl graph::WithSuccessors for ReadOnlyBodyCache<'a, 'tcx> { + fn successors( + &self, + node: Self::Node, + ) -> >::Iter { + self.body.successors(node) + } +} + +impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyCache<'a, 'tcx> { + type Item = BasicBlock; + type Iter = iter::Cloned>; +} + + +impl Deref for ReadOnlyBodyCache<'a, 'tcx> { + type Target = Body<'tcx>; + + fn deref(&self) -> &Self::Target { + self.body + } +} + +impl Index for ReadOnlyBodyCache<'a, 'tcx> { + type Output = BasicBlockData<'tcx>; + + #[inline] + fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { + &self.body[index] + } +} \ No newline at end of file diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9f71840576382..57d396ae93302 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -38,7 +38,7 @@ use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -pub use crate::mir::cache::BodyCache; +pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache}; pub mod cache; pub mod interpret; @@ -2600,7 +2600,7 @@ impl Location { pub fn is_predecessor_of<'tcx>( &self, other: Location, - mut body_cache: BodyCache<&'_ Body<'tcx>> + body_cache: &ReadOnlyBodyCache<'_, 'tcx> ) -> bool { // If we are in the same block as the other location and are an earlier statement // then we are a predecessor of `other`. diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index aa3aeb36e063e..7877466fbf6a6 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -65,6 +65,15 @@ use syntax_pos::Span; // variant argument) that does not require visiting, as in // `is_cleanup` above. +macro_rules! body_cache_type { + (mut $a:lifetime, $tcx:lifetime) => { + &mut BodyCache<& $a mut Body<$tcx>> + }; + ($a:lifetime, $tcx:lifetime) => { + &ReadOnlyBodyCache<$a, $tcx> + }; +} + macro_rules! make_mir_visitor { ($visitor_trait_name:ident, $($mutability:ident)?) => { pub trait $visitor_trait_name<'tcx> { @@ -73,7 +82,7 @@ macro_rules! make_mir_visitor { fn visit_body( &mut self, - body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>> + body_cache: body_cache_type!($($mutability)? '_, 'tcx) ) { self.super_body(body_cache); } @@ -245,7 +254,7 @@ macro_rules! make_mir_visitor { fn super_body( &mut self, - body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>> + body_cache: body_cache_type!($($mutability)? '_, 'tcx) ) { macro_rules! body { (mut) => (body_cache.body_mut()); diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 6b405ed28274c..fff0117834101 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -4,7 +4,7 @@ use rustc_index::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::vec::{Idx, IndexVec}; -use rustc::mir::{self, Body, BodyCache, Location, TerminatorKind}; +use rustc::mir::{self, Location, TerminatorKind}; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext, NonUseContext, }; @@ -16,15 +16,14 @@ use syntax_pos::DUMMY_SP; use super::FunctionCx; use crate::traits::*; -pub fn non_ssa_locals<'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - fx: &FunctionCx<'a, 'b, 'tcx, Bx>, - mir: &'c mut BodyCache<&'b Body<'tcx>>, +pub fn non_ssa_locals<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + fx: &FunctionCx<'a, 'b, 'tcx, Bx> ) -> BitSet { - let mut analyzer = LocalAnalyzer::new(fx, mir); + let mut analyzer = LocalAnalyzer::new(fx); - analyzer.visit_body(mir); + analyzer.visit_body(fx.mir); - for (local, decl) in mir.local_decls.iter_enumerated() + for (local, decl) in fx.mir.local_decls.iter_enumerated() { // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead // of putting everything in allocas just so we can use llvm.dbg.declare. @@ -66,20 +65,20 @@ struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { first_assignment: IndexVec, } -impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>, mir: &'c mut BodyCache<&'b Body<'tcx>>) -> Self { +impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { + fn new(fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>) -> Self { let invalid_location = - mir::BasicBlock::new(mir.basic_blocks().len()).start_location(); - let dominators = mir.dominators(); + mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); + let dominators = fx.mir.dominators(); let mut analyzer = LocalAnalyzer { fx, dominators, - non_ssa_locals: BitSet::new_empty(mir.local_decls.len()), - first_assignment: IndexVec::from_elem(invalid_location, &mir.local_decls) + non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()), + first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls) }; // Arguments get assigned to by means of the function being called - for arg in mir.args_iter() { + for arg in fx.mir.args_iter() { analyzer.first_assignment[arg] = mir::START_BLOCK.start_location(); } @@ -131,7 +130,7 @@ impl<'mir, 'a, 'b, 'c, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, ' }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir.body(), cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 53bffc794d770..e2cae0aa56516 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { // a loop. fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( &self, - mir: &'b mir::Body<'tcx>, + mir: &mir::ReadOnlyBodyCache<'_, 'tcx>, bx: &mut Bx, targets: &[mir::BasicBlock], ) { @@ -216,7 +216,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let lltrue = helper.llblock(self, targets[0]); let llfalse = helper.llblock(self, targets[1]); if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool if let [0] = values[..] { bx.cond_br(discr.immediate(), llfalse, lltrue); @@ -230,11 +230,11 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { ); let llval = bx.const_uint_big(switch_llty, values[0]); let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice()); bx.cond_br(cmp, lltrue, llfalse); } } else { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice()); let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), @@ -324,13 +324,13 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(self.mir, bx.tcx()).ty; + let ty = location.ty(self.mir.body(), bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return } @@ -361,7 +361,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { FnAbi::of_instance(&bx, drop_fn)) } }; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); @@ -397,7 +397,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Don't codegen the panic block if success if known. if const_cond == Some(expected) { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -408,7 +408,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Create the failure block and the conditional branch to it. let lltarget = helper.llblock(self, target); let panic_block = self.new_block("panic"); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -493,7 +493,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; self.codegen_transmute(&mut bx, &args[0], dest); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { // If we are trying to transmute to an uninhabited type, @@ -510,7 +510,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); + let op_ty = op_arg.ty(self.mir.body(), bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); @@ -521,7 +521,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { Some(ty::InstanceDef::DropGlue(_, None)) => { // Empty drop glue; a no-op. let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -553,7 +553,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let llfn = bx.get_fn_addr(instance); if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[*target]); } // Codegen the actual panic invoke/call. helper.do_call( @@ -568,7 +568,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } else { // a NOP let target = destination.as_ref().unwrap().1; - helper.maybe_sideeffect(mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) } return; @@ -682,7 +682,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } if let Some((_, target)) = *destination { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { bx.unreachable(); @@ -776,7 +776,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { }; if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[*target]); } helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), @@ -827,7 +827,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index db7d0bfa6be3d..a58b13ce102d2 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -21,7 +21,7 @@ use self::operand::{OperandRef, OperandValue}; pub struct FunctionCx<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: &'b mir::Body<'tcx>, + mir: &'b mir::ReadOnlyBodyCache<'a, 'tcx>, debug_context: Option>, @@ -156,10 +156,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }).collect(); let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); - + let mir_body = mir.body(); + let readonly_mir = mir.read_only(); let mut fx = FunctionCx { instance, - mir: mir.body(), + mir: &readonly_mir, llfn, fn_abi, cx, @@ -174,14 +175,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), }; - let memory_locals = analyze::non_ssa_locals(&fx, &mut mir); + let memory_locals = analyze::non_ssa_locals(&fx); // Allocate variable and temp allocas fx.locals = { let args = arg_local_refs(&mut bx, &fx, &memory_locals); let mut allocate_local = |local| { - let decl = &mir.local_decls[local]; + let decl = &mir_body.local_decls[local]; let layout = bx.layout_of(fx.monomorphize(&decl.ty)); assert!(!layout.ty.has_erasable_regions()); @@ -207,7 +208,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let retptr = allocate_local(mir::RETURN_PLACE); iter::once(retptr) .chain(args.into_iter()) - .chain(mir.vars_and_temps_iter().map(allocate_local)) + .chain(mir_body.vars_and_temps_iter().map(allocate_local)) .collect() }; @@ -226,8 +227,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( debug_context.source_locations_enabled = true; } - let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitSet::new_empty(mir.basic_blocks().len()); + let rpo = traversal::reverse_postorder(&mir_body); + let mut visited = BitSet::new_empty(mir_body.basic_blocks().len()); // Codegen the body of each block using reverse postorder for (bb, _) in rpo { @@ -237,7 +238,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Remove blocks that haven't been visited, or have no // predecessors. - for bb in mir.basic_blocks().indices() { + for bb in mir_body.basic_blocks().indices() { // Unreachable block if !visited.contains(bb.index()) { debug!("codegen_mir: block {:?} was not visited", bb); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 245998bd87d9b..34f2b56adee49 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -591,7 +591,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir, tcx); + let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir.body(), tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 5180f4376a67e..19554156b2277 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -460,7 +460,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(self.mir, bx.tcx()); + let discr_ty = rvalue.ty(self.mir.body(), bx.tcx()); let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { @@ -513,7 +513,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(self.mir, self.cx.tcx()); + let ty = rvalue.ty(self.mir.body(), self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -714,7 +714,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(self.mir, self.cx.tcx()); + let ty = rvalue.ty(self.mir.body(), self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 9ce60d207ad0e..37335799d19af 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -50,7 +50,7 @@ where Self: for<'graph> GraphPredecessors<'graph, Item = ::Node>, { fn predecessors( - &mut self, + &self, node: Self::Node, ) -> >::Iter; } diff --git a/src/librustc_data_structures/graph/reference.rs b/src/librustc_data_structures/graph/reference.rs index bc4458334d57f..eab217692d049 100644 --- a/src/librustc_data_structures/graph/reference.rs +++ b/src/librustc_data_structures/graph/reference.rs @@ -4,20 +4,11 @@ impl<'graph, G: DirectedGraph> DirectedGraph for &'graph G { type Node = G::Node; } -impl<'graph, G: DirectedGraph> DirectedGraph for &'graph mut G { - type Node = G::Node; -} - impl<'graph, G: WithNumNodes> WithNumNodes for &'graph G { fn num_nodes(&self) -> usize { (**self).num_nodes() } } -impl<'graph, G: WithNumNodes> WithNumNodes for &'graph mut G { - fn num_nodes(&self) -> usize { - (**self).num_nodes() - } -} impl<'graph, G: WithStartNode> WithStartNode for &'graph G { fn start_node(&self) -> Self::Node { @@ -25,25 +16,13 @@ impl<'graph, G: WithStartNode> WithStartNode for &'graph G { } } -impl<'graph, G: WithStartNode> WithStartNode for &'graph mut G { - fn start_node(&self) -> Self::Node { - (**self).start_node() - } -} - impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G { fn successors(&self, node: Self::Node) -> >::Iter { (**self).successors(node) } } -impl<'graph, G: WithSuccessors> WithSuccessors for &'graph mut G { - fn successors(&self, node: Self::Node) -> >::Iter { - (**self).successors(node) - } -} - -impl<'graph, G: WithPredecessors> WithPredecessors for &'graph mut G { - fn predecessors(&mut self, +impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G { + fn predecessors(&self, node: Self::Node) -> >::Iter { (**self).predecessors(node) @@ -55,17 +34,7 @@ impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph G type Iter = >::Iter; } -impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph mut G { - type Item = G::Node; - type Iter = >::Iter; -} - impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph G { type Item = G::Node; type Iter = >::Iter; } - -impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph mut G { - type Item = G::Node; - type Iter = >::Iter; -} From ab98c595eaa07249e2ebbf37c9123b33fc6a892f Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 24 Oct 2019 00:38:01 -0400 Subject: [PATCH 22/47] Fix a large number of Body -> (ReadOnly)BodyCache type errors, add predecessor_locations fn to ReadOnlyBodyCache --- src/librustc/mir/cache.rs | 64 ++++++++++------ src/librustc_mir/borrow_check/borrow_set.rs | 16 ++-- .../borrow_check/conflict_errors.rs | 56 +++++++------- .../borrow_check/error_reporting.rs | 32 ++++---- src/librustc_mir/borrow_check/mod.rs | 75 ++++++++++--------- src/librustc_mir/borrow_check/move_errors.rs | 20 ++--- .../borrow_check/mutability_errors.rs | 24 +++--- .../borrow_check/nll/explain_borrow/mod.rs | 20 ++--- .../borrow_check/nll/invalidation.rs | 10 +-- src/librustc_mir/borrow_check/nll/mod.rs | 31 ++++---- .../borrow_check/nll/region_infer/values.rs | 8 +- src/librustc_mir/borrow_check/nll/renumber.rs | 10 +-- .../borrow_check/nll/type_check/mod.rs | 20 ++--- src/librustc_mir/borrow_check/prefixes.rs | 2 +- src/librustc_mir/borrow_check/used_muts.rs | 2 +- 15 files changed, 207 insertions(+), 183 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 63d8eba971bb5..c0c5f77fe6ea9 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -33,6 +33,41 @@ pub struct Cache { // } //} +macro_rules! get_predecessors { + (mut $self:ident, $block:expr, $body:expr) => { + $self.predecessors_for($block, $body) + }; + ($self:ident, $block:expr, $body:expr) => { + $self.unwrap_predecessors_for($block) + }; +} + +macro_rules! impl_predecessor_locations { + ( ( $($pub:ident)? ) $name:ident $($mutability:ident)?) => { + $($pub)? fn $name<'a>(&'a $($mutability)? self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { + let if_zero_locations = if loc.statement_index == 0 { + let predecessor_blocks = get_predecessors!($($mutability)? self, loc.block, body); + let num_predecessor_blocks = predecessor_blocks.len(); + Some( + (0..num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| body.terminator_loc(bb)), + ) + } else { + None + }; + + let if_not_zero_locations = if loc.statement_index == 0 { + None + } else { + Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) + }; + + if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) + } + }; +} + impl Cache { pub fn new() -> Self { Self { @@ -80,27 +115,9 @@ impl Cache { } #[inline] - pub fn predecessor_locations<'a>(&'a mut self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { - let if_zero_locations = if loc.statement_index == 0 { - let predecessor_blocks = self.predecessors_for(loc.block, body); - let num_predecessor_blocks = predecessor_blocks.len(); - Some( - (0..num_predecessor_blocks) - .map(move |i| predecessor_blocks[i]) - .map(move |bb| body.terminator_loc(bb)), - ) - } else { - None - }; - - let if_not_zero_locations = if loc.statement_index == 0 { - None - } else { - Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) - }; - - if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) - } + impl_predecessor_locations!((pub) predecessor_locations mut); + + impl_predecessor_locations!(() unwrap_predecessor_locations); #[inline] pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec> { @@ -240,6 +257,11 @@ impl ReadOnlyBodyCache<'a, 'tcx> { self.cache.unwrap_predecessors_for(bb) } + #[inline] + pub fn predecessor_locations(&self, loc: Location) -> impl Iterator + '_ { + self.cache.unwrap_predecessor_locations(loc, self.body) + } + #[inline] pub fn body(&self) -> &'a Body<'tcx> { self.body diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 943234319906a..6191a93d22878 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -5,7 +5,7 @@ use crate::dataflow::indexes::BorrowIndex; use crate::dataflow::move_paths::MoveData; use rustc::mir::traversal; use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext}; -use rustc::mir::{self, Location, Body, Local}; +use rustc::mir::{self, Location, Body, Local, ReadOnlyBodyCache}; use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; @@ -90,7 +90,7 @@ crate enum LocalsStateAtExit { impl LocalsStateAtExit { fn build( locals_are_invalidated_at_exit: bool, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, move_data: &MoveData<'tcx> ) -> Self { struct HasStorageDead(BitSet); @@ -106,8 +106,8 @@ impl LocalsStateAtExit { if locals_are_invalidated_at_exit { LocalsStateAtExit::AllAreInvalidated } else { - let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body.local_decls.len())); - has_storage_dead.visit_body(body); + let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body_cache.local_decls.len())); + has_storage_dead.visit_body(body_cache); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { if let Some(index) = move_data.base_local(move_out.path) { @@ -123,23 +123,23 @@ impl LocalsStateAtExit { impl<'tcx> BorrowSet<'tcx> { pub fn build( tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, locals_are_invalidated_at_exit: bool, move_data: &MoveData<'tcx>, ) -> Self { let mut visitor = GatherBorrows { tcx, - body, + body: body_cache.body(), idx_vec: IndexVec::new(), location_map: Default::default(), activation_map: Default::default(), local_map: Default::default(), pending_activations: Default::default(), locals_state_at_exit: - LocalsStateAtExit::build(locals_are_invalidated_at_exit, body, move_data), + LocalsStateAtExit::build(locals_are_invalidated_at_exit, body_cache, move_data), }; - for (block, block_data) in traversal::preorder(body) { + for (block, block_data) in traversal::preorder(body_cache) { visitor.visit_basic_block_data(block, block_data); } diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 48f8ad9bbd8d6..b44ef1c1706a4 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -206,7 +206,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let ty = - Place::ty_from(used_place.base, used_place.projection, self.body, self.infcx.tcx) + Place::ty_from(used_place.base, used_place.projection, self.body_cache.body(), self.infcx.tcx) .ty; let needs_note = match ty.kind { ty::Closure(id, _) => { @@ -222,7 +222,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mpi = self.move_data.moves[move_out_indices[0]].path; let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(self.body, self.infcx.tcx).ty; + let ty = place.ty(self.body_cache.body(), self.infcx.tcx).ty; let opt_name = self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); let note_msg = match opt_name { @@ -314,7 +314,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ).add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -356,7 +356,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -578,7 +578,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, first_borrow_desc, @@ -619,7 +619,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Define a small closure that we can use to check if the type of a place // is a union. let union_ty = |place_base, place_projection| { - let ty = Place::ty_from(place_base, place_projection, self.body, self.infcx.tcx).ty; + let ty = Place::ty_from(place_base, place_projection, self.body_cache.body(), self.infcx.tcx).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) }; let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned()); @@ -738,7 +738,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assert!(root_place.projection.is_empty()); let proper_span = match root_place.base { - PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span, + PlaceBase::Local(local) => self.body_cache.local_decls[*local].source_info.span, _ => drop_span, }; @@ -965,7 +965,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -991,7 +991,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); explanation.add_explanation_to_diagnostic( - self.infcx.tcx, self.body, &self.local_names, &mut err, "", None); + self.infcx.tcx, &self.body_cache, &self.local_names, &mut err, "", None); } err @@ -1051,7 +1051,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -1138,7 +1138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } explanation.add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -1174,7 +1174,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; // FIXME use a better heuristic than Spans - let reference_desc = if return_span == self.body.source_info(borrow.reserve_location).span { + let reference_desc = if return_span == self.body_cache.source_info(borrow.reserve_location).span { "reference to" } else { "value referencing" @@ -1182,7 +1182,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let (place_desc, note) = if let Some(place_desc) = opt_place_desc { let local_kind = if let Some(local) = borrow.borrowed_place.as_local() { - match self.body.local_kind(local) { + match self.body_cache.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Temp => bug!("temporary or return pointer with a name"), LocalKind::Var => "local variable ", @@ -1215,7 +1215,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { bug!("try_report_cannot_return_reference_to_local: not a local") }; - match self.body.local_kind(*local) { + match self.body_cache.local_kind(*local) { LocalKind::ReturnPointer | LocalKind::Temp => ( "temporary value".to_string(), "temporary value created here".to_string(), @@ -1372,10 +1372,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec { - let body = self.body; - let mut stack = Vec::new(); - stack.extend(body.predecessor_locations(location).map(|predecessor| { + stack.extend(self.body_cache.predecessor_locations(location).map(|predecessor| { let is_back_edge = location.dominates(predecessor, &self.dominators); (predecessor, is_back_edge) })); @@ -1394,7 +1392,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // check for moves - let stmt_kind = body[location.block] + let stmt_kind = self.body_cache[location.block] .statements .get(location.statement_index) .map(|s| &s.kind); @@ -1449,7 +1447,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut any_match = false; drop_flag_effects::for_location_inits( self.infcx.tcx, - self.body, + &self.body_cache, self.move_data, location, |m| { @@ -1462,7 +1460,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { continue 'dfs; } - stack.extend(body.predecessor_locations(location).map(|predecessor| { + stack.extend(self.body_cache.predecessor_locations(location).map(|predecessor| { let back_edge = location.dominates(predecessor, &self.dominators); (predecessor, is_back_edge || back_edge) })); @@ -1514,7 +1512,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, loan, None) .add_explanation_to_diagnostic( self.infcx.tcx, - self.body, + &self.body_cache, &self.local_names, &mut err, "", @@ -1539,8 +1537,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { let (from_arg, local_decl, local_name) = match err_place.as_local() { Some(local) => ( - self.body.local_kind(local) == LocalKind::Arg, - Some(&self.body.local_decls[local]), + self.body_cache.local_kind(local) == LocalKind::Arg, + Some(&self.body_cache.local_decls[local]), self.local_names[local], ), None => (false, None, None), @@ -1625,7 +1623,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { assert!( - Place::ty_from(&place.base, proj_base, self.body, tcx).ty.is_box(), + Place::ty_from(&place.base, proj_base, self.body_cache.body(), tcx).ty.is_box(), "Drop of value behind a reference or raw pointer" ); StorageDeadOrDrop::BoxedStorageDead @@ -1633,7 +1631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::Destructor(_) => base_access, }, ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, self.body_cache.body(), tcx).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor @@ -1721,7 +1719,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location ); if let Some(&Statement { kind: StatementKind::Assign(box(ref reservation, _)), ..}) - = &self.body[location.block].statements.get(location.statement_index) + = &self.body_cache[location.block].statements.get(location.statement_index) { debug!( "annotate_argument_and_return_for_borrow: reservation={:?}", @@ -1729,14 +1727,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Check that the initial assignment of the reserve location is into a temporary. let mut target = match reservation.as_local() { - Some(local) if self.body.local_kind(local) == LocalKind::Temp => local, + Some(local) if self.body_cache.local_kind(local) == LocalKind::Temp => local, _ => return None, }; // Next, look through the rest of the block, checking if we are assigning the // `target` (that is, the place that contains our borrow) to anything. let mut annotated_closure = None; - for stmt in &self.body[location.block].statements[location.statement_index + 1..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] { debug!( "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", target, stmt @@ -1861,7 +1859,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Check the terminator if we didn't find anything in the statements. - let terminator = &self.body[location.block].terminator(); + let terminator = &self.body_cache[location.block].terminator(); debug!( "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", target, terminator diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a555e0b74c2b7..8267e5c1c4bd2 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -39,7 +39,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); - for stmt in &self.body[location.block].statements[location.statement_index..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index..] { debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); @@ -53,7 +53,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Check if we are attempting to call a closure after it has been invoked. - let terminator = self.body[location.block].terminator(); + let terminator = self.body_cache[location.block].terminator(); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); if let TerminatorKind::Call { func: Operand::Constant(box Constant { @@ -76,7 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); - if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind { + if let ty::Closure(did, _) = self.body_cache.local_decls[closure].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -99,7 +99,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if we are just moving a closure after it has been invoked. if let Some(target) = target { - if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind { + if let ty::Closure(did, _) = self.body_cache.local_decls[target].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -332,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have /// a name, or its name was generated by the compiler, then `Err` is returned fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> { - let decl = &self.body.local_decls[local]; + let decl = &self.body_cache.local_decls[local]; match self.local_names[local] { Some(name) if !decl.from_compiler_desugaring() => { buf.push_str(&name.as_str()); @@ -350,7 +350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { base: PlaceBase::Local(local), projection: [], } => { - let local = &self.body.local_decls[*local]; + let local = &self.body_cache.local_decls[*local]; self.describe_field_from_ty(&local.ty, field, None) } PlaceRef { @@ -370,7 +370,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ProjectionElem::Downcast(_, variant_index) => { let base_ty = - Place::ty_from(place.base, place.projection, self.body, self.infcx.tcx).ty; + Place::ty_from(place.base, place.projection, self.body_cache.body(), self.infcx.tcx).ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } ProjectionElem::Field(_, field_type) => { @@ -481,7 +481,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => continue, }; - let bbd = &self.body[loc.block]; + let bbd = &self.body_cache[loc.block]; let is_terminator = bbd.statements.len() == loc.statement_index; debug!( "borrowed_content_source: loc={:?} is_terminator={:?}", @@ -499,7 +499,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }) = bbd.terminator { if let Some(source) - = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx) + = BorrowedContentSource::from_call(func.ty(self.body_cache.body(), tcx), tcx) { return source; } @@ -512,7 +512,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find an overloaded deref or index, then assume it's a // built in deref and check the type of the base. - let base_ty = Place::ty_from(deref_base.base, deref_base.projection, self.body, tcx).ty; + let base_ty = Place::ty_from(deref_base.base, deref_base.projection, self.body_cache.body(), tcx).ty; if base_ty.is_unsafe_ptr() { BorrowedContentSource::DerefRawPointer } else if base_ty.is_mutable_ptr() { @@ -767,9 +767,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> UseSpans { use self::UseSpans::*; - let stmt = match self.body[location.block].statements.get(location.statement_index) { + let stmt = match self.body_cache[location.block].statements.get(location.statement_index) { Some(stmt) => stmt, - None => return OtherUse(self.body.source_info(location).span), + None => return OtherUse(self.body_cache.source_info(location).span), }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); @@ -807,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use self::UseSpans::*; debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); - let target = match self.body[location.block] + let target = match self.body_cache[location.block] .statements .get(location.statement_index) { @@ -824,12 +824,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => return OtherUse(use_span), }; - if self.body.local_kind(target) != LocalKind::Temp { + if self.body_cache.local_kind(target) != LocalKind::Temp { // operands are always temporaries. return OtherUse(use_span); } - for stmt in &self.body[location.block].statements[location.statement_index + 1..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] { if let StatementKind::Assign( box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { @@ -901,7 +901,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Helper to retrieve span(s) of given borrow from the current MIR /// representation pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans { - let span = self.body.source_info(borrow.reserve_location).span; + let span = self.body_cache.source_info(borrow.reserve_location).span; self.borrow_spans(span, borrow.reserve_location) } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f861a423ae266..0c1b0c4e14edd 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -10,7 +10,7 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT}; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase, - PlaceElem, PlaceRef, Static, StaticKind + PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind }; use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -163,16 +163,19 @@ fn do_mir_borrowck<'a, 'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); - let mut promoted: IndexVec> = input_promoted.clone(); + // TODO(pfaria) this very likely won't work because + let promoted: IndexVec> = input_promoted.clone(); + let mut promoted_cache: IndexVec>> = promoted.iter_mut().map(|body| BodyCache::new(body)).collect(); + let mut body_cache = BodyCache::new(&mut body); let free_regions = - nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted_cache); + let body_cache = BodyCache::new(&body).read_only(); // no further changes - let body_cache = &BodyCache::new(&body); // no further changes - let location_table = &LocationTable::new(body_cache); + let location_table = &LocationTable::new(&body_cache); let mut errors_buffer = Vec::new(); let (move_data, move_errors): (MoveData<'tcx>, Option, MoveError<'tcx>)>>) = - match MoveData::gather_moves(body_cache, tcx) { + match MoveData::gather_moves(&body_cache, tcx) { Ok(move_data) => (move_data, None), Err((move_data, move_errors)) => (move_data, Some(move_errors)), }; @@ -185,24 +188,24 @@ fn do_mir_borrowck<'a, 'tcx>( let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - MaybeInitializedPlaces::new(tcx, body_cache, &mdpe), + MaybeInitializedPlaces::new(tcx, &body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build( - tcx, body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); + tcx, &body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( infcx, def_id, free_regions, - body_cache, + &body_cache, &promoted, &local_names, &upvars, @@ -223,29 +226,29 @@ fn do_mir_borrowck<'a, 'tcx>( let flow_borrows = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - Borrows::new(tcx, body_cache, param_env, regioncx.clone(), &borrow_set), + Borrows::new(tcx, &body_cache, param_env, regioncx.clone(), &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); let flow_uninits = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe), + MaybeUninitializedPlaces::new(tcx, &body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, - body_cache, + &body_cache, def_id, &attributes, &dead_unwinds, - EverInitializedPlaces::new(tcx, body_cache, &mdpe), + EverInitializedPlaces::new(tcx, &body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); @@ -302,7 +305,7 @@ fn do_mir_borrowck<'a, 'tcx>( mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow); let scope = mbcx.body.source_info(location).scope; - let lint_root = match &mbcx.body.source_scopes[scope].local_data { + let lint_root = match &mbcx.body_cache.source_scopes[scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => id, }; @@ -324,21 +327,21 @@ fn do_mir_borrowck<'a, 'tcx>( // would have a chance of erroneously adding non-user-defined mutable vars // to the set. let temporary_used_locals: FxHashSet = mbcx.used_mut.iter() - .filter(|&local| !mbcx.body.local_decls[*local].is_user_variable()) + .filter(|&local| !mbcx.body_cache.local_decls[*local].is_user_variable()) .cloned() .collect(); // For the remaining unused locals that are marked as mutable, we avoid linting any that // were never initialized. These locals may have been removed as unreachable code; or will be // linted as unused variables. - let unused_mut_locals = mbcx.body.mut_vars_iter() + let unused_mut_locals = mbcx.body_cache.mut_vars_iter() .filter(|local| !mbcx.used_mut.contains(local)) .collect(); mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); let used_mut = mbcx.used_mut; - for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { - let local_decl = &mbcx.body.local_decls[local]; + for local in mbcx.body_cache.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { + let local_decl = &mbcx.body_cache.local_decls[local]; let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => continue, @@ -399,7 +402,7 @@ fn do_mir_borrowck<'a, 'tcx>( crate struct MirBorrowckCtxt<'cx, 'tcx> { crate infcx: &'cx InferCtxt<'cx, 'tcx>, - body_cache: BodyCache<&'cx Body<'tcx>>, + body_cache: ReadOnlyBodyCache<'cx, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, move_data: &'cx MoveData<'tcx>, @@ -490,7 +493,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx type FlowState = Flows<'cx, 'tcx>; fn body(&self) -> &'cx Body<'tcx> { - self.body_cache + &self.body_cache } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { @@ -640,7 +643,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx let tcx = self.infcx.tcx; // Compute the type with accurate region information. - let drop_place_ty = drop_place.ty(self.body_cache, self.infcx.tcx); + let drop_place_ty = drop_place.ty(self.body_cache.body(), self.infcx.tcx); // Erase the regions. let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; @@ -984,7 +987,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut error_reported = false; let tcx = self.infcx.tcx; - let body = self.body_cache; + let body = self.body_cache.body(); let param_env = self.param_env; let location_table = self.location_table.start_index(location); let borrow_set = self.borrow_set.clone(); @@ -1150,7 +1153,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // (e.g., `x = ...`) so long as it has never been initialized // before (at this point in the flow). if let Some(local) = place_span.0.as_local() { - if let Mutability::Not = self.body.local_decls[local].mutability { + if let Mutability::Not = self.body+cache.local_decls[local].mutability { // check for reassignments to immutable local variables self.check_if_reassignment_to_immutable_state( location, @@ -1303,7 +1306,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match *operand { Operand::Move(ref place) | Operand::Copy(ref place) => { match place.as_local() { - Some(local) if !self.body.local_decls[local].is_user_variable() => { + Some(local) if !self.body_cache.local_decls[local].is_user_variable() => { if self.body.local_decls[local].ty.is_mutable_ptr() { // The variable will be marked as mutable by the borrow. return; @@ -1335,7 +1338,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => bug!("temporary initialized in arguments"), }; - let bbd = &self.body[loc.block]; + let bbd = &self.body_cache[loc.block]; let stmt = &bbd.statements[loc.statement_index]; debug!("temporary assigned in: stmt={:?}", stmt); @@ -1454,7 +1457,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if places_conflict::borrow_conflicts_with_place( self.infcx.tcx, self.param_env, - self.body, + &self.body_cache, place, borrow.kind, root_place, @@ -1534,7 +1537,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) { // And, if so, report an error. let init = &self.move_data.inits[init_index]; - let span = init.span(&self.body); + let span = init.span(&self.body_cache); self.report_illegal_reassignment( location, place_span, span, place_span.0 ); @@ -1745,7 +1748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // assigning to `P.f` requires `P` itself // be already initialized let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, self.body(), tcx).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( @@ -1852,12 +1855,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // of the union - we should error in that case. let tcx = this.infcx.tcx; if let ty::Adt(def, _) = - Place::ty_from(base.base, base.projection, this.body, tcx).ty.kind + Place::ty_from(base.base, base.projection, this.body(), tcx).ty.kind { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { this.move_data.moves[*moi].source.is_predecessor_of( - location, this.body, + location, &this.body_cache, ) }) { return; @@ -2061,7 +2064,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { base: PlaceBase::Local(local), projection: [], } => { - let local = &self.body.local_decls[*local]; + let local = &self.body_cache.local_decls[*local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { LocalMutationIsAllowed::Yes => Ok(RootPlace { @@ -2122,7 +2125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match elem { ProjectionElem::Deref => { let base_ty = - Place::ty_from(place.base, proj_base, self.body, self.infcx.tcx).ty; + Place::ty_from(place.base, proj_base, self.body(), self.infcx.tcx).ty; // Check the kind of deref to decide match base_ty.kind { @@ -2262,7 +2265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match place_projection { [base @ .., ProjectionElem::Field(field, _ty)] => { let tcx = self.infcx.tcx; - let base_ty = Place::ty_from(place_ref.base, base, self.body, tcx).ty; + let base_ty = Place::ty_from(place_ref.base, base, self.body(), tcx).ty; if (base_ty.is_closure() || base_ty.is_generator()) && (!by_ref || self.upvars[field.index()].by_ref) { diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index bf61eb9f0c5c7..5907da09c671a 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -90,13 +90,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // flow could be used. if let Some(StatementKind::Assign( box(place, Rvalue::Use(Operand::Move(move_from))) - )) = self.body.basic_blocks()[location.block] + )) = self.body_cache.basic_blocks()[location.block] .statements .get(location.statement_index) .map(|stmt| &stmt.kind) { if let Some(local) = place.as_local() { - let local_decl = &self.body.local_decls[local]; + let local_decl = &self.body_cache.local_decls[local]; // opt_match_place is the // match_span is the span of the expression being matched on // match *x.y { ... } match_place is Some(*x.y) @@ -112,7 +112,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { pat_span: _, }, ))) = local_decl.local_info { - let stmt_source_info = self.body.source_info(location); + let stmt_source_info = self.body_cache.source_info(location); self.append_binding_error( grouped_errors, kind, @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. - let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty; + let ty = deref_target_place.ty(self.body_cache.body(), self.infcx.tcx).ty; let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); @@ -318,7 +318,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { base: PlaceBase::Local(local), projection: [], } = deref_base { - let decl = &self.body.local_decls[*local]; + let decl = &self.body_cache.local_decls[*local]; if decl.is_ref_for_guard() { let mut err = self.cannot_move_out_of( span, @@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let move_ty = format!( "{:?}", - move_place.ty(self.body, self.infcx.tcx).ty, + move_place.ty(self.body_cache.body(), self.infcx.tcx).ty, ); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { let is_option = move_ty.starts_with("std::option::Option"); @@ -454,7 +454,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.is_empty() { - let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; + let place_ty = move_from.ty(self.body_cache.body(), self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -482,7 +482,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // No binding. Nothing to suggest. GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => { let span = use_spans.var_or_use(); - let place_ty = original_path.ty(self.body, self.infcx.tcx).ty; + let place_ty = original_path.ty(self.body_cache.body(), self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -510,7 +510,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ) { let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); for local in binds_to { - let bind_to = &self.body.local_decls[*local]; + let bind_to = &self.body_cache.local_decls[*local]; if let LocalInfo::User( ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { pat_span, @@ -559,7 +559,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { binds_to: &[Local], ) { for (j, local) in binds_to.into_iter().enumerate() { - let bind_to = &self.body.local_decls[*local]; + let bind_to = &self.body_cache.local_decls[*local]; let binding_span = bind_to.source_info.span; if j == 0 { diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index bf070c3f07d48..654666882cca4 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty + Place::ty_from(&the_place_err.base, proj_base, self.body_cache.body(), self.infcx.tcx).ty )); item_msg = format!("`{}`", access_place_desc.unwrap()); @@ -106,12 +106,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { proj_base.is_empty() && !self.upvars.is_empty() { item_msg = format!("`{}`", access_place_desc.unwrap()); - debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr()); + debug_assert!(self.body_cache.local_decls[Local::new(1)].ty.is_region_ptr()); debug_assert!(is_closure_or_generator( Place::ty_from( the_place_err.base, the_place_err.projection, - self.body, + self.body_cache.body(), self.infcx.tcx ) .ty @@ -225,7 +225,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty, + Place::ty_from(base, proj_base, self.body_cache.body(), self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -242,7 +242,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { base: PlaceBase::Local(local), projection: [], } if { - self.body.local_decls.get(*local).map(|local_decl| { + self.body_cache.local_decls.get(*local).map(|local_decl| { if let LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(kind) )) = local_decl.local_info { @@ -277,12 +277,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [], - } if self.body.local_decls[*local].can_be_made_mutable() => { + } if self.body_cache.local_decls[*local].can_be_made_mutable() => { // ... but it doesn't make sense to suggest it on // variables that are `ref x`, `ref mut x`, `&self`, // or `&mut self` (such variables are simply not // mutable). - let local_decl = &self.body.local_decls[*local]; + let local_decl = &self.body_cache.local_decls[*local]; assert_eq!(local_decl.mutability, Mutability::Not); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty + Place::ty_from(base, proj_base, self.body_cache.body(), self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -346,7 +346,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref], - } if self.body.local_decls[*local].is_ref_for_guard() => { + } if self.body_cache.local_decls[*local].is_ref_for_guard() => { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.note( "variables bound in patterns are immutable until the end of the pattern guard", @@ -363,7 +363,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [ProjectionElem::Deref], } if self.body.local_decls[*local].is_user_variable() => { - let local_decl = &self.body.local_decls[*local]; + let local_decl = &self.body_cache.local_decls[*local]; let suggestion = match local_decl.local_info { LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => { Some(suggest_ampmut_self(self.infcx.tcx, local_decl)) @@ -377,7 +377,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, ))) => Some(suggest_ampmut( self.infcx.tcx, - self.body, + &self.body_cache, *local, local_decl, opt_ty_info, @@ -451,7 +451,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_help( - self.body.span, + self.body_cache.span, "consider changing this to accept closures that implement `FnMut`" ); } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index c7058531958e1..4097bfeeb3599 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -237,7 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let regioncx = &self.nonlexical_regioncx; - let body = self.body; + let body = self.body_cache.body(); let tcx = self.infcx.tcx; let borrow_region_vid = borrow.region; @@ -297,9 +297,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) { let (category, from_closure, span, region_name) = self.nonlexical_regioncx.free_region_constraint_info( - self.body, - &self.local_names, - &self.upvars, + &self.body_cache, + &self.local_names, + &self.upvars, self.mir_def_id, self.infcx, borrow_region_vid, @@ -365,7 +365,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return outmost_back_edge; } - let block = &self.body.basic_blocks()[location.block]; + let block = &self.body_cache.basic_blocks()[location.block]; if location.statement_index < block.statements.len() { let successor = location.successor_within_block(); @@ -427,7 +427,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if loop_head.dominates(from, &self.dominators) { - let block = &self.body.basic_blocks()[from.block]; + let block = &self.body_cache.basic_blocks()[from.block]; if from.statement_index < block.statements.len() { let successor = from.successor_within_block(); @@ -475,7 +475,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (LaterUseKind::ClosureCapture, var_span) } UseSpans::OtherUse(span) => { - let block = &self.body.basic_blocks()[location.block]; + let block = &self.body_cache.basic_blocks()[location.block]; let kind = if let Some(&Statement { kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), @@ -498,7 +498,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { - let local_decl = &self.body.local_decls[l]; + let local_decl = &self.body_cache.local_decls[l]; if self.local_names[l].is_none() { local_decl.source_info.span } else { @@ -528,7 +528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool { // Start at the reserve location, find the place that we want to see cast to a trait object. let location = borrow.reserve_location; - let block = &self.body[location.block]; + let block = &self.body_cache[location.block]; let stmt = block.statements.get(location.statement_index); debug!( "was_captured_by_trait_object: location={:?} stmt={:?}", @@ -558,7 +558,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); while let Some(current_location) = queue.pop() { debug!("was_captured_by_trait: target={:?}", target); - let block = &self.body[current_location.block]; + let block = &self.body_cache[current_location.block]; // We need to check the current location to find out if it is a terminator. let is_terminator = current_location.statement_index == block.statements.len(); if !is_terminator { diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 1d429e3a6dee6..7cb5b839ceebd 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -11,7 +11,7 @@ use crate::borrow_check::path_utils::*; use crate::dataflow::indexes::BorrowIndex; use rustc::ty::{self, TyCtxt}; use rustc::mir::visit::Visitor; -use rustc::mir::{BasicBlock, Location, Body, Place, Rvalue}; +use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyCache, Rvalue}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::TerminatorKind; use rustc::mir::{Operand, BorrowKind}; @@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>( param_env: ty::ParamEnv<'tcx>, all_facts: &mut Option, location_table: &LocationTable, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, borrow_set: &BorrowSet<'tcx>, ) { if all_facts.is_none() { @@ -31,17 +31,17 @@ pub(super) fn generate_invalidates<'tcx>( } if let Some(all_facts) = all_facts { - let dominators = body.dominators(); + let dominators = body_cache.dominators(); let mut ig = InvalidationGenerator { all_facts, borrow_set, param_env, tcx, location_table, - body, + body: body_cache.body(), dominators, }; - ig.visit_body(body); + ig.visit_body(&body_cache); } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 4d67b72c98c57..dac5815fada23 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -12,7 +12,8 @@ use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, - Local, Location, Body, LocalKind, BasicBlock, Promoted}; + Local, Location, Body, BodyCache, LocalKind, BasicBlock, + Promoted, ReadOnlyBodyCache}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_index::vec::IndexVec; use rustc_errors::Diagnostic; @@ -54,8 +55,8 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body: &mut Body<'tcx>, - promoted: &mut IndexVec>, + body_cache: &mut BodyCache<&mut Body<'tcx>>, + promoted: &mut IndexVec>>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -63,10 +64,10 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( let universal_regions = UniversalRegions::new(infcx, def_id, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body, promoted); + renumber::renumber_mir(infcx, body_cache, promoted); let source = MirSource::item(def_id); - mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); + mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body_cache, |_, _| Ok(())); universal_regions } @@ -157,7 +158,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, universal_regions: UniversalRegions<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, promoted: &IndexVec>, local_names: &IndexVec>, upvars: &[Upvar], @@ -180,7 +181,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(body)); + let elements = &Rc::new(RegionValueElements::new(body_cache)); // Run the MIR type-checker. let MirTypeckResults { @@ -189,7 +190,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( } = type_check::type_check( infcx, param_env, - body, + body_cache, promoted, def_id, &universal_regions, @@ -205,7 +206,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); - populate_polonius_move_facts(all_facts, move_data, location_table, body); + populate_polonius_move_facts(all_facts, move_data, location_table, body_cache); } // Create the region inference context, taking ownership of the @@ -229,7 +230,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( &mut liveness_constraints, &mut all_facts, location_table, - &body, + body_cache, borrow_set, ); @@ -238,7 +239,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( universal_regions, placeholder_indices, universal_region_relations, - body, + body_cache, outlives_constraints, member_constraints, closure_bounds_mapping, @@ -253,7 +254,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( param_env, &mut all_facts, location_table, - &body, + body_cache, borrow_set, ); @@ -283,21 +284,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let closure_region_requirements = - regioncx.solve(infcx, body, local_names, upvars, def_id, errors_buffer); + regioncx.solve(infcx, body_cache, local_names, upvars, def_id, errors_buffer); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, MirSource::item(def_id), - &body, + body_cache, ®ioncx, &closure_region_requirements, ); // We also have a `#[rustc_nll]` annotation that causes us to dump // information - dump_annotation(infcx, &body, def_id, ®ioncx, &closure_region_requirements, errors_buffer); + dump_annotation(infcx, body_cache, def_id, ®ioncx, &closure_region_requirements, errors_buffer); (regioncx, polonius_output, closure_region_requirements) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 7a86536573dcf..5d1891c0bf64c 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -1,4 +1,4 @@ -use rustc::mir::{BasicBlock, Location, Body}; +use rustc::mir::{BasicBlock, Location, Body, ReadOnlyBodyCache}; use rustc::ty::{self, RegionVid}; use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; use rustc_data_structures::fx::FxHashMap; @@ -92,7 +92,7 @@ impl RegionValueElements { /// Pushes all predecessors of `index` onto `stack`. crate fn push_predecessors( &self, - body: &Body<'_>, + body_cache: &ReadOnlyBodyCache<'_, '_>, index: PointIndex, stack: &mut Vec, ) { @@ -104,9 +104,9 @@ impl RegionValueElements { // If this is a basic block head, then the predecessors are // the terminators of other basic blocks stack.extend( - body.predecessors_for(block) + body_cache.predecessors_for(block) .iter() - .map(|&pred_bb| body.terminator_loc(pred_bb)) + .map(|&pred_bb| body_cache.terminator_loc(pred_bb)) .map(|pred_loc| self.point_from_location(pred_loc)), ); } else { diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index d949c7e01aab7..57e977eacba15 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,6 +1,6 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::mir::{Body, Location, PlaceElem, Promoted}; +use rustc::mir::{Body, BodyCache, Location, PlaceElem, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -9,11 +9,11 @@ use rustc_index::vec::IndexVec; /// inference variables, returning the number of variables created. pub fn renumber_mir<'tcx>( infcx: &InferCtxt<'_, 'tcx>, - body: &mut Body<'tcx>, - promoted: &mut IndexVec>, + body_cache: &mut BodyCache<&mut Body<'tcx>>, + promoted: &mut IndexVec>>, ) { debug!("renumber_mir()"); - debug!("renumber_mir: body.arg_count={:?}", body.arg_count); + debug!("renumber_mir: body.arg_count={:?}", body_cache.arg_count); let mut visitor = NLLVisitor { infcx }; @@ -21,7 +21,7 @@ pub fn renumber_mir<'tcx>( visitor.visit_body(body); } - visitor.visit_body(body); + visitor.visit_body(body_cache); } /// Replaces all regions appearing in `value` with fresh inference diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 4f95aa4a7b003..2de9f0e12821b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -115,7 +115,7 @@ mod relate_tys; pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, @@ -161,15 +161,15 @@ pub(crate) fn type_check<'tcx>( infcx, mir_def_id, param_env, - body, + body_cache, promoted, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, &universal_region_relations, |mut cx| { - cx.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); - liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); + cx.equate_inputs_and_outputs(body_cache, universal_regions, &normalized_inputs_and_output); + liveness::generate(&mut cx, body_cache, elements, flow_inits, move_data, location_table); translate_outlives_facts(cx.borrowck_context); }, @@ -185,7 +185,7 @@ fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body: &'a Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'a, 'tcx>, promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, @@ -195,7 +195,7 @@ fn type_check_internal<'a, 'tcx, R>( ) -> R where { let mut checker = TypeChecker::new( infcx, - body, + body_cache, mir_def_id, param_env, region_bound_pairs, @@ -204,14 +204,14 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body, promoted); - verifier.visit_body(body); + let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted); + verifier.visit_body(body_cache); verifier.errors_reported }; if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(body); + checker.typeck_mir(body_cache); } extra(&mut checker) @@ -385,7 +385,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - fn visit_body(&mut self, body_cache: &BodyCache<&'_ Body<'tcx>>) { + fn visit_body(&mut self, body_cache: &ReadOnlyBodyCache<'_, 'tcx>) { self.sanitize_type(&"return type", body_cache.return_ty()); for local_decl in &body_cache.local_decls { self.sanitize_type(local_decl, local_decl.ty); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 57833cac9cb44..aa02c0641e351 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -56,7 +56,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, - body: self.body, + body: &self.body_cache, tcx: self.infcx.tcx, } } diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 95471afb7884f..430452efe422d 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -32,7 +32,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { never_initialized_mut_locals: &mut never_initialized_mut_locals, mbcx: self, }; - visitor.visit_body(visitor.mbcx.body); + visitor.visit_body(&visitor.mbcx.body_cache); } // Take the union of the existed `used_mut` set with those variables we've found were From 26f1c01ff7d63415cabacefa301b6b4a6814f661 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 24 Oct 2019 09:18:04 -0400 Subject: [PATCH 23/47] Add read_only fn to BodyCache<&mut...> impl, fix more Body -> (ReadOnly)BodyCache type errors --- src/librustc/mir/cache.rs | 9 ++++++ src/librustc_mir/borrow_check/mod.rs | 6 ++-- src/librustc_mir/borrow_check/nll/mod.rs | 4 +-- .../nll/type_check/liveness/mod.rs | 11 ++++--- .../nll/type_check/liveness/trace.rs | 28 ++++++++--------- .../borrow_check/nll/type_check/mod.rs | 30 +++++++++---------- 6 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index c0c5f77fe6ea9..24d1f9e373bb0 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -205,6 +205,15 @@ impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> { self.body } + #[inline] + pub fn read_only(mut self) -> ReadOnlyBodyCache<'a, 'tcx> { + self.cache.ensure_predecessors(self.body); + ReadOnlyBodyCache { + cache: self.cache, + body: self.body, + } + } + #[inline] pub fn basic_blocks(&self) -> &IndexVec> { &self.body.basic_blocks diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 0c1b0c4e14edd..f8ae07aa394b5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -163,13 +163,13 @@ fn do_mir_borrowck<'a, 'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); - // TODO(pfaria) this very likely won't work because - let promoted: IndexVec> = input_promoted.clone(); - let mut promoted_cache: IndexVec>> = promoted.iter_mut().map(|body| BodyCache::new(body)).collect(); + let mut promoted = input_promoted.clone(); + let mut promoted_cache: IndexVec>> = input_promoted.clone().iter_mut().map(|body| BodyCache::new(body)).collect(); let mut body_cache = BodyCache::new(&mut body); let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted_cache); let body_cache = BodyCache::new(&body).read_only(); // no further changes + let promoted: IndexVec> = promoted_cache.into_iter().map(|body_cache| body_cache.read_only()).collect(); let location_table = &LocationTable::new(&body_cache); diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index dac5815fada23..5fa2c6605f6fb 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -159,7 +159,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( def_id: DefId, universal_regions: UniversalRegions<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>, - promoted: &IndexVec>, + promoted_cache: &IndexVec>, local_names: &IndexVec>, upvars: &[Upvar], location_table: &LocationTable, @@ -191,7 +191,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx, param_env, body_cache, - promoted, + promoted_cache, def_id, &universal_regions, location_table, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index a01b528833b2d..833958814af45 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -7,7 +7,7 @@ use crate::borrow_check::nll::ToRegionVid; use crate::dataflow::move_paths::MoveData; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; -use rustc::mir::{Body, Local}; +use rustc::mir::{Body, Local, ReadOnlyBodyCache}; use rustc::ty::{RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::rc::Rc; @@ -28,7 +28,7 @@ mod trace; /// performed before pub(super) fn generate<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -41,15 +41,14 @@ pub(super) fn generate<'tcx>( &typeck.borrowck_context.universal_regions, &typeck.borrowck_context.constraints.outlives_constraints, ); - let live_locals = compute_live_locals(typeck.tcx(), &free_regions, body); + let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body_cache); let facts_enabled = AllFacts::enabled(typeck.tcx()); - let polonius_drop_used = if facts_enabled { let mut drop_used = Vec::new(); polonius::populate_access_facts( typeck, - body, + &body_cache, location_table, move_data, &mut drop_used, @@ -62,7 +61,7 @@ pub(super) fn generate<'tcx>( if !live_locals.is_empty() || facts_enabled { trace::trace( typeck, - body, + body_cache, elements, flow_inits, move_data, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index eacc4d084dbb8..5929516ec4e47 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -7,7 +7,7 @@ use crate::dataflow::indexes::MovePathIndex; use crate::dataflow::move_paths::MoveData; use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces}; use rustc::infer::canonical::QueryRegionConstraints; -use rustc::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; +use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyCache}; use rustc::traits::query::dropck_outlives::DropckOutlivesResult; use rustc::traits::query::type_op::outlives::DropckOutlives; use rustc::traits::query::type_op::TypeOp; @@ -32,7 +32,7 @@ use std::rc::Rc; /// this respects `#[may_dangle]` annotations). pub(super) fn trace( typeck: &mut TypeChecker<'_, 'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -41,11 +41,11 @@ pub(super) fn trace( ) { debug!("trace()"); - let local_use_map = &LocalUseMap::build(&live_locals, elements, body); + let local_use_map = &LocalUseMap::build(&live_locals, elements, &body_cache); let cx = LivenessContext { typeck, - body, + body_cache, flow_inits, elements, local_use_map, @@ -71,7 +71,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { elements: &'me RegionValueElements, /// MIR we are analyzing. - body: &'me Body<'tcx>, + body_cache: &'me ReadOnlyBodyCache<'me, 'tcx>, /// Mapping to/from the various indices used for initialization tracking. move_data: &'me MoveData<'tcx>, @@ -135,7 +135,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { self.compute_use_live_points_for(local); self.compute_drop_live_points_for(local); - let local_ty = self.cx.body.local_decls[local].ty; + let local_ty = self.cx.body_cache.local_decls[local].ty; if !self.use_live_at.is_empty() { self.cx.add_use_live_facts_for(local_ty, &self.use_live_at); @@ -165,7 +165,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { for (local, location) in drop_used { if !live_locals.contains(&local) { - let local_ty = self.cx.body.local_decls[local].ty; + let local_ty = self.cx.body_cache.local_decls[local].ty; if local_ty.has_free_regions() { self.cx.add_drop_live_facts_for( local, @@ -211,7 +211,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } if self.use_live_at.insert(p) { - self.cx.elements.push_predecessors(self.cx.body, p, &mut self.stack) + self.cx.elements.push_predecessors(&self.cx.body_cache, p, &mut self.stack) } } } @@ -234,7 +234,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // Find the drops where `local` is initialized. for drop_point in self.cx.local_use_map.drops(local) { let location = self.cx.elements.to_location(drop_point); - debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); + debug_assert_eq!(self.cx.body_cache.terminator_loc(location.block), location,); if self.cx.initialized_at_terminator(location.block, mpi) { if self.drop_live_at.insert(drop_point) { @@ -280,7 +280,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // block. One of them may be either a definition or use // live point. let term_location = self.cx.elements.to_location(term_point); - debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,); + debug_assert_eq!(self.cx.body_cache.terminator_loc(term_location.block), term_location,); let block = term_location.block; let entry_point = self.cx.elements.entry_point(term_location.block); for p in (entry_point..term_point).rev() { @@ -302,7 +302,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - for &pred_block in self.cx.body.predecessors_for(block).iter() { + for &pred_block in self.cx.body_cache.predecessors_for(block).iter() { debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,); // Check whether the variable is (at least partially) @@ -328,7 +328,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { continue; } - let pred_term_loc = self.cx.body.terminator_loc(pred_block); + let pred_term_loc = self.cx.body_cache.terminator_loc(pred_block); let pred_term_point = self.cx.elements.point_from_location(pred_term_loc); // If the terminator of this predecessor either *assigns* @@ -399,7 +399,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { // the effects of all statements. This is the only way to get // "just ahead" of a terminator. self.flow_inits.reset_to_entry_of(block); - for statement_index in 0..self.body[block].statements.len() { + for statement_index in 0..self.body_cache[block].statements.len() { let location = Location { block, statement_index }; self.flow_inits.reconstruct_statement_effect(location); self.flow_inits.apply_local_effect(location); @@ -471,7 +471,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { drop_data.dropck_result.report_overflows( self.typeck.infcx.tcx, - self.body.source_info(*drop_locations.first().unwrap()).span, + self.body_cache.source_info(*drop_locations.first().unwrap()).span, dropped_ty, ); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 2de9f0e12821b..8e966033bb8fd 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -116,7 +116,7 @@ pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body_cache: &ReadOnlyBodyCache<'_, 'tcx>, - promoted: &IndexVec>, + promoted_cache: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, location_table: &LocationTable, @@ -162,7 +162,7 @@ pub(crate) fn type_check<'tcx>( mir_def_id, param_env, body_cache, - promoted, + promoted_cache, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, @@ -186,7 +186,7 @@ fn type_check_internal<'a, 'tcx, R>( mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, body_cache: &ReadOnlyBodyCache<'a, 'tcx>, - promoted: &'a IndexVec>, + promoted_cache: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -204,7 +204,7 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted); + let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted_cache); verifier.visit_body(body_cache); verifier.errors_reported }; @@ -261,7 +261,7 @@ enum FieldAccessError { struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, - promoted: &'b IndexVec>, + promoted_cache: &'b IndexVec>, last_span: Span, mir_def_id: DefId, errors_reported: bool, @@ -401,11 +401,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn new( cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, - promoted: &'b IndexVec>, + promoted_cache: &'b IndexVec>, ) -> Self { TypeVerifier { body, - promoted, + promoted_cache, mir_def_id: cx.mir_def_id, cx, last_span: body.span, @@ -464,10 +464,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { match kind { StaticKind::Promoted(promoted, _) => { if !self.errors_reported { - let promoted_body = &self.promoted[*promoted]; - self.sanitize_promoted(promoted_body, location); + let promoted_body_cache = &self.promoted_cache[*promoted]; + self.sanitize_promoted(promoted_body_cache, location); - let promoted_ty = promoted_body.return_ty(); + let promoted_ty = promoted_body_cache.return_ty(); check_err(self, place, promoted_ty, san_ty); } } @@ -535,12 +535,12 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place_ty } - fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) { + fn sanitize_promoted(&mut self, promoted_body_cache: &ReadOnlyBodyCache<'b, 'tcx>, location: Location) { // Determine the constraints from the promoted MIR by running the type // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. - let parent_body = mem::replace(&mut self.body, promoted_body); + let parent_body = mem::replace(&mut self.body, &promoted_body_cache); // Use new sets of constraints and closure bounds so that we can // modify their locations. @@ -548,7 +548,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let mut constraints = Default::default(); let mut closure_bounds = Default::default(); let mut liveness_constraints = LivenessValues::new( - Rc::new(RegionValueElements::new(promoted_body)), + Rc::new(RegionValueElements::new(&promoted_body_cache)), ); // Don't try to add borrow_region facts for the promoted MIR @@ -570,12 +570,12 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { swap_constraints(self); - self.visit_body(promoted_body); + self.visit_body(promoted_body_cache); if !self.errors_reported { // if verifier failed, don't do further checks to avoid ICEs - self.cx.typeck_mir(promoted_body); + self.cx.typeck_mir(&promoted_body_cache); } self.body = parent_body; From 0a193712431d61cd70dda517b88c564a411b3541 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 25 Oct 2019 09:36:59 -0400 Subject: [PATCH 24/47] Add predecessors fn to ReadOnlyBodyCache, fix more Body -> (ReadOnly)BodyCache type errors --- src/librustc/mir/cache.rs | 6 ++++- src/librustc/mir/visit.rs | 2 +- .../borrow_check/mutability_errors.rs | 8 +++---- .../nll/type_check/liveness/local_use_map.rs | 10 ++++----- .../nll/type_check/liveness/polonius.rs | 8 +++---- .../dataflow/impls/storage_liveness.rs | 22 +++++++++---------- src/librustc_mir/monomorphize/collector.rs | 5 +++-- src/librustc_mir/util/collect_writes.rs | 4 ++-- src/librustc_mir/util/liveness.rs | 16 +++++++------- src/librustc_mir/util/patch.rs | 18 +++++++-------- 10 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 24d1f9e373bb0..b668247060647 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -14,7 +14,6 @@ pub struct Cache { predecessors: Option>>, } - //impl<'tcx, T> rustc_serialize::Encodable for Cache<'tcx, T> { // fn encode(&self, s: &mut S) -> Result<(), S::Error> { // Encodable::encode(&(), s) @@ -261,6 +260,11 @@ pub struct ReadOnlyBodyCache<'a, 'tcx> { } impl ReadOnlyBodyCache<'a, 'tcx> { + #[inline] + pub fn predecessors(&self) -> &IndexVec> { + self.cache.predecessors.as_ref().unwrap() + } + #[inline] pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { self.cache.unwrap_predecessors_for(bb) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 7877466fbf6a6..c464247c4b4c9 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -812,7 +812,7 @@ macro_rules! make_mir_visitor { fn visit_location( &mut self, - body_cache: & $($mutability)? BodyCache<&'_ $($mutability)? Body<'tcx>>, + body_cache: body_cache_type!($($mutability)? '_, 'tcx), location: Location ) { let basic_block = & $($mutability)? body_cache[location.block]; diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 654666882cca4..44e139889c938 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -1,6 +1,6 @@ use rustc::hir; use rustc::hir::Node; -use rustc::mir::{self, Body, ClearCrossCrate, Local, LocalInfo, Location}; +use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyCache}; use rustc::mir::{Mutability, Place, PlaceRef, PlaceBase, ProjectionElem}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_index::vec::Idx; @@ -529,14 +529,14 @@ fn suggest_ampmut_self<'tcx>( // by trying (3.), then (2.) and finally falling back on (1.). fn suggest_ampmut<'tcx>( tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, local: Local, local_decl: &mir::LocalDecl<'tcx>, opt_ty_info: Option, ) -> (Span, String) { - let locations = body.find_assignments(local); + let locations = body_cache.find_assignments(local); if !locations.is_empty() { - let assignment_rhs_span = body.source_info(locations[0]).span; + let assignment_rhs_span = body_cache.source_info(locations[0]).span; if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { if let (true, Some(ws_pos)) = ( src.starts_with("&'"), diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 7dee00b3eca67..181508a983a16 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -1,7 +1,7 @@ use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Body, Local, Location}; +use rustc::mir::{Local, Location, ReadOnlyBodyCache}; use rustc_index::vec::{Idx, IndexVec}; use rustc_data_structures::vec_linked_list as vll; @@ -60,9 +60,9 @@ impl LocalUseMap { crate fn build( live_locals: &Vec, elements: &RegionValueElements, - body: &Body<'_>, + body_cache: &ReadOnlyBodyCache<'_, '_>, ) -> Self { - let nones = IndexVec::from_elem_n(None, body.local_decls.len()); + let nones = IndexVec::from_elem_n(None, body_cache.local_decls.len()); let mut local_use_map = LocalUseMap { first_def_at: nones.clone(), first_use_at: nones.clone(), @@ -75,11 +75,11 @@ impl LocalUseMap { } let mut locals_with_use_data: IndexVec = - IndexVec::from_elem_n(false, body.local_decls.len()); + IndexVec::from_elem_n(false, body_cache.local_decls.len()); live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } - .visit_body(body); + .visit_body(body_cache); local_use_map } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index 526ad7fb905bb..3320815688f27 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -3,7 +3,7 @@ use crate::dataflow::indexes::MovePathIndex; use crate::dataflow::move_paths::{LookupResult, MoveData}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; -use rustc::mir::{Body, Local, Location, Place}; +use rustc::mir::{Local, Location, Place, ReadOnlyBodyCache}; use rustc::ty::subst::GenericArg; use rustc::ty::Ty; @@ -97,7 +97,7 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - body: &Body<'tcx>, + body_cache: &ReadOnlyBodyCache<'_, 'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, drop_used: &mut Vec<(Local, Location)>, @@ -113,14 +113,14 @@ pub(super) fn populate_access_facts( location_table, move_data, } - .visit_body(body); + .visit_body(body_cache); facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| { (local, location_table.mid_index(location)) })); } - for (local, local_decl) in body.local_decls.iter_enumerated() { + for (local, local_decl) in body_cache.local_decls.iter_enumerated() { add_var_uses_regions(typeck, local, local_decl.ty); } } diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 1b81032bfe62f..2e164765043d4 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -75,24 +75,24 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. pub struct RequiresStorage<'mir, 'tcx> { - body: &'mir Body<'tcx>, + body_cache: &'mir ReadOnlyBodyCache<'mir, 'tcx>, borrowed_locals: RefCell>>, } impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { pub fn new( - body: &'mir Body<'tcx>, + body_cache: &'mir ReadOnlyBodyCache<'mir, 'tcx>, borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>, ) -> Self { RequiresStorage { - body, - borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body)), + body_cache, + borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body_cache)), } } pub fn body(&self) -> &Body<'tcx> { - self.body + &self.body_cache } } @@ -100,13 +100,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { type Idx = Local; fn name() -> &'static str { "requires_storage" } fn bits_per_block(&self) -> usize { - self.body.local_decls.len() + self.body_cache.local_decls.len() } fn start_block_effect(&self, _sets: &mut BitSet) { // Nothing is live on function entry (generators only have a self // argument, and we don't care about that) - assert_eq!(1, self.body.arg_count); + assert_eq!(1, self.body_cache.arg_count); } fn before_statement_effect(&self, sets: &mut GenKillSet, loc: Location) { @@ -114,7 +114,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { // statement. self.check_for_borrow(sets, loc); - let stmt = &self.body[loc.block].statements[loc.statement_index]; + let stmt = &self.body_cache[loc.block].statements[loc.statement_index]; match stmt.kind { StatementKind::StorageDead(l) => sets.kill(l), StatementKind::Assign(box(ref place, _)) @@ -146,7 +146,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { if let TerminatorKind::Call { destination: Some((Place { base: PlaceBase::Local(local), .. }, _)), .. - } = self.body[loc.block].terminator().kind { + } = self.body_cache[loc.block].terminator().kind { sets.gen(local); } } @@ -159,7 +159,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { if let TerminatorKind::Call { destination: Some((ref place, _)), .. - } = self.body[loc.block].terminator().kind { + } = self.body_cache[loc.block].terminator().kind { if let Some(local) = place.as_local() { sets.kill(local); } @@ -187,7 +187,7 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { sets, borrowed_locals: &self.borrowed_locals, }; - visitor.visit_location(self.body, loc); + visitor.visit_location(&self.body_cache, loc); } /// Gen locals that are newly borrowed. This includes borrowing any part of diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a4c4c7ff616d9..285bdf50d4a25 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -186,7 +186,7 @@ use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::session::config::EntryFnType; -use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; +use rustc::mir::{self, BodyCache, Location, PlaceBase, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::{MonoItem, InstantiationMode}; use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled}; @@ -1249,13 +1249,14 @@ fn collect_neighbours<'tcx>( ) { debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); + let body_cache = BodyCache::new(body).read_only(); MirNeighborCollector { tcx, body: &body, output, param_substs: instance.substs, - }.visit_body(&body); + }.visit_body(&body_cache); } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs index c8804dfbaf261..0092c3c86d713 100644 --- a/src/librustc_mir/util/collect_writes.rs +++ b/src/librustc_mir/util/collect_writes.rs @@ -1,5 +1,5 @@ use rustc::mir::{Local, Location}; -use rustc::mir::Body; +use rustc::mir::ReadOnlyBodyCache; use rustc::mir::visit::PlaceContext; use rustc::mir::visit::Visitor; @@ -9,7 +9,7 @@ crate trait FindAssignments { fn find_assignments(&self, local: Local) -> Vec; } -impl<'tcx> FindAssignments for Body<'tcx>{ +impl<'a, 'tcx> FindAssignments for ReadOnlyBodyCache<'a, 'tcx>{ fn find_assignments(&self, local: Local) -> Vec{ let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]}; visitor.visit_body(self); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index d313cba6bdf1a..87e6291a45486 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -57,17 +57,17 @@ pub struct LivenessResult { /// Computes which local variables are live within the given function /// `mir`, including drops. pub fn liveness_of_locals( - body: &Body<'_>, + body_cache: &ReadOnlyBodyCache<'_, '_>, ) -> LivenessResult { - let num_live_vars = body.local_decls.len(); + let num_live_vars = body_cache.local_decls.len(); - let def_use: IndexVec<_, DefsUses> = body + let def_use: IndexVec<_, DefsUses> = body_cache .basic_blocks() .iter() .map(|b| block(b, num_live_vars)) .collect(); - let mut outs: IndexVec<_, LiveVarSet> = body + let mut outs: IndexVec<_, LiveVarSet> = body_cache .basic_blocks() .indices() .map(|_| LiveVarSet::new_empty(num_live_vars)) @@ -83,18 +83,18 @@ pub fn liveness_of_locals( // FIXME(ecstaticmorse): Reverse post-order on the reverse CFG may generate a better iteration // order when cycles are present, but the overhead of computing the reverse CFG may outweigh // any benefits. Benchmark this and find out. - let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks().len()); - for (bb, _) in traversal::postorder(body) { + let mut dirty_queue: WorkQueue = WorkQueue::with_none(body_cache.basic_blocks().len()); + for (bb, _) in traversal::postorder(body_cache) { dirty_queue.insert(bb); } // Add blocks which are not reachable from START_BLOCK to the work queue. These blocks will // be processed after the ones added above. - for bb in body.basic_blocks().indices() { + for bb in body_cache.basic_blocks().indices() { dirty_queue.insert(bb); } - let predecessors = body.unwrap_predecessors(); + let predecessors = body_cache.predecessors(); while let Some(bb) = dirty_queue.pop() { // bits = use ∪ (bits - def) diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index a5f7e5401573b..01be0f598ed21 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -127,21 +127,21 @@ impl<'tcx> MirPatch<'tcx> { self.make_nop.push(loc); } - pub fn apply(self, body: &mut Body<'tcx>) { + pub fn apply(self, body_cache: &mut BodyCache<&'_ mut Body<'tcx>>) { debug!("MirPatch: make nops at: {:?}", self.make_nop); for loc in self.make_nop { - body.make_statement_nop(loc); + body_cache.make_statement_nop(loc); } debug!("MirPatch: {:?} new temps, starting from index {}: {:?}", - self.new_locals.len(), body.local_decls.len(), self.new_locals); + self.new_locals.len(), body_cache.local_decls.len(), self.new_locals); debug!("MirPatch: {} new blocks, starting from index {}", - self.new_blocks.len(), body.basic_blocks().len()); - body.basic_blocks_mut().extend(self.new_blocks); - body.local_decls.extend(self.new_locals); + self.new_blocks.len(), body_cache.basic_blocks().len()); + body_cache.basic_blocks_mut().extend(self.new_blocks); + body_cache.local_decls.extend(self.new_locals); for (src, patch) in self.patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); - body[src].terminator_mut().kind = patch; + body_cache[src].terminator_mut().kind = patch; } } @@ -159,9 +159,9 @@ impl<'tcx> MirPatch<'tcx> { stmt, loc, delta); loc.statement_index += delta; let source_info = Self::source_info_for_index( - &body[loc.block], loc + &body_cache[loc.block], loc ); - body[loc.block].statements.insert( + body_cache[loc.block].statements.insert( loc.statement_index, Statement { source_info, kind: stmt From 3642a71da21005366e5ab270cf4a347d5abeca54 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 25 Oct 2019 09:53:59 -0400 Subject: [PATCH 25/47] Fix typo caused by rebasing --- src/librustc_metadata/rmeta/decoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index bbf28418f11a6..820783bab6d27 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> CrateMetadata { fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { self.root.per_def.mir.get(self, id) - self.entry_unless_proc_macro(id) + .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) From 38c0887c769b227c827c76d80fa76fc5e4493516 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 25 Oct 2019 10:01:08 -0400 Subject: [PATCH 26/47] Fix remaining Body -> (ReadOnly)BodyCache type errors in librustc_mir outside of librustc_mir/transform --- src/librustc_mir/shim.rs | 11 +++++++---- src/librustc_mir/util/def_use.rs | 19 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 734e1a5972e45..c80b6e38ac504 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -202,12 +202,14 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) sig.inputs().len(), span); + let mut body_cache = BodyCache::new(&mut body); + if let Some(..) = ty { // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::from(Local::new(1+0)); if tcx.sess.opts.debugging_opts.mir_emit_retag { // Function arguments should be retagged, and we make this one raw. - body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { + body_cache.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, kind: StatementKind::Retag(RetagKind::Raw, box(dropee_ptr.clone())), }); @@ -215,8 +217,8 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let patch = { let param_env = tcx.param_env(def_id).with_reveal_all(); let mut elaborator = DropShimElaborator { - body: &body, - patch: MirPatch::new(&body), + body: body_cache.body(), + patch: MirPatch::new(body_cache.body()), tcx, param_env }; @@ -233,9 +235,10 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) ); elaborator.patch }; - patch.apply(&mut body); + patch.apply(&mut body_cache); } + // TODO(pfaia) return owning body cache... body } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 1611caddad1a6..11b61bcd48444 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,6 +1,6 @@ //! Def-use analysis. -use rustc::mir::{Body, Local, Location, PlaceElem, VarDebugInfo}; +use rustc::mir::{Body, BodyCache, Local, Location, PlaceElem, ReadOnlyBodyCache, VarDebugInfo}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc::ty::TyCtxt; use rustc_index::vec::IndexVec; @@ -30,7 +30,7 @@ impl DefUseAnalysis { } } - pub fn analyze(&mut self, body: &Body<'_>) { + pub fn analyze(&mut self, body_cache: &ReadOnlyBodyCache<'_, '_>) { self.clear(); let mut finder = DefUseFinder { @@ -38,7 +38,7 @@ impl DefUseAnalysis { var_debug_info_index: 0, in_var_debug_info: false, }; - finder.visit_body(body); + finder.visit_body(body_cache); self.info = finder.info } @@ -55,28 +55,28 @@ impl DefUseAnalysis { fn mutate_defs_and_uses( &self, local: Local, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<&mut Body<'tcx>>, new_local: Local, tcx: TyCtxt<'tcx>, ) { - let mut visitor = MutateUseVisitor::new(local, new_local, body, tcx); + let mut visitor = MutateUseVisitor::new(local, new_local, tcx); let info = &self.info[local]; for place_use in &info.defs_and_uses { - visitor.visit_location(body, place_use.location) + visitor.visit_location(body_cache, place_use.location) } // Update debuginfo as well, alongside defs/uses. for &i in &info.var_debug_info_indices { - visitor.visit_var_debug_info(&mut body.var_debug_info[i]); + visitor.visit_var_debug_info(&mut body_cache.var_debug_info[i]); } } // FIXME(pcwalton): this should update the def-use chains. pub fn replace_all_defs_and_uses_with(&self, local: Local, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<&mut Body<'tcx>>, new_local: Local, tcx: TyCtxt<'tcx>) { - self.mutate_defs_and_uses(local, body, new_local, tcx) + self.mutate_defs_and_uses(local, body_cache, new_local, tcx) } } @@ -156,7 +156,6 @@ impl MutateUseVisitor<'tcx> { fn new( query: Local, new_local: Local, - _: &Body<'tcx>, tcx: TyCtxt<'tcx>, ) -> MutateUseVisitor<'tcx> { MutateUseVisitor { query, new_local, tcx } From fc6b58d0a809b4994cd1a633ccb04e89234ff0b8 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 26 Oct 2019 01:41:17 -0400 Subject: [PATCH 27/47] Simplify BodyCache impl and fix all remaining type errors in librustc_mir (lifetime errors still exist) --- src/librustc/arena.rs | 8 +- src/librustc/mir/cache.rs | 184 +++++++-------- src/librustc/mir/mod.rs | 4 +- src/librustc/mir/visit.rs | 4 +- src/librustc/query/mod.rs | 26 ++- src/librustc/ty/context.rs | 14 +- src/librustc/ty/mod.rs | 10 +- src/librustc_codegen_ssa/base.rs | 3 - src/librustc_codegen_ssa/mir/analyze.rs | 16 +- src/librustc_codegen_ssa/mir/block.rs | 58 ++--- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 17 +- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 4 +- src/librustc_codegen_ssa/mir/statement.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 7 +- src/librustc_metadata/rmeta/mod.rs | 4 +- src/librustc_mir/borrow_check/borrow_set.rs | 6 +- src/librustc_mir/borrow_check/mod.rs | 21 +- .../borrow_check/mutability_errors.rs | 4 +- .../borrow_check/nll/invalidation.rs | 4 +- src/librustc_mir/borrow_check/nll/mod.rs | 20 +- .../borrow_check/nll/region_infer/values.rs | 2 +- src/librustc_mir/borrow_check/nll/renumber.rs | 6 +- .../nll/type_check/liveness/local_use_map.rs | 2 +- .../nll/type_check/liveness/mod.rs | 4 +- .../nll/type_check/liveness/polonius.rs | 2 +- .../nll/type_check/liveness/trace.rs | 8 +- .../borrow_check/nll/type_check/mod.rs | 18 +- src/librustc_mir/borrow_check/used_muts.rs | 2 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/const_eval.rs | 4 +- .../dataflow/impls/storage_liveness.rs | 8 +- src/librustc_mir/interpret/eval_context.rs | 6 +- src/librustc_mir/monomorphize/collector.rs | 8 +- src/librustc_mir/shim.rs | 25 +- src/librustc_mir/transform/add_call_guards.rs | 14 +- .../transform/add_moves_for_packed_drops.rs | 12 +- src/librustc_mir/transform/add_retag.rs | 6 +- src/librustc_mir/transform/check_unsafety.rs | 2 +- .../transform/cleanup_post_borrowck.rs | 6 +- src/librustc_mir/transform/const_prop.rs | 41 ++-- src/librustc_mir/transform/copy_prop.rs | 41 ++-- src/librustc_mir/transform/deaggregator.rs | 4 +- src/librustc_mir/transform/dump_mir.rs | 4 +- src/librustc_mir/transform/elaborate_drops.rs | 10 +- src/librustc_mir/transform/erase_regions.rs | 4 +- src/librustc_mir/transform/generator.rs | 215 +++++++++--------- src/librustc_mir/transform/inline.rs | 46 ++-- src/librustc_mir/transform/instcombine.rs | 11 +- src/librustc_mir/transform/mod.rs | 42 ++-- src/librustc_mir/transform/no_landing_pads.rs | 6 +- src/librustc_mir/transform/promote_consts.rs | 67 +++--- .../transform/remove_noop_landing_pads.rs | 26 +-- src/librustc_mir/transform/rustc_peek.rs | 32 +-- src/librustc_mir/transform/simplify.rs | 46 ++-- .../transform/simplify_branches.rs | 4 +- .../transform/uniform_array_move_out.rs | 26 +-- src/librustc_mir/util/collect_writes.rs | 2 +- src/librustc_mir/util/def_use.rs | 6 +- src/librustc_mir/util/liveness.rs | 4 +- src/librustc_mir/util/patch.rs | 2 +- 63 files changed, 588 insertions(+), 612 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 1d6a3420ed952..364a35f1b6faa 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -23,17 +23,17 @@ macro_rules! arena_types { [] generics: rustc::ty::Generics, [] trait_def: rustc::ty::TraitDef, [] adt_def: rustc::ty::AdtDef, - [] steal_mir: rustc::ty::steal::Steal>, - [] mir: rustc::mir::Body<$tcx>, + [] steal_mir: rustc::ty::steal::Steal>, + [] mir: rustc::mir::BodyCache<$tcx>, [] steal_promoted: rustc::ty::steal::Steal< rustc_index::vec::IndexVec< rustc::mir::Promoted, - rustc::mir::Body<$tcx> + rustc::mir::BodyCache<$tcx> > >, [] promoted: rustc_index::vec::IndexVec< rustc::mir::Promoted, - rustc::mir::Body<$tcx> + rustc::mir::BodyCache<$tcx> >, [] tables: rustc::ty::TypeckTables<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index b668247060647..8958a31b51cb5 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -1,7 +1,7 @@ use rustc_index::vec::IndexVec; -//use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -//use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; -//use crate::ich::StableHashingContext; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +use crate::ich::StableHashingContext; use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::graph::dominators::{dominators, Dominators}; @@ -14,23 +14,23 @@ pub struct Cache { predecessors: Option>>, } -//impl<'tcx, T> rustc_serialize::Encodable for Cache<'tcx, T> { -// fn encode(&self, s: &mut S) -> Result<(), S::Error> { -// Encodable::encode(&(), s) -// } -//} -// -//impl<'tcx, T> rustc_serialize::Decodable for Cache<'tcx, T> { -// fn decode(d: &mut D) -> Result { -// Decodable::decode(d).map(|_v: ()| Self::new()) -// } -//} -// -//impl<'a, 'tcx, T> HashStable> for Cache<'tcx, T> { -// fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { -// // Do nothing. -// } -//} +impl rustc_serialize::Encodable for Cache { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + Encodable::encode(&(), s) + } +} + +impl rustc_serialize::Decodable for Cache { + fn decode(d: &mut D) -> Result { + Decodable::decode(d).map(|_v: ()| Self::new()) + } +} + +impl<'a> HashStable> for Cache { + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + // Do nothing. + } +} macro_rules! get_predecessors { (mut $self:ident, $block:expr, $body:expr) => { @@ -98,13 +98,13 @@ impl Cache { #[inline] /// This will recompute the predecessors cache if it is not available - pub fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec> { + fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec> { self.ensure_predecessors(body); self.predecessors.as_ref().unwrap() } #[inline] - pub fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] { + fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] { &self.predecessors(body)[bb] } @@ -136,55 +136,58 @@ impl Cache { } } -pub struct BodyCache { +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub struct BodyCache<'tcx> { cache: Cache, - body: T, + body: Body<'tcx>, } -impl BodyCache { - pub fn new(body: T) -> Self { +impl BodyCache<'tcx> { + pub fn new(body: Body<'tcx>) -> Self { Self { cache: Cache::new(), - body + body, } } } -impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> { - #[inline] - pub fn predecessors_for(&mut self, bb: BasicBlock) -> &[BasicBlock] { - self.cache.predecessors_for(bb, self.body) +impl BodyCache<'tcx> { + pub fn ensure_predecessors(&mut self) { + self.cache.ensure_predecessors(&self.body); } - #[inline] - pub fn body(&self) -> &'a Body<'tcx> { - self.body + pub fn predecessors(&mut self) -> &IndexVec> { + self.cache.predecessors(&self.body) } - #[inline] - pub fn read_only(mut self) -> ReadOnlyBodyCache<'a, 'tcx> { - self.cache.ensure_predecessors(self.body); + pub fn read_only(&self) -> ReadOnlyBodyCache<'_, '_> { + assert!(self.cache.predecessors.is_some(), ""); ReadOnlyBodyCache { - cache: self.cache, - body: self.body, + cache: &self.cache, + body: &self.body, } } - #[inline] - pub fn basic_blocks(&self) -> &IndexVec> { - &self.body.basic_blocks + pub fn body(&self) -> &Body<'tcx> { + &self.body } -} -impl<'a, 'tcx> Deref for BodyCache<&'a Body<'tcx>> { - type Target = Body<'tcx>; + pub fn body_mut(&mut self) -> &mut Body<'tcx> { + &mut self.body + } - fn deref(&self) -> &Self::Target { - self.body + pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { + self.cache.basic_blocks_mut(&mut self.body) + } + + pub fn basic_blocks_and_local_decls_mut( + &mut self + ) -> (&mut IndexVec>, &mut LocalDecls<'tcx>) { + self.cache.basic_blocks_and_local_decls_mut(&mut self.body) } } -impl<'a, 'tcx> Index for BodyCache<&'a Body<'tcx>> { +impl<'tcx> Index for BodyCache<'tcx> { type Output = BasicBlockData<'tcx>; #[inline] @@ -193,69 +196,29 @@ impl<'a, 'tcx> Index for BodyCache<&'a Body<'tcx>> { } } -impl<'a, 'tcx> BodyCache<&'a mut Body<'tcx>> { - #[inline] - pub fn body(&self) -> &Body<'tcx> { - self.body - } - - #[inline] - pub fn body_mut(&mut self) -> &mut Body<'tcx> { - self.body - } - - #[inline] - pub fn read_only(mut self) -> ReadOnlyBodyCache<'a, 'tcx> { - self.cache.ensure_predecessors(self.body); - ReadOnlyBodyCache { - cache: self.cache, - body: self.body, - } - } - - #[inline] - pub fn basic_blocks(&self) -> &IndexVec> { - &self.body.basic_blocks - } - - #[inline] - pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { - self.cache.basic_blocks_mut(&mut self.body) +impl<'tcx> IndexMut for BodyCache<'tcx> { + fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output { + &mut self.basic_blocks_mut()[index] } } -impl<'a, 'tcx> Deref for BodyCache<&'a mut Body<'tcx>> { +impl<'tcx> Deref for BodyCache<'tcx> { type Target = Body<'tcx>; fn deref(&self) -> &Self::Target { - self.body - } -} - -impl<'a, 'tcx> DerefMut for BodyCache<&'a mut Body<'tcx>> { - fn deref_mut(&mut self) -> &mut Body<'tcx> { - self.body - } -} - -impl<'a, 'tcx> Index for BodyCache<&'a mut Body<'tcx>> { - type Output = BasicBlockData<'tcx>; - - #[inline] - fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { - &self.body[index] + &self.body } } -impl<'a, 'tcx> IndexMut for BodyCache<&'a mut Body<'tcx>> { - fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output { - self.cache.invalidate_predecessors(); - &mut self.body.basic_blocks[index] +impl<'tcx> DerefMut for BodyCache<'tcx> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.body } } +#[derive(Copy, Clone, Debug)] pub struct ReadOnlyBodyCache<'a, 'tcx> { - cache: Cache, + cache: &'a Cache, body: &'a Body<'tcx>, } @@ -289,13 +252,6 @@ impl ReadOnlyBodyCache<'a, 'tcx> { pub fn dominators(&self) -> Dominators { dominators(self) } - - pub fn to_owned(self) -> BodyCache<&'a Body<'tcx>> { - BodyCache { - cache: self.cache, - body: self.body, - } - } } impl graph::DirectedGraph for ReadOnlyBodyCache<'a, 'tcx> { @@ -358,4 +314,20 @@ impl Index for ReadOnlyBodyCache<'a, 'tcx> { fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { &self.body[index] } -} \ No newline at end of file +} + +CloneTypeFoldableAndLiftImpls! { + Cache, +} + +impl_stable_hash_for!(struct BodyCache<'tcx> { + cache, + body, +}); + +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for BodyCache<'tcx> { + cache, + body + } +} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 57d396ae93302..b6d1c78cc4f57 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -107,7 +107,7 @@ pub struct Body<'tcx> { pub yield_ty: Option>, /// Generator drop glue. - pub generator_drop: Option>>, + pub generator_drop: Option>>, /// The layout of a generator. Produced by the state transformation. pub generator_layout: Option>, @@ -2600,7 +2600,7 @@ impl Location { pub fn is_predecessor_of<'tcx>( &self, other: Location, - body_cache: &ReadOnlyBodyCache<'_, 'tcx> + body_cache: ReadOnlyBodyCache<'_, 'tcx> ) -> bool { // If we are in the same block as the other location and are an earlier statement // then we are a predecessor of `other`. diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index c464247c4b4c9..68694f1b71711 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -67,10 +67,10 @@ use syntax_pos::Span; macro_rules! body_cache_type { (mut $a:lifetime, $tcx:lifetime) => { - &mut BodyCache<& $a mut Body<$tcx>> + &mut BodyCache<$tcx> }; ($a:lifetime, $tcx:lifetime) => { - &ReadOnlyBodyCache<$a, $tcx> + ReadOnlyBodyCache<$a, $tcx> }; } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index d715ddb1b81de..cdfdcee5823ec 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -106,42 +106,46 @@ rustc_queries! { /// Fetch the MIR for a given `DefId` right after it's built - this includes /// unreachable code. - query mir_built(_: DefId) -> &'tcx Steal> {} + query mir_built(_: DefId) -> &'tcx Steal> {} /// Fetch the MIR for a given `DefId` up till the point where it is /// ready for const evaluation. /// /// See the README for the `mir` module for details. - query mir_const(_: DefId) -> &'tcx Steal> { + query mir_const(_: DefId) -> &'tcx Steal> { no_hash } query mir_validated(_: DefId) -> ( - &'tcx Steal>, - &'tcx Steal>> + &'tcx Steal>, + &'tcx Steal>> ) { no_hash } /// MIR after our optimization passes have run. This is MIR that is ready /// for codegen. This is also the only query that can fetch non-local MIR, at present. - query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { + query optimized_mir(key: DefId) -> &'tcx mir::BodyCache<'tcx> { cache_on_disk_if { key.is_local() } load_cached(tcx, id) { - let mir: Option> = tcx.queries.on_disk_cache - .try_load_query_result(tcx, id); - mir.map(|x| &*tcx.arena.alloc(x)) + let mir: Option> + = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); + mir.map(|x| { + let cache = tcx.arena.alloc(x); + cache.ensure_predecessors(); + &*cache + }) } } - query promoted_mir(key: DefId) -> &'tcx IndexVec> { + query promoted_mir(key: DefId) -> &'tcx IndexVec> { cache_on_disk_if { key.is_local() } load_cached(tcx, id) { let promoted: Option< rustc_index::vec::IndexVec< crate::mir::Promoted, - crate::mir::Body<'tcx> + crate::mir::BodyCache<'tcx> >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); promoted.map(|p| &*tcx.arena.alloc(p)) } @@ -502,7 +506,7 @@ rustc_queries! { /// in the case of closures, this will be redirected to the enclosing function. query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {} - query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> { + query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyCache<'tcx> { no_force desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 776ae7dc141ce..07d86a5f86a4f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -22,7 +22,7 @@ use crate::middle::cstore::EncodedMetadata; use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::{Body, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::{BodyCache, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -1083,17 +1083,17 @@ impl<'tcx> TyCtxt<'tcx> { &self.hir_map } - pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal> { - self.arena.alloc(Steal::new(mir)) + pub fn alloc_steal_mir(self, mir_cache: BodyCache<'tcx>) -> &'tcx Steal> { + self.arena.alloc(Steal::new(mir_cache)) } - pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> - &'tcx Steal>> { + pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> + &'tcx Steal>> { self.arena.alloc(Steal::new(promoted)) } - pub fn intern_promoted(self, promoted: IndexVec>) -> - &'tcx IndexVec> { + pub fn intern_promoted(self, promoted: IndexVec>) -> + &'tcx IndexVec> { self.arena.alloc(promoted) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8ccfc467f4a0b..f8feff0def972 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -18,7 +18,7 @@ use crate::infer::canonical::Canonical; use crate::middle::cstore::CrateStoreDyn; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; -use crate::mir::Body; +use crate::mir::ReadOnlyBodyCache; use crate::mir::interpret::{GlobalId, ErrorHandled}; use crate::mir::GeneratorLayout; use crate::session::CrateDisambiguator; @@ -2985,10 +2985,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. - pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { + pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyCache<'tcx, 'tcx> { match instance { ty::InstanceDef::Item(did) => { - self.optimized_mir(did) + self.optimized_mir(did).read_only() } ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) | @@ -2998,7 +2998,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) => { - self.mir_shims(instance) + self.mir_shims(instance).read_only() } } } @@ -3023,7 +3023,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> { - self.optimized_mir(def_id).generator_layout.as_ref().unwrap() + self.optimized_mir(def_id).body().generator_layout.as_ref().unwrap() } /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index f50be08c15c1d..e460a4a2e8c97 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,7 +31,6 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::weak_lang_items; -use rustc::mir::BodyCache; use rustc::mir::mono::{CodegenUnitNameBuilder, CodegenUnit, MonoItem}; use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; @@ -375,8 +374,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let lldecl = cx.get_fn(instance); let mir = cx.tcx().instance_mir(instance.def); - // TODO(nashenas88) move this into instance_mir before merging PR - let mir = BodyCache::new(mir); mir::codegen_mir::(cx, lldecl, mir, instance, sig); } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index fff0117834101..830b7da8c0373 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -16,8 +16,8 @@ use syntax_pos::DUMMY_SP; use super::FunctionCx; use crate::traits::*; -pub fn non_ssa_locals<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - fx: &FunctionCx<'a, 'b, 'tcx, Bx> +pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + fx: &FunctionCx<'a, 'tcx, Bx> ) -> BitSet { let mut analyzer = LocalAnalyzer::new(fx); @@ -56,8 +56,8 @@ pub fn non_ssa_locals<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( analyzer.non_ssa_locals } -struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { - fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>, +struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { + fx: &'mir FunctionCx<'a, 'tcx, Bx>, dominators: Dominators, non_ssa_locals: BitSet, // The location of the first visited direct assignment to each @@ -65,8 +65,8 @@ struct LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { first_assignment: IndexVec, } -impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> { - fn new(fx: &'mir FunctionCx<'a, 'b, 'tcx, Bx>) -> Self { +impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { + fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self { let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); let dominators = fx.mir.dominators(); @@ -232,8 +232,8 @@ impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, ' } -impl<'mir, 'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> - for LocalAnalyzer<'mir, 'a, 'b, 'tcx, Bx> +impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> + for LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn visit_assign(&mut self, place: &mir::Place<'tcx>, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index e2cae0aa56516..f661e7bba806f 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -33,19 +33,19 @@ struct TerminatorCodegenHelper<'a, 'tcx> { impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Returns the associated funclet from `FunctionCx::funclets` for the /// `funclet_bb` member if it is not `None`. - fn funclet<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, - ) -> Option<&'d Bx::Funclet> { + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + ) -> Option<&'c Bx::Funclet> { match self.funclet_bb { Some(funcl) => fx.funclets[funcl].as_ref(), None => None, } } - fn lltarget<'b, 'c, 'd, Bx: BuilderMethods<'b, 'tcx>>( + fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, target: mir::BasicBlock ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; @@ -63,9 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } /// Create a basic block. - fn llblock<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, target: mir::BasicBlock ) -> Bx::BasicBlock { let (lltarget, is_cleanupret) = self.lltarget(fx, target); @@ -83,9 +83,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } } - fn funclet_br<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, bx: &mut Bx, target: mir::BasicBlock, ) { @@ -101,9 +101,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional /// return destination `destination` and the cleanup function `cleanup`. - fn do_call<'d, 'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - fx: &'d mut FunctionCx<'b, 'c, 'tcx, Bx>, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, bx: &mut Bx, fn_abi: FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, @@ -153,7 +153,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { // a loop. fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( &self, - mir: &mir::ReadOnlyBodyCache<'_, 'tcx>, + mir: mir::ReadOnlyBodyCache<'_, 'tcx>, bx: &mut Bx, targets: &[mir::BasicBlock], ) { @@ -171,7 +171,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } /// Codegen implementations for some terminator variants. -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Generates code for a `Resume` terminator. fn codegen_resume_terminator<'c>( &mut self, @@ -216,7 +216,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let lltrue = helper.llblock(self, targets[0]); let llfalse = helper.llblock(self, targets[1]); if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool if let [0] = values[..] { bx.cond_br(discr.immediate(), llfalse, lltrue); @@ -230,11 +230,11 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { ); let llval = bx.const_uint_big(switch_llty, values[0]); let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); - helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); bx.cond_br(cmp, lltrue, llfalse); } } else { - helper.maybe_sideeffect(&self.mir, &mut bx, targets.as_slice()); + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), @@ -330,7 +330,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return } @@ -361,7 +361,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { FnAbi::of_instance(&bx, drop_fn)) } }; - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); @@ -397,7 +397,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Don't codegen the panic block if success if known. if const_cond == Some(expected) { - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -408,7 +408,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { // Create the failure block and the conditional branch to it. let lltarget = helper.llblock(self, target); let panic_block = self.new_block("panic"); - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -493,7 +493,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; self.codegen_transmute(&mut bx, &args[0], dest); - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { // If we are trying to transmute to an uninhabited type, @@ -521,7 +521,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { Some(ty::InstanceDef::DropGlue(_, None)) => { // Empty drop glue; a no-op. let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -553,7 +553,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { let llfn = bx.get_fn_addr(instance); if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(&self.mir, &mut bx, &[*target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); } // Codegen the actual panic invoke/call. helper.do_call( @@ -568,7 +568,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } else { // a NOP let target = destination.as_ref().unwrap().1; - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) } return; @@ -682,7 +682,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } if let Some((_, target)) = *destination { - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { bx.unreachable(); @@ -776,7 +776,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { }; if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(&self.mir, &mut bx, &[*target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); } helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), @@ -784,13 +784,13 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } } -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_block( &mut self, bb: mir::BasicBlock, ) { let mut bx = self.build_block(bb); - let data = &self.mir[bb]; + let data = &self.mir.body()[bb]; debug!("codegen_block({:?}={:?})", bb, data); @@ -827,7 +827,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - helper.maybe_sideeffect(&self.mir, &mut bx, &[target]); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 71d0abf2bff80..27891be6b82c5 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -9,7 +9,7 @@ use crate::mir::operand::OperandRef; use super::FunctionCx; -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn eval_mir_constant_to_operand( &mut self, bx: &mut Bx, diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index a58b13ce102d2..2a012cd2ed943 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -1,6 +1,6 @@ use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, Body, BodyCache}; +use rustc::mir::{self, Body, ReadOnlyBodyCache}; use rustc_target::abi::call::{FnAbi, PassMode}; use crate::base; use crate::traits::*; @@ -18,10 +18,10 @@ use rustc::mir::traversal; use self::operand::{OperandRef, OperandValue}; /// Master context for codegenning from MIR. -pub struct FunctionCx<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { +pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: &'b mir::ReadOnlyBodyCache<'a, 'tcx>, + mir: mir::ReadOnlyBodyCache<'a, 'tcx>, debug_context: Option>, @@ -79,7 +79,7 @@ pub struct FunctionCx<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { per_local_var_debug_info: Option>>>, } -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphize(&self, value: &T) -> T where T: TypeFoldable<'tcx> { @@ -122,7 +122,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, llfn: Bx::Function, - mut mir: BodyCache<&'a Body<'tcx>>, + mir: ReadOnlyBodyCache<'a, 'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, ) { @@ -157,10 +157,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); let mir_body = mir.body(); - let readonly_mir = mir.read_only(); let mut fx = FunctionCx { instance, - mir: &readonly_mir, + mir, llfn, fn_abi, cx, @@ -319,9 +318,9 @@ fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// Produces, for each argument, a `Value` pointing at the /// argument's value. As arguments are places, these are always /// indirect. -fn arg_local_refs<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, - fx: &FunctionCx<'a, 'b, 'tcx, Bx>, + fx: &FunctionCx<'a, 'tcx, Bx>, memory_locals: &BitSet, ) -> Vec> { let mut idx = 0; diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 947dc2df87d20..310b8aeb4db09 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -377,7 +377,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { } } -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn maybe_codegen_consume_direct( &mut self, bx: &mut Bx, diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 34f2b56adee49..281539277cb77 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -435,7 +435,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } } -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_place( &mut self, bx: &mut Bx, diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 19554156b2277..680c5b873b02e 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -18,7 +18,7 @@ use syntax::source_map::{DUMMY_SP, Span}; use std::{u128, i128}; -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_rvalue( &mut self, mut bx: Bx, @@ -695,7 +695,7 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { } } -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn rvalue_creates_operand( &self, rvalue: &mir::Rvalue<'tcx>, diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 5307108f8571c..0b82edea15790 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -8,7 +8,7 @@ use crate::traits::*; use rustc_error_codes::*; -impl<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'b, 'tcx, Bx> { +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_statement( &mut self, mut bx: Bx, diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 820783bab6d27..30dad03648c91 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -18,12 +18,11 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc::dep_graph::{self, DepNodeIndex}; use rustc::middle::lang_items; -use rustc::mir::{self, interpret}; +use rustc::mir::{self, BodyCache, interpret, Promoted}; use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; -use rustc::mir::{Body, Promoted}; use rustc::util::common::record_time; use rustc::util::captures::Captures; @@ -1080,7 +1079,7 @@ impl<'a, 'tcx> CrateMetadata { self.root.per_def.mir.get(self, id).is_some() } - fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyCache<'tcx> { self.root.per_def.mir.get(self, id) .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { @@ -1093,7 +1092,7 @@ impl<'a, 'tcx> CrateMetadata { &self, tcx: TyCtxt<'tcx>, id: DefIndex, - ) -> IndexVec> { + ) -> IndexVec> { self.root.per_def.promoted_mir.get(self, id) .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 4ea562fced304..fdf43f06eb10f 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -276,8 +276,8 @@ define_per_def_tables! { // Also, as an optimization, a missing entry indicates an empty `&[]`. inferred_outlives: Table, Span)])>, super_predicates: Table)>, - mir: Table)>, - promoted_mir: Table>)>, + mir: Table)>, + promoted_mir: Table>)>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 6191a93d22878..d1af7461f4754 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -90,7 +90,7 @@ crate enum LocalsStateAtExit { impl LocalsStateAtExit { fn build( locals_are_invalidated_at_exit: bool, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, move_data: &MoveData<'tcx> ) -> Self { struct HasStorageDead(BitSet); @@ -123,7 +123,7 @@ impl LocalsStateAtExit { impl<'tcx> BorrowSet<'tcx> { pub fn build( tcx: TyCtxt<'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, locals_are_invalidated_at_exit: bool, move_data: &MoveData<'tcx>, ) -> Self { @@ -139,7 +139,7 @@ impl<'tcx> BorrowSet<'tcx> { LocalsStateAtExit::build(locals_are_invalidated_at_exit, body_cache, move_data), }; - for (block, block_data) in traversal::preorder(body_cache) { + for (block, block_data) in traversal::preorder(&body_cache) { visitor.visit_basic_block_data(block, block_data); } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f8ae07aa394b5..0170cc8b42abf 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -102,7 +102,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, - input_promoted: &IndexVec>, + input_promoted: &IndexVec>, def_id: DefId, ) -> BorrowCheckResult<'tcx> { debug!("do_mir_borrowck(def_id = {:?})", def_id); @@ -162,14 +162,13 @@ fn do_mir_borrowck<'a, 'tcx>( // requires first making our own copy of the MIR. This copy will // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. - let mut body: Body<'tcx> = input_body.clone(); + let body: Body<'tcx> = input_body.clone(); let mut promoted = input_promoted.clone(); - let mut promoted_cache: IndexVec>> = input_promoted.clone().iter_mut().map(|body| BodyCache::new(body)).collect(); - let mut body_cache = BodyCache::new(&mut body); + let mut body_cache = BodyCache::new(body); let free_regions = - nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted_cache); - let body_cache = BodyCache::new(&body).read_only(); // no further changes - let promoted: IndexVec> = promoted_cache.into_iter().map(|body_cache| body_cache.read_only()).collect(); + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted); + let body_cache = body_cache.read_only(); // no further changes + let promoted: IndexVec<_, _> = promoted.iter().map(|body_cache| body_cache.read_only()).collect(); let location_table = &LocationTable::new(&body_cache); @@ -198,14 +197,14 @@ fn do_mir_borrowck<'a, 'tcx>( let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build( - tcx, &body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); + tcx, body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( infcx, def_id, free_regions, - &body_cache, + body_cache, &promoted, &local_names, &upvars, @@ -1338,7 +1337,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => bug!("temporary initialized in arguments"), }; - let bbd = &self.body_cache[loc.block]; + let bbd = &self.body_cache.body()[loc.block]; let stmt = &bbd.statements[loc.statement_index]; debug!("temporary assigned in: stmt={:?}", stmt); @@ -1860,7 +1859,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { this.move_data.moves[*moi].source.is_predecessor_of( - location, &this.body_cache, + location, this.body_cache, ) }) { return; diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 44e139889c938..feaa5fd3a5519 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -377,7 +377,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, ))) => Some(suggest_ampmut( self.infcx.tcx, - &self.body_cache, + self.body_cache, *local, local_decl, opt_ty_info, @@ -529,7 +529,7 @@ fn suggest_ampmut_self<'tcx>( // by trying (3.), then (2.) and finally falling back on (1.). fn suggest_ampmut<'tcx>( tcx: TyCtxt<'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, local: Local, local_decl: &mir::LocalDecl<'tcx>, opt_ty_info: Option, diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 7cb5b839ceebd..8d5466e545d52 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>( param_env: ty::ParamEnv<'tcx>, all_facts: &mut Option, location_table: &LocationTable, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, borrow_set: &BorrowSet<'tcx>, ) { if all_facts.is_none() { @@ -41,7 +41,7 @@ pub(super) fn generate_invalidates<'tcx>( body: body_cache.body(), dominators, }; - ig.visit_body(&body_cache); + ig.visit_body(body_cache); } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 5fa2c6605f6fb..bf11d348409ca 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -55,8 +55,8 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body_cache: &mut BodyCache<&mut Body<'tcx>>, - promoted: &mut IndexVec>>, + body_cache: &mut BodyCache<'tcx>, + promoted: &mut IndexVec>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -158,7 +158,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, universal_regions: UniversalRegions<'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, promoted_cache: &IndexVec>, local_names: &IndexVec>, upvars: &[Upvar], @@ -181,7 +181,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(body_cache)); + let elements = &Rc::new(RegionValueElements::new(body_cache.body())); // Run the MIR type-checker. let MirTypeckResults { @@ -206,7 +206,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); - populate_polonius_move_facts(all_facts, move_data, location_table, body_cache); + populate_polonius_move_facts(all_facts, move_data, location_table, body_cache.body()); } // Create the region inference context, taking ownership of the @@ -230,7 +230,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( &mut liveness_constraints, &mut all_facts, location_table, - body_cache, + body_cache.body(), borrow_set, ); @@ -239,7 +239,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( universal_regions, placeholder_indices, universal_region_relations, - body_cache, + body_cache.body(), outlives_constraints, member_constraints, closure_bounds_mapping, @@ -284,21 +284,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let closure_region_requirements = - regioncx.solve(infcx, body_cache, local_names, upvars, def_id, errors_buffer); + regioncx.solve(infcx, body_cache.body(), local_names, upvars, def_id, errors_buffer); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, MirSource::item(def_id), - body_cache, + body_cache.body(), ®ioncx, &closure_region_requirements, ); // We also have a `#[rustc_nll]` annotation that causes us to dump // information - dump_annotation(infcx, body_cache, def_id, ®ioncx, &closure_region_requirements, errors_buffer); + dump_annotation(infcx, body_cache.body(), def_id, ®ioncx, &closure_region_requirements, errors_buffer); (regioncx, polonius_output, closure_region_requirements) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 5d1891c0bf64c..16d2eca8f20e4 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -92,7 +92,7 @@ impl RegionValueElements { /// Pushes all predecessors of `index` onto `stack`. crate fn push_predecessors( &self, - body_cache: &ReadOnlyBodyCache<'_, '_>, + body_cache: ReadOnlyBodyCache<'_, '_>, index: PointIndex, stack: &mut Vec, ) { diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 57e977eacba15..882b825c5284e 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,6 +1,6 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::mir::{Body, BodyCache, Location, PlaceElem, Promoted}; +use rustc::mir::{BodyCache, Location, PlaceElem, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -9,8 +9,8 @@ use rustc_index::vec::IndexVec; /// inference variables, returning the number of variables created. pub fn renumber_mir<'tcx>( infcx: &InferCtxt<'_, 'tcx>, - body_cache: &mut BodyCache<&mut Body<'tcx>>, - promoted: &mut IndexVec>>, + body_cache: &mut BodyCache<'tcx>, + promoted: &mut IndexVec>, ) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body_cache.arg_count); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 181508a983a16..0cd5dd8059495 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -60,7 +60,7 @@ impl LocalUseMap { crate fn build( live_locals: &Vec, elements: &RegionValueElements, - body_cache: &ReadOnlyBodyCache<'_, '_>, + body_cache: ReadOnlyBodyCache<'_, '_>, ) -> Self { let nones = IndexVec::from_elem_n(None, body_cache.local_decls.len()); let mut local_use_map = LocalUseMap { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 833958814af45..2dea6797ec748 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -28,7 +28,7 @@ mod trace; /// performed before pub(super) fn generate<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -48,7 +48,7 @@ pub(super) fn generate<'tcx>( let mut drop_used = Vec::new(); polonius::populate_access_facts( typeck, - &body_cache, + body_cache, location_table, move_data, &mut drop_used, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index 3320815688f27..c17fbf0cdc9f8 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -97,7 +97,7 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, drop_used: &mut Vec<(Local, Location)>, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 5929516ec4e47..9a0392ab1d836 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -32,7 +32,7 @@ use std::rc::Rc; /// this respects `#[may_dangle]` annotations). pub(super) fn trace( typeck: &mut TypeChecker<'_, 'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -41,7 +41,7 @@ pub(super) fn trace( ) { debug!("trace()"); - let local_use_map = &LocalUseMap::build(&live_locals, elements, &body_cache); + let local_use_map = &LocalUseMap::build(&live_locals, elements, body_cache); let cx = LivenessContext { typeck, @@ -71,7 +71,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { elements: &'me RegionValueElements, /// MIR we are analyzing. - body_cache: &'me ReadOnlyBodyCache<'me, 'tcx>, + body_cache: ReadOnlyBodyCache<'me, 'tcx>, /// Mapping to/from the various indices used for initialization tracking. move_data: &'me MoveData<'tcx>, @@ -211,7 +211,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } if self.use_live_at.insert(p) { - self.cx.elements.push_predecessors(&self.cx.body_cache, p, &mut self.stack) + self.cx.elements.push_predecessors(self.cx.body_cache, p, &mut self.stack) } } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 8e966033bb8fd..92efd383c3c81 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -115,7 +115,7 @@ mod relate_tys; pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_cache: &ReadOnlyBodyCache<'_, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, promoted_cache: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, @@ -168,7 +168,7 @@ pub(crate) fn type_check<'tcx>( &mut borrowck_context, &universal_region_relations, |mut cx| { - cx.equate_inputs_and_outputs(body_cache, universal_regions, &normalized_inputs_and_output); + cx.equate_inputs_and_outputs(body_cache.body(), universal_regions, &normalized_inputs_and_output); liveness::generate(&mut cx, body_cache, elements, flow_inits, move_data, location_table); translate_outlives_facts(cx.borrowck_context); @@ -185,7 +185,7 @@ fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body_cache: &ReadOnlyBodyCache<'a, 'tcx>, + body_cache: ReadOnlyBodyCache<'a, 'tcx>, promoted_cache: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, @@ -195,7 +195,7 @@ fn type_check_internal<'a, 'tcx, R>( ) -> R where { let mut checker = TypeChecker::new( infcx, - body_cache, + body_cache.body(), mir_def_id, param_env, region_bound_pairs, @@ -204,14 +204,14 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body_cache, promoted_cache); + let mut verifier = TypeVerifier::new(&mut checker, body_cache.body(), promoted_cache); verifier.visit_body(body_cache); verifier.errors_reported }; if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(body_cache); + checker.typeck_mir(body_cache.body()); } extra(&mut checker) @@ -385,7 +385,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - fn visit_body(&mut self, body_cache: &ReadOnlyBodyCache<'_, 'tcx>) { + fn visit_body(&mut self, body_cache: ReadOnlyBodyCache<'_, 'tcx>) { self.sanitize_type(&"return type", body_cache.return_ty()); for local_decl in &body_cache.local_decls { self.sanitize_type(local_decl, local_decl.ty); @@ -464,7 +464,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { match kind { StaticKind::Promoted(promoted, _) => { if !self.errors_reported { - let promoted_body_cache = &self.promoted_cache[*promoted]; + let promoted_body_cache = self.promoted_cache[*promoted]; self.sanitize_promoted(promoted_body_cache, location); let promoted_ty = promoted_body_cache.return_ty(); @@ -535,7 +535,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place_ty } - fn sanitize_promoted(&mut self, promoted_body_cache: &ReadOnlyBodyCache<'b, 'tcx>, location: Location) { + fn sanitize_promoted(&mut self, promoted_body_cache: ReadOnlyBodyCache<'b, 'tcx>, location: Location) { // Determine the constraints from the promoted MIR by running the type // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 430452efe422d..27e6d803bd0ab 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -32,7 +32,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { never_initialized_mut_locals: &mut never_initialized_mut_locals, mbcx: self, }; - visitor.visit_body(&visitor.mbcx.body_cache); + visitor.visit_body(visitor.mbcx.body_cache); } // Take the union of the existed `used_mut` set with those variables we've found were diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index eb9b401f27208..28b4c9fd09b37 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -24,7 +24,7 @@ use syntax_pos::Span; use super::lints; /// Construct the MIR for a given `DefId`. -pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { +pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> { let id = tcx.hir().as_local_hir_id(def_id).unwrap(); // Figure out what primary body this item has. @@ -196,7 +196,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { lints::check(tcx, &body, def_id); - body + BodyCache::new(body) }) } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 0967b25788557..0a205be0c58de 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -354,7 +354,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } // This is a const fn. Call it. Ok(Some(match ecx.load_mir(instance.def, None) { - Ok(body) => body, + Ok(body_cache) => body_cache.body(), Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { return Err( @@ -697,7 +697,7 @@ pub fn const_eval_raw_provider<'tcx>( let res = ecx.load_mir(cid.instance.def, cid.promoted); res.and_then( - |body| eval_body_using_ecx(&mut ecx, cid, body) + |body_cache| eval_body_using_ecx(&mut ecx, cid, body_cache.body()) ).and_then(|place| { Ok(RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 2e164765043d4..fc344f9b25259 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -75,19 +75,19 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. pub struct RequiresStorage<'mir, 'tcx> { - body_cache: &'mir ReadOnlyBodyCache<'mir, 'tcx>, + body_cache: ReadOnlyBodyCache<'mir, 'tcx>, borrowed_locals: RefCell>>, } impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { pub fn new( - body_cache: &'mir ReadOnlyBodyCache<'mir, 'tcx>, + body_cache: ReadOnlyBodyCache<'mir, 'tcx>, borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>, ) -> Self { RequiresStorage { body_cache, - borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body_cache)), + borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body_cache.body())), } } @@ -187,7 +187,7 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { sets, borrowed_locals: &self.borrowed_locals, }; - visitor.visit_location(&self.body_cache, loc); + visitor.visit_location(self.body_cache, loc); } /// Gen locals that are newly borrowed. This includes borrowing any part of diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 6c16c4f221928..043ba09f52a9a 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -292,7 +292,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, instance: ty::InstanceDef<'tcx>, promoted: Option, - ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { + ) -> InterpResult<'tcx, mir::ReadOnlyBodyCache<'tcx, 'tcx>> { // do not continue if typeck errors occurred (can only occur in local crate) let did = instance.def_id(); if did.is_local() @@ -303,11 +303,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); if let Some(promoted) = promoted { - return Ok(&self.tcx.promoted_mir(did)[promoted]); + return Ok(self.tcx.promoted_mir(did)[promoted].read_only()); } match instance { ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { - Ok(self.tcx.optimized_mir(did)) + Ok(self.tcx.optimized_mir(did).read_only()) } else { throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id))) }, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 285bdf50d4a25..ecfbe529b9566 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -186,7 +186,7 @@ use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::session::config::EntryFnType; -use rustc::mir::{self, BodyCache, Location, PlaceBase, Static, StaticKind}; +use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::{MonoItem, InstantiationMode}; use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled}; @@ -1248,15 +1248,15 @@ fn collect_neighbours<'tcx>( output: &mut Vec>, ) { debug!("collect_neighbours: {:?}", instance.def_id()); - let body = tcx.instance_mir(instance.def); - let body_cache = BodyCache::new(body).read_only(); + let body_cache = tcx.instance_mir(instance.def); + let body = body_cache.body(); MirNeighborCollector { tcx, body: &body, output, param_substs: instance.substs, - }.visit_body(&body_cache); + }.visit_body(body_cache); } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index c80b6e38ac504..8f97a4e7f5c89 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -26,7 +26,7 @@ pub fn provide(providers: &mut Providers<'_>) { providers.mir_shims = make_shim; } -fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { +fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx BodyCache<'tcx> { debug!("make_shim({:?})", instance); let mut result = match instance { @@ -113,7 +113,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx bug!("creating shims from intrinsics ({:?}) is unsupported", instance) } }; - debug!("make_shim({:?}) = untransformed {:?}", instance, result); + debug!("make_shim({:?}) = untransformed {:?}", instance, result.body()); run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, @@ -123,7 +123,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx &add_call_guards::CriticalCallEdges, ]); - debug!("make_shim({:?}) = {:?}", instance, result); + debug!("make_shim({:?}) = {:?}", instance, result.body()); tcx.arena.alloc(result) } @@ -164,7 +164,7 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span) .collect() } -fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) -> Body<'tcx> { +fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) -> BodyCache<'tcx> { debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); // Check if this is a generator, if so, return the drop glue for it @@ -202,7 +202,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) sig.inputs().len(), span); - let mut body_cache = BodyCache::new(&mut body); + let mut body_cache = BodyCache::new(body); if let Some(..) = ty { // The first argument (index 0), but add 1 for the return value. @@ -238,8 +238,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) patch.apply(&mut body_cache); } - // TODO(pfaia) return owning body cache... - body + body_cache } fn new_body<'tcx>( @@ -317,7 +316,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { } /// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`. -fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> { +fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> BodyCache<'tcx> { debug!("build_clone_shim(def_id={:?})", def_id); let param_env = tcx.param_env(def_id); @@ -346,7 +345,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - } }; - builder.into_mir() + BodyCache::new(builder.into_mir()) } struct CloneShimBuilder<'tcx> { @@ -707,7 +706,7 @@ fn build_call_shim<'tcx>( rcvr_adjustment: Adjustment, call_kind: CallKind, untuple_args: Option<&[Ty<'tcx>]>, -) -> Body<'tcx> { +) -> BodyCache<'tcx> { debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \ call_kind={:?}, untuple_args={:?})", def_id, rcvr_adjustment, call_kind, untuple_args); @@ -842,10 +841,10 @@ fn build_call_shim<'tcx>( if let Abi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); } - body + BodyCache::new(body) } -pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { +pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> { debug_assert!(tcx.is_constructor(ctor_id)); let span = tcx.hir().span_if_local(ctor_id) @@ -929,5 +928,5 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { |_, _| Ok(()), ); - tcx.arena.alloc(body) + tcx.arena.alloc(BodyCache::new(body)) } diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index bf3df1ae2fd84..071ad002c169d 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -31,22 +31,22 @@ pub use self::AddCallGuards::*; */ impl<'tcx> MirPass<'tcx> for AddCallGuards { - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { - self.add_call_guards(body); + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + self.add_call_guards(body_cache); } } impl AddCallGuards { - pub fn add_call_guards(&self, body: &mut Body<'_>) { + pub fn add_call_guards(&self, body_cache: &mut BodyCache<'_>) { let pred_count: IndexVec<_, _> = - body.predecessors().iter().map(|ps| ps.len()).collect(); + body_cache.predecessors().iter().map(|ps| ps.len()).collect(); // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); - let cur_len = body.basic_blocks().len(); + let cur_len = body_cache.basic_blocks().len(); - for block in body.basic_blocks_mut() { + for block in body_cache.basic_blocks_mut() { match block.terminator { Some(Terminator { kind: TerminatorKind::Call { @@ -78,6 +78,6 @@ impl AddCallGuards { debug!("Broke {} N edges", new_blocks.len()); - body.basic_blocks_mut().extend(new_blocks); + body_cache.basic_blocks_mut().extend(new_blocks); } } diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index 052631ddff371..aebd632978ad1 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -40,15 +40,15 @@ use crate::util; pub struct AddMovesForPackedDrops; impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span); - add_moves_for_packed_drops(tcx, body, src.def_id()); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body_cache.span); + add_moves_for_packed_drops(tcx, body_cache, src.def_id()); } } -pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, def_id: DefId) { - let patch = add_moves_for_packed_drops_patch(tcx, body, def_id); - patch.apply(body); +pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>, def_id: DefId) { + let patch = add_moves_for_packed_drops_patch(tcx, body_cache, def_id); + patch.apply(body_cache); } fn add_moves_for_packed_drops_patch<'tcx>( diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index b56a1b263fd6a..25594ab20a91c 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -59,12 +59,12 @@ fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { } impl<'tcx> MirPass<'tcx> for AddRetag { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } - let (span, arg_count) = (body.span, body.arg_count); - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + let (span, arg_count) = (body_cache.span, body_cache.arg_count); + let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut(); let needs_retag = |place: &Place<'tcx>| { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d12d21aee6abe..78628474bce97 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -528,7 +528,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult hir::BodyOwnerKind::Static(_) => (true, false), }; let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env); - checker.visit_body(body); + checker.visit_body(body.read_only()); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); UnsafetyCheckResult { diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 4fd4fe45cd4f1..3ea41816ebefe 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -16,7 +16,7 @@ //! [`FakeRead`]: rustc::mir::StatementKind::FakeRead //! [`Nop`]: rustc::mir::StatementKind::Nop -use rustc::mir::{BorrowKind, Rvalue, Location, Body}; +use rustc::mir::{BodyCache, BorrowKind, Rvalue, Location}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; @@ -29,9 +29,9 @@ pub struct DeleteNonCodegenStatements<'tcx> { } impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { let mut delete = DeleteNonCodegenStatements { tcx }; - delete.visit_body(body); + delete.visit_body(body_cache); } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 67958af3460fc..f79f375a7e846 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -7,9 +7,10 @@ use std::cell::Cell; use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::{ - AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, UnOp, - StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, - BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, RETURN_PLACE, + AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp, + Rvalue. StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, + SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache, + RETURN_PLACE }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -41,7 +42,7 @@ const MAX_ALLOC_LIMIT: u64 = 1024; pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { return; @@ -76,15 +77,15 @@ impl<'tcx> MirPass<'tcx> for ConstProp { let dummy_body = &Body::new( - body.basic_blocks().clone(), - body.source_scopes.clone(), - body.local_decls.clone(), + body_cache.basic_blocks().clone(), + body_cache.source_scopes.clone(), + body_cache.local_decls.clone(), Default::default(), - body.arg_count, + body_cache.arg_count, Default::default(), tcx.def_span(source.def_id()), Default::default(), - body.generator_kind, + body_cache.generator_kind, ); // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold @@ -92,12 +93,12 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // That would require an uniform one-def no-mutation analysis // and RPO (or recursing when needing the value of a local). let mut optimization_finder = ConstPropagator::new( - body, + body_cache.read_only(), dummy_body, tcx, source ); - optimization_finder.visit_body(body); + optimization_finder.visit_body(body_cache); trace!("ConstProp done for {:?}", source.def_id()); } @@ -284,7 +285,7 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> { impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new( - body: &Body<'tcx>, + body_cache: ReadOnlyBodyCache<'mir, 'tcx>, dummy_body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, @@ -293,7 +294,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let param_env = tcx.param_env(def_id); let span = tcx.def_span(def_id); let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ()); - let can_const_prop = CanConstProp::check(body); + let can_const_prop = CanConstProp::check(body_cache); let substs = &InternalSubsts::identity_for_item(tcx, def_id); @@ -325,9 +326,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { can_const_prop, // FIXME(eddyb) avoid cloning these two fields more than once, // by accessing them through `ecx` instead. - source_scopes: body.source_scopes.clone(), + source_scopes: body_cache.source_scopes.clone(), //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it - local_decls: body.local_decls.clone(), + local_decls: body_cache.local_decls.clone(), ret: ret.map(Into::into), } } @@ -678,10 +679,10 @@ struct CanConstProp { impl CanConstProp { /// returns true if `local` can be propagated - fn check(body: &Body<'_>) -> IndexVec { + fn check(body_cache: ReadOnlyBodyCache<'_, '_>) -> IndexVec { let mut cpv = CanConstProp { - can_const_prop: IndexVec::from_elem(true, &body.local_decls), - found_assignment: IndexVec::from_elem(false, &body.local_decls), + can_const_prop: IndexVec::from_elem(true, &body_cache.local_decls), + found_assignment: IndexVec::from_elem(false, &body_cache.local_decls), }; for (local, val) in cpv.can_const_prop.iter_enumerated_mut() { // cannot use args at all @@ -689,14 +690,14 @@ impl CanConstProp { // lint for x != y // FIXME(oli-obk): lint variables until they are used in a condition // FIXME(oli-obk): lint if return value is constant - let local_kind = body.local_kind(local); + let local_kind = body_cache.local_kind(local); *val = local_kind == LocalKind::Temp || local_kind == LocalKind::ReturnPointer; if !*val { trace!("local {:?} can't be propagated because it's not a temporary", local); } } - cpv.visit_body(body); + cpv.visit_body(body_cache); cpv.can_const_prop } } diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 4c26feac4af79..637f4792029a2 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -19,7 +19,10 @@ //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the //! future. -use rustc::mir::{Constant, Local, LocalKind, Location, Place, Body, Operand, Rvalue, StatementKind}; +use rustc::mir::{ + Constant, Local, LocalKind, Location, Place, Body, BodyCache, Operand, Rvalue, + StatementKind +}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; use crate::transform::{MirPass, MirSource}; @@ -28,23 +31,23 @@ use crate::util::def_use::DefUseAnalysis; pub struct CopyPropagation; impl<'tcx> MirPass<'tcx> for CopyPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { return; } - let mut def_use_analysis = DefUseAnalysis::new(body); + let mut def_use_analysis = DefUseAnalysis::new(body_cache); loop { - def_use_analysis.analyze(body); + def_use_analysis.analyze(body_cache.read_only()); - if eliminate_self_assignments(body, &def_use_analysis) { - def_use_analysis.analyze(body); + if eliminate_self_assignments(body_cache, &def_use_analysis) { + def_use_analysis.analyze(body_cache.read_only()); } let mut changed = false; - for dest_local in body.local_decls.indices() { + for dest_local in body_cache.local_decls.indices() { debug!("considering destination local: {:?}", dest_local); let action; @@ -71,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } // Conservatively gives up if the dest is an argument, // because there may be uses of the original argument value. - if body.local_kind(dest_local) == LocalKind::Arg { + if body_cache.local_kind(dest_local) == LocalKind::Arg { debug!(" Can't copy-propagate local: dest {:?} (argument)", dest_local); continue; @@ -79,7 +82,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { let dest_place_def = dest_use_info.defs_not_including_drop().next().unwrap(); location = dest_place_def.location; - let basic_block = &body[location.block]; + let basic_block = &body_cache[location.block]; let statement_index = location.statement_index; let statement = match basic_block.statements.get(statement_index) { Some(statement) => statement, @@ -97,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { let maybe_action = match operand { Operand::Copy(ref src_place) | Operand::Move(ref src_place) => { - Action::local_copy(&body, &def_use_analysis, src_place) + Action::local_copy(&body_cache, &def_use_analysis, src_place) } Operand::Constant(ref src_constant) => { Action::constant(src_constant) @@ -127,7 +130,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } changed = - action.perform(body, &def_use_analysis, dest_local, location, tcx) || changed; + action.perform(body_cache, &def_use_analysis, dest_local, location, tcx) || changed; // FIXME(pcwalton): Update the use-def chains to delete the instructions instead of // regenerating the chains. break @@ -242,7 +245,7 @@ impl<'tcx> Action<'tcx> { } fn perform(self, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, def_use_analysis: &DefUseAnalysis, dest_local: Local, location: Location, @@ -260,21 +263,21 @@ impl<'tcx> Action<'tcx> { src_local); for place_use in &def_use_analysis.local_info(dest_local).defs_and_uses { if place_use.context.is_storage_marker() { - body.make_statement_nop(place_use.location) + body_cache.make_statement_nop(place_use.location) } } for place_use in &def_use_analysis.local_info(src_local).defs_and_uses { if place_use.context.is_storage_marker() { - body.make_statement_nop(place_use.location) + body_cache.make_statement_nop(place_use.location) } } // Replace all uses of the destination local with the source local. - def_use_analysis.replace_all_defs_and_uses_with(dest_local, body, src_local, tcx); + def_use_analysis.replace_all_defs_and_uses_with(dest_local, body_cache, src_local, tcx); // Finally, zap the now-useless assignment instruction. debug!(" Deleting assignment"); - body.make_statement_nop(location); + body_cache.make_statement_nop(location); true } @@ -288,7 +291,7 @@ impl<'tcx> Action<'tcx> { let dest_local_info = def_use_analysis.local_info(dest_local); for place_use in &dest_local_info.defs_and_uses { if place_use.context.is_storage_marker() { - body.make_statement_nop(place_use.location) + body_cache.make_statement_nop(place_use.location) } } @@ -297,7 +300,7 @@ impl<'tcx> Action<'tcx> { src_constant, tcx); for dest_place_use in &dest_local_info.defs_and_uses { - visitor.visit_location(body, dest_place_use.location) + visitor.visit_location(body_cache, dest_place_use.location) } // Zap the assignment instruction if we eliminated all the uses. We won't have been @@ -308,7 +311,7 @@ impl<'tcx> Action<'tcx> { debug!(" {} of {} use(s) replaced; deleting assignment", visitor.uses_replaced, use_count); - body.make_statement_nop(location); + body_cache.make_statement_nop(location); true } else if visitor.uses_replaced == 0 { debug!(" No uses replaced; not deleting assignment"); diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index cdde9e12edcbb..3d0bf6192dc49 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -6,8 +6,8 @@ use crate::util::expand_aggregate; pub struct Deaggregator; impl<'tcx> MirPass<'tcx> for Deaggregator { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { bb.expand_statements(|stmt| { diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index ed0eff943a165..987f0fde2e379 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -5,7 +5,7 @@ use std::fmt; use std::fs::File; use std::io; -use rustc::mir::Body; +use rustc::mir::{Body, BodyCache}; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; use crate::transform::{MirPass, MirSource}; @@ -18,7 +18,7 @@ impl<'tcx> MirPass<'tcx> for Marker { Cow::Borrowed(self.0) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body_cache: &mut BodyCache<'tcx>) { } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index f91a08bcd9aa6..378d991025a8f 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -21,17 +21,17 @@ use syntax_pos::Span; pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - debug!("elaborate_drops({:?} @ {:?})", src, body.span); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + debug!("elaborate_drops({:?} @ {:?})", src, body_cache.span); let def_id = src.def_id(); let param_env = tcx.param_env(src.def_id()).with_reveal_all(); - let move_data = match MoveData::gather_moves(body, tcx) { + let move_data = match MoveData::gather_moves(body_cache, tcx) { Ok(move_data) => move_data, Err(_) => bug!("No `move_errors` should be allowed in MIR borrowck"), }; let elaborate_patch = { - let body = &*body; + let body = &*body_cache; let env = MoveDataParamEnv { move_data, param_env, @@ -56,7 +56,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { patch: MirPatch::new(body), }.elaborate() }; - elaborate_patch.apply(body); + elaborate_patch.apply(body_cache); } } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index b30e2de4ca0bc..ff07f65d22c43 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -62,7 +62,7 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { pub struct EraseRegions; impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { - EraseRegionsVisitor::new(tcx).visit_body(body); + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + EraseRegionsVisitor::new(tcx).visit_body(body_cache); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 37205e65a0a42..503d24e56ae7b 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -378,9 +378,9 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { fn make_generator_state_argument_indirect<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, ) { - let gen_ty = body.local_decls.raw[1].ty; + let gen_ty = body_cache.local_decls.raw[1].ty; let region = ty::ReFree(ty::FreeRegion { scope: def_id, @@ -395,14 +395,14 @@ fn make_generator_state_argument_indirect<'tcx>( }); // Replace the by value generator argument - body.local_decls.raw[1].ty = ref_gen_ty; + body_cache.local_decls.raw[1].ty = ref_gen_ty; // Add a deref to accesses of the generator state - DerefArgVisitor { tcx }.visit_body(body); + DerefArgVisitor { tcx }.visit_body(body_cache); } -fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let ref_gen_ty = body.local_decls.raw[1].ty; +fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) { + let ref_gen_ty = body_cache.local_decls.raw[1].ty; let pin_did = tcx.lang_items().pin_type().unwrap(); let pin_adt_ref = tcx.adt_def(pin_did); @@ -410,18 +410,18 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs); // Replace the by ref generator argument - body.local_decls.raw[1].ty = pin_ref_gen_ty; + body_cache.local_decls.raw[1].ty = pin_ref_gen_ty; // Add the Pin field access to accesses of the generator state - PinArgVisitor { ref_gen_ty, tcx }.visit_body(body); + PinArgVisitor { ref_gen_ty, tcx }.visit_body(body_cache); } fn replace_result_variable<'tcx>( ret_ty: Ty<'tcx>, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, tcx: TyCtxt<'tcx>, ) -> Local { - let source_info = source_info(body); + let source_info = source_info(body_cache); let new_ret = LocalDecl { mutability: Mutability::Mut, ty: ret_ty, @@ -431,15 +431,15 @@ fn replace_result_variable<'tcx>( is_block_tail: None, local_info: LocalInfo::Other }; - let new_ret_local = Local::new(body.local_decls.len()); - body.local_decls.push(new_ret); - body.local_decls.swap(RETURN_PLACE, new_ret_local); + let new_ret_local = Local::new(body_cache.local_decls.len()); + body_cache.local_decls.push(new_ret); + body_cache.local_decls.swap(RETURN_PLACE, new_ret_local); RenameLocalVisitor { from: RETURN_PLACE, to: new_ret_local, tcx, - }.visit_body(body); + }.visit_body(body_cache); new_ret_local } @@ -481,12 +481,13 @@ struct LivenessInfo { fn locals_live_across_suspend_points( tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, source: MirSource<'tcx>, movable: bool, ) -> LivenessInfo { - let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); let def_id = source.def_id(); + let body = body_cache.body(); // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. @@ -498,8 +499,8 @@ fn locals_live_across_suspend_points( // Find the MIR locals which do not use StorageLive/StorageDead statements. // The storage of these locals are always live. - let mut ignored = StorageIgnored(BitSet::new_filled(body.local_decls.len())); - ignored.visit_body(body); + let mut ignored = StorageIgnored(BitSet::new_filled(body_cache.local_decls.len())); + ignored.visit_body(body_cache); // Calculate the MIR locals which have been previously // borrowed (even if they are still active). @@ -511,16 +512,16 @@ fn locals_live_across_suspend_points( // Calculate the MIR locals that we actually need to keep storage around // for. - let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results); + let requires_storage_analysis = RequiresStorage::new(body_cache, &borrowed_locals_results); let requires_storage_results = do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body); // Calculate the liveness of MIR locals ignoring borrows. - let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len()); + let mut live_locals = liveness::LiveVarSet::new_empty(body_cache.local_decls.len()); let mut liveness = liveness::liveness_of_locals( - body, + body_cache, ); liveness::dump_mir( tcx, @@ -533,7 +534,7 @@ fn locals_live_across_suspend_points( let mut storage_liveness_map = FxHashMap::default(); let mut live_locals_at_suspension_points = Vec::new(); - for (block, data) in body.basic_blocks().iter_enumerated() { + for (block, data) in body_cache.basic_blocks().iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { let loc = Location { block: block, @@ -749,7 +750,7 @@ fn compute_layout<'tcx>( upvars: &Vec>, interior: Ty<'tcx>, movable: bool, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, ) -> ( FxHashMap, VariantIdx, usize)>, GeneratorLayout<'tcx>, @@ -758,7 +759,7 @@ fn compute_layout<'tcx>( // Use a liveness analysis to compute locals which are live across a suspension point let LivenessInfo { live_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness - } = locals_live_across_suspend_points(tcx, body, source, movable); + } = locals_live_across_suspend_points(tcx, body_cache.read_only(), source, movable); // Erase regions from the types passed in from typeck so we can compare them with // MIR types @@ -768,7 +769,7 @@ fn compute_layout<'tcx>( _ => bug!(), }; - for (local, decl) in body.local_decls.iter_enumerated() { + for (local, decl) in body_cache.local_decls.iter_enumerated() { // Ignore locals which are internal or not live if !live_locals.contains(local) || decl.internal { continue; @@ -777,7 +778,7 @@ fn compute_layout<'tcx>( // Sanity check that typeck knows about the type of locals which are // live across a suspension point if !allowed.contains(&decl.ty) && !allowed_upvars.contains(&decl.ty) { - span_bug!(body.span, + span_bug!(body_cache.span, "Broken MIR: generator contains type {} in MIR, \ but typeck only knows about {}", decl.ty, @@ -790,7 +791,7 @@ fn compute_layout<'tcx>( let mut tys = IndexVec::::new(); for (idx, local) in live_locals.iter().enumerate() { locals.push(local); - tys.push(body.local_decls[local].ty); + tys.push(body_cache.local_decls[local].ty); debug!("generator saved local {:?} => {:?}", GeneratorSavedLocal::from(idx), local); } @@ -828,13 +829,13 @@ fn compute_layout<'tcx>( } fn insert_switch<'tcx>( - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, cases: Vec<(usize, BasicBlock)>, transform: &TransformVisitor<'tcx>, default: TerminatorKind<'tcx>, ) { - let default_block = insert_term_block(body, default); - let (assign, discr) = transform.get_discr(body); + let default_block = insert_term_block(body_cache, default); + let (assign, discr) = transform.get_discr(body_cache); let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), switch_ty: transform.discr_ty, @@ -842,8 +843,8 @@ fn insert_switch<'tcx>( targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(), }; - let source_info = source_info(body); - body.basic_blocks_mut().raw.insert(0, BasicBlockData { + let source_info = source_info(body_cache); + body_cache.basic_blocks_mut().raw.insert(0, BasicBlockData { statements: vec![assign], terminator: Some(Terminator { source_info, @@ -852,14 +853,14 @@ fn insert_switch<'tcx>( is_cleanup: false, }); - let blocks = body.basic_blocks_mut().iter_mut(); + let blocks = body_cache.basic_blocks_mut().iter_mut(); for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) { *target = BasicBlock::new(target.index() + 1); } } -fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut Body<'tcx>) { +fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body_cache: &mut BodyCache<'tcx>) { use crate::util::elaborate_drops::{elaborate_drop, Unwind}; use crate::util::patch::MirPatch; use crate::shim::DropShimElaborator; @@ -872,13 +873,13 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut let gen = self_arg(); let mut elaborator = DropShimElaborator { - body: body, - patch: MirPatch::new(body), + body: body_cache, + patch: MirPatch::new(body_cache), tcx, param_env }; - for (block, block_data) in body.basic_blocks().iter_enumerated() { + for (block, block_data) in body_cache.basic_blocks().iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { Terminator { source_info, @@ -915,7 +916,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut block, ); } - elaborator.patch.apply(body); + elaborator.patch.apply(body_cache); } fn create_generator_drop_shim<'tcx>( @@ -924,23 +925,23 @@ fn create_generator_drop_shim<'tcx>( def_id: DefId, source: MirSource<'tcx>, gen_ty: Ty<'tcx>, - body: &Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, drop_clean: BasicBlock, -) -> Body<'tcx> { - let mut body = body.clone(); +) -> BodyCache<'tcx> { + let mut body_cache = body_cache.clone(); - let source_info = source_info(&body); + let source_info = source_info(body_cache.body()); - let mut cases = create_cases(&mut body, transform, |point| point.drop); + let mut cases = create_cases(&mut body_cache, transform, |point| point.drop); cases.insert(0, (UNRESUMED, drop_clean)); // The returned state and the poisoned state fall through to the default // case which is just to return - insert_switch(&mut body, cases, &transform, TerminatorKind::Return); + insert_switch(&mut body_cache, cases, &transform, TerminatorKind::Return); - for block in body.basic_blocks_mut() { + for block in body_cache.basic_blocks_mut() { let kind = &mut block.terminator_mut().kind; if let TerminatorKind::GeneratorDrop = *kind { *kind = TerminatorKind::Return; @@ -948,7 +949,7 @@ fn create_generator_drop_shim<'tcx>( } // Replace the return variable - body.local_decls[RETURN_PLACE] = LocalDecl { + body_cache.local_decls[RETURN_PLACE] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_unit(), user_ty: UserTypeProjections::none(), @@ -958,10 +959,10 @@ fn create_generator_drop_shim<'tcx>( local_info: LocalInfo::Other }; - make_generator_state_argument_indirect(tcx, def_id, &mut body); + make_generator_state_argument_indirect(tcx, def_id, &mut body_cache); // Change the generator argument from &mut to *mut - body.local_decls[self_arg()] = LocalDecl { + body_cache.local_decls[self_arg()] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, @@ -975,27 +976,27 @@ fn create_generator_drop_shim<'tcx>( }; if tcx.sess.opts.debugging_opts.mir_emit_retag { // Alias tracking must know we changed the type - body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { + body_cache.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())), }) } - no_landing_pads(tcx, &mut body); + no_landing_pads(tcx, &mut body_cache); // Make sure we remove dead blocks to remove // unrelated code from the resume part of the function - simplify::remove_dead_blocks(&mut body); + simplify::remove_dead_blocks(&mut body_cache); - dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_drop", &0, source, &mut body_cache, |_, _| Ok(()) ); - body + body_cache } -fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { - let term_block = BasicBlock::new(body.basic_blocks().len()); - let source_info = source_info(body); - body.basic_blocks_mut().push(BasicBlockData { +fn insert_term_block<'tcx>(body_cache: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { + let term_block = BasicBlock::new(body_cache.basic_blocks().len()); + let source_info = source_info(body_cache); + body_cache.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, @@ -1008,13 +1009,13 @@ fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> fn insert_panic_block<'tcx>( tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, message: AssertMessage<'tcx>, ) -> BasicBlock { - let assert_block = BasicBlock::new(body.basic_blocks().len()); + let assert_block = BasicBlock::new(body_cache.basic_blocks().len()); let term = TerminatorKind::Assert { cond: Operand::Constant(box Constant { - span: body.span, + span: body_cache.span, user_ty: None, literal: ty::Const::from_bool(tcx, false), }), @@ -1024,8 +1025,8 @@ fn insert_panic_block<'tcx>( cleanup: None, }; - let source_info = source_info(body); - body.basic_blocks_mut().push(BasicBlockData { + let source_info = source_info(body_cache); + body_cache.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, @@ -1042,10 +1043,10 @@ fn create_generator_resume_function<'tcx>( transform: TransformVisitor<'tcx>, def_id: DefId, source: MirSource<'tcx>, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, ) { // Poison the generator when it unwinds - for block in body.basic_blocks_mut() { + for block in body_cache.basic_blocks_mut() { let source_info = block.terminator().source_info; if let &TerminatorKind::Resume = &block.terminator().kind { block.statements.push( @@ -1053,7 +1054,7 @@ fn create_generator_resume_function<'tcx>( } } - let mut cases = create_cases(body, &transform, |point| Some(point.resume)); + let mut cases = create_cases(body_cache, &transform, |point| Some(point.resume)); use rustc::mir::interpret::PanicInfo::{ ResumedAfterPanic, @@ -1067,25 +1068,25 @@ fn create_generator_resume_function<'tcx>( let generator_kind = body.generator_kind.unwrap(); cases.insert(1, (RETURNED, insert_panic_block( tcx, - body, + body_cache, ResumedAfterReturn(generator_kind)))); cases.insert(2, (POISONED, insert_panic_block( tcx, - body, + body_cache, ResumedAfterPanic(generator_kind)))); - insert_switch(body, cases, &transform, TerminatorKind::Unreachable); + insert_switch(body_cache, cases, &transform, TerminatorKind::Unreachable); - make_generator_state_argument_indirect(tcx, def_id, body); - make_generator_state_argument_pinned(tcx, body); + make_generator_state_argument_indirect(tcx, def_id, body_cache); + make_generator_state_argument_pinned(tcx, body_cache); - no_landing_pads(tcx, body); + no_landing_pads(tcx, body_cache); // Make sure we remove dead blocks to remove // unrelated code from the drop part of the function - simplify::remove_dead_blocks(body); + simplify::remove_dead_blocks(body_cache); - dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_resume", &0, source, body_cache, |_, _| Ok(()) ); } fn source_info(body: &Body<'_>) -> SourceInfo { @@ -1095,18 +1096,18 @@ fn source_info(body: &Body<'_>) -> SourceInfo { } } -fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { - let return_block = insert_term_block(body, TerminatorKind::Return); +fn insert_clean_drop(body_cache: &mut BodyCache<'_>) -> BasicBlock { + let return_block = insert_term_block(body_cache, TerminatorKind::Return); // Create a block to destroy an unresumed generators. This can only destroy upvars. - let drop_clean = BasicBlock::new(body.basic_blocks().len()); + let drop_clean = BasicBlock::new(body_cache.basic_blocks().len()); let term = TerminatorKind::Drop { location: Place::from(self_arg()), target: return_block, unwind: None, }; - let source_info = source_info(body); - body.basic_blocks_mut().push(BasicBlockData { + let source_info = source_info(body_cache); + body_cache.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, @@ -1119,23 +1120,23 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { } fn create_cases<'tcx, F>( - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, transform: &TransformVisitor<'tcx>, target: F, ) -> Vec<(usize, BasicBlock)> where F: Fn(&SuspensionPoint) -> Option, { - let source_info = source_info(body); + let source_info = source_info(body_cache); transform.suspension_points.iter().filter_map(|point| { // Find the target for this suspension point, if applicable target(point).map(|target| { - let block = BasicBlock::new(body.basic_blocks().len()); + let block = BasicBlock::new(body_cache.basic_blocks().len()); let mut statements = Vec::new(); // Create StorageLive instructions for locals with live storage - for i in 0..(body.local_decls.len()) { + for i in 0..(body_cache.local_decls.len()) { let l = Local::new(i); if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) { statements.push(Statement { @@ -1146,7 +1147,7 @@ where } // Then jump to the real target - body.basic_blocks_mut().push(BasicBlockData { + body_cache.basic_blocks_mut().push(BasicBlockData { statements, terminator: Some(Terminator { source_info, @@ -1163,20 +1164,20 @@ where } impl<'tcx> MirPass<'tcx> for StateTransform { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - let yield_ty = if let Some(yield_ty) = body.yield_ty { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + let yield_ty = if let Some(yield_ty) = body_cache.yield_ty { yield_ty } else { // This only applies to generators return }; - assert!(body.generator_drop.is_none()); + assert!(body_cache.generator_drop.is_none()); let def_id = source.def_id(); // The first argument is the generator type passed by value - let gen_ty = body.local_decls.raw[1].ty; + let gen_ty = body_cache.local_decls.raw[1].ty; // Get the interior types and substs which typeck computed let (upvars, interior, discr_ty, movable) = match gen_ty.kind { @@ -1195,13 +1196,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.intern_substs(&[ yield_ty.into(), - body.return_ty().into(), + body_cache.return_ty().into(), ]); let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local // RETURN_PLACE then is a fresh unused local with type ret_ty. - let new_ret_local = replace_result_variable(ret_ty, body, tcx); + let new_ret_local = replace_result_variable(ret_ty, body_cache, tcx); // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices @@ -1212,7 +1213,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { &upvars, interior, movable, - body); + body_cache); // Run the transformation which converts Places from Local to generator struct // accesses for locals in `remap`. @@ -1228,40 +1229,40 @@ impl<'tcx> MirPass<'tcx> for StateTransform { new_ret_local, discr_ty, }; - transform.visit_body(body); + transform.visit_body(body_cache); // Update our MIR struct to reflect the changed we've made - body.yield_ty = None; - body.arg_count = 1; - body.spread_arg = None; - body.generator_layout = Some(layout); + body_cache.yield_ty = None; + body_cache.arg_count = 1; + body_cache.spread_arg = None; + body_cache.generator_layout = Some(layout); // Insert `drop(generator_struct)` which is used to drop upvars for generators in // the unresumed state. // This is expanded to a drop ladder in `elaborate_generator_drops`. - let drop_clean = insert_clean_drop(body); + let drop_clean = insert_clean_drop(body_cache); - dump_mir(tcx, None, "generator_pre-elab", &0, source, body, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_pre-elab", &0, source, body_cache, |_, _| 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, body); + elaborate_generator_drops(tcx, def_id, body_cache); - dump_mir(tcx, None, "generator_post-transform", &0, source, body, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_post-transform", &0, source, body_cache, |_, _| 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, - &transform, - def_id, - source, - gen_ty, - &body, - drop_clean); + &transform, + def_id, + source, + gen_ty, + body_cache, + drop_clean); - body.generator_drop = Some(box drop_shim); + body_cache.generator_drop = Some(box drop_shim); // Create the Generator::resume function - create_generator_resume_function(tcx, transform, def_id, source, body); + create_generator_resume_function(tcx, transform, def_id, source, body_cache); } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index ebfadd0cfd3ed..c1c3d39bdc086 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -38,9 +38,9 @@ struct CallSite<'tcx> { } impl<'tcx> MirPass<'tcx> for Inline { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - Inliner { tcx, source }.run_pass(body); + Inliner { tcx, source }.run_pass(body_cache); } } } @@ -51,7 +51,7 @@ struct Inliner<'tcx> { } impl Inliner<'tcx> { - fn run_pass(&self, caller_body: &mut Body<'tcx>) { + fn run_pass(&self, caller_body_cache: &mut BodyCache<'tcx>) { // Keep a queue of callsites to try inlining on. We take // advantage of the fact that queries detect cycles here to // allow us to try and fetch the fully optimized MIR of a @@ -73,11 +73,11 @@ impl Inliner<'tcx> { if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() { - for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() { + for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated() { if let Some(callsite) = self.get_valid_function_call(bb, - bb_data, - caller_body, - param_env) { + bb_data, + caller_body_cache, + param_env) { callsites.push_back(callsite); } } @@ -127,19 +127,19 @@ impl Inliner<'tcx> { continue; }; - let start = caller_body.basic_blocks().len(); + let start = caller_body_cache.basic_blocks().len(); debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body); - if !self.inline_call(callsite, caller_body, callee_body) { + if !self.inline_call(callsite, caller_body_cache, callee_body) { debug!("attempting to inline callsite {:?} - failure", callsite); continue; } debug!("attempting to inline callsite {:?} - success", callsite); // Add callsites from inlined function - for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) { + for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated().skip(start) { if let Some(new_callsite) = self.get_valid_function_call(bb, bb_data, - caller_body, + caller_body_cache, param_env) { // Don't inline the same function multiple times. if callsite.callee != new_callsite.callee { @@ -160,8 +160,8 @@ impl Inliner<'tcx> { // Simplify if we inlined anything. if changed { debug!("running simplify cfg on {:?}", self.source); - CfgSimplifier::new(caller_body).simplify(); - remove_dead_blocks(caller_body); + CfgSimplifier::new(caller_body_cache).simplify(); + remove_dead_blocks(caller_body_cache); } } @@ -377,23 +377,23 @@ impl Inliner<'tcx> { fn inline_call(&self, callsite: CallSite<'tcx>, - caller_body: &mut Body<'tcx>, - mut callee_body: Body<'tcx>) -> bool { + caller_body: &mut BodyCache<'tcx>, + mut callee_body_cache: BodyCache<'tcx>) -> bool { let terminator = caller_body[callsite.bb].terminator.take().unwrap(); match terminator.kind { // FIXME: Handle inlining of diverging calls TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { debug!("inlined {:?} into {:?}", callsite.callee, self.source); - let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); - let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); + let mut local_map = IndexVec::with_capacity(callee_body_cache.local_decls.len()); + let mut scope_map = IndexVec::with_capacity(callee_body_cache.source_scopes.len()); - for mut scope in callee_body.source_scopes.iter().cloned() { + for mut scope in callee_body_cache.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { scope.parent_scope = Some(callsite.location.scope); // FIXME(eddyb) is this really needed? // (also note that it's always overwritten below) - scope.span = callee_body.span; + scope.span = callee_body_cache.span; } // FIXME(eddyb) this doesn't seem right at all. @@ -405,8 +405,8 @@ impl Inliner<'tcx> { scope_map.push(idx); } - for loc in callee_body.vars_and_temps_iter() { - let mut local = callee_body.local_decls[loc].clone(); + for loc in callee_body_cache.vars_and_temps_iter() { + let mut local = callee_body_cache.local_decls[loc].clone(); local.source_info.scope = scope_map[local.source_info.scope]; @@ -445,7 +445,7 @@ impl Inliner<'tcx> { BorrowKind::Mut { allow_two_phase_borrow: false }, destination.0); - let ty = dest.ty(caller_body, self.tcx); + let ty = dest.ty(caller_body.body(), self.tcx); let temp = LocalDecl::new_temp(ty, callsite.location.span); @@ -486,7 +486,7 @@ impl Inliner<'tcx> { caller_body.var_debug_info.push(var_debug_info); } - for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) { + for (bb, mut block) in callee_body_cache.basic_blocks_mut().drain_enumerated(..) { integrator.visit_basic_block_data(bb, &mut block); caller_body.basic_blocks_mut().push(block); } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index a567ed668bfa5..e466b0cb77b72 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -1,7 +1,8 @@ //! Performs various peephole optimizations. use rustc::mir::{ - Constant, Location, Place, PlaceBase, PlaceRef, Body, Operand, ProjectionElem, Rvalue, Local + Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyCache, Operand, ProjectionElem, + Rvalue, Local }; use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::ty::{self, TyCtxt}; @@ -13,7 +14,7 @@ use crate::transform::{MirPass, MirSource}; pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return @@ -23,13 +24,13 @@ impl<'tcx> MirPass<'tcx> for InstCombine { // read-only so that we can do global analyses on the MIR in the process (e.g. // `Place::ty()`). let optimizations = { - let mut optimization_finder = OptimizationFinder::new(body, tcx); - optimization_finder.visit_body(body); + let mut optimization_finder = OptimizationFinder::new(body_cache, tcx); + optimization_finder.visit_body(body_cache.read_only()); optimization_finder.optimizations }; // Then carry out those optimizations. - MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body); + MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body_cache); } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 1eac40fc591a0..97c4efc08a375 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -1,7 +1,7 @@ use crate::{build, shim}; use rustc_index::vec::IndexVec; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::mir::{Body, MirPhase, Promoted, ConstQualifs}; +use rustc::mir::{BodyCache, MirPhase, Promoted, ConstQualifs}; use rustc::ty::{TyCtxt, InstanceDef, TypeFoldable}; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -97,7 +97,7 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet { tcx.arena.alloc(set) } -fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { +fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { let mir = build::mir_build(tcx, def_id); tcx.alloc_steal_mir(mir) } @@ -144,12 +144,12 @@ pub trait MirPass<'tcx> { default_name::() } - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>); } pub fn run_passes( tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, + body: &mut BodyCache<'tcx>, instance: InstanceDef<'tcx>, promoted: Option, mir_phase: MirPhase, @@ -220,47 +220,47 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs { validator.qualifs_in_return_place().into() } -fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { +fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { // Unsafety check uses the raw mir, so make sure it is run let _ = tcx.unsafety_check_result(def_id); - let mut body = tcx.mir_built(def_id).steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Const, &[ + let mut body_cache = tcx.mir_built(def_id).steal(); + run_passes(tcx, &mut body_cache, InstanceDef::Item(def_id), None, MirPhase::Const, &[ // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, &uniform_array_move_out::UniformArrayMoveOut, ]); - tcx.alloc_steal_mir(body) + tcx.alloc_steal_mir(body_cache) } fn mir_validated( tcx: TyCtxt<'tcx>, def_id: DefId, -) -> (&'tcx Steal>, &'tcx Steal>>) { +) -> (&'tcx Steal>, &'tcx Steal>>) { // Ensure that we compute the `mir_const_qualif` for constants at // this point, before we steal the mir-const result. let _ = tcx.mir_const_qualif(def_id); - let mut body = tcx.mir_const(def_id).steal(); + let mut body_cache = tcx.mir_const(def_id).steal(); let promote_pass = promote_consts::PromoteTemps::default(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ + run_passes(tcx, &mut body_cache, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ // What we need to run borrowck etc. &promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); let promoted = promote_pass.promoted_fragments.into_inner(); - (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) + (tcx.alloc_steal_mir(body_cache), tcx.alloc_steal_promoted(promoted)) } fn run_optimization_passes<'tcx>( tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, def_id: DefId, promoted: Option, ) { - run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ + run_passes(tcx, body_cache, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads::new(tcx), &simplify_branches::SimplifyBranches::new("initial"), @@ -318,7 +318,7 @@ fn run_optimization_passes<'tcx>( ]); } -fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { +fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { if tcx.is_constructor(def_id) { // There's no reason to run all of the MIR passes on constructors when // we can just output the MIR we want directly. This also saves const @@ -332,12 +332,12 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { tcx.ensure().mir_borrowck(def_id); let (body, _) = tcx.mir_validated(def_id); - let mut body = body.steal(); - run_optimization_passes(tcx, &mut body, def_id, None); - tcx.arena.alloc(body) + let mut body_cache = body.steal(); + run_optimization_passes(tcx, &mut body_cache, def_id, None); + tcx.arena.alloc(body_cache) } -fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec> { +fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec> { if tcx.is_constructor(def_id) { return tcx.intern_promoted(IndexVec::new()); } @@ -346,8 +346,8 @@ fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec NoLandingPads<'tcx> { } impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { no_landing_pads(tcx, body) } } -pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) { if tcx.sess.no_landing_pads() { - NoLandingPads::new(tcx).visit_body(body); + NoLandingPads::new(tcx).visit_body(body_cache); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 591f3ca44009d..e409bb0842903 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -770,8 +770,8 @@ pub fn validate_candidates( struct Promoter<'a, 'tcx> { tcx: TyCtxt<'tcx>, - source: &'a mut Body<'tcx>, - promoted: Body<'tcx>, + source_cache: &'a mut BodyCache<'tcx>, + promoted_cache: BodyCache<'tcx>, temps: &'a mut IndexVec, /// If true, all nested temps are also kept in the @@ -781,8 +781,8 @@ struct Promoter<'a, 'tcx> { impl<'a, 'tcx> Promoter<'a, 'tcx> { fn new_block(&mut self) -> BasicBlock { - let span = self.promoted.span; - self.promoted.basic_blocks_mut().push(BasicBlockData { + let span = self.promoted_cache.span; + self.promoted_cache.basic_blocks_mut().push(BasicBlockData { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo { @@ -796,8 +796,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) { - let last = self.promoted.basic_blocks().last().unwrap(); - let data = &mut self.promoted[last]; + let last = self.promoted_cache.basic_blocks().last().unwrap(); + let data = &mut self.promoted_cache[last]; data.statements.push(Statement { source_info: SourceInfo { span, @@ -808,7 +808,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn is_temp_kind(&self, local: Local) -> bool { - self.source.local_kind(local) == LocalKind::Temp + self.source_cache.local_kind(local) == LocalKind::Temp } /// Copies the initialization of this temp to the @@ -823,7 +823,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { location } state => { - span_bug!(self.promoted.span, "{:?} not promotable: {:?}", + span_bug!(self.promoted_cache.span, "{:?} not promotable: {:?}", temp, state); } }; @@ -831,10 +831,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.temps[temp] = TempState::PromotedOut; } - let num_stmts = self.source[loc.block].statements.len(); - let new_temp = self.promoted.local_decls.push( - LocalDecl::new_temp(self.source.local_decls[temp].ty, - self.source.local_decls[temp].source_info.span)); + let num_stmts = self.source_cacje[loc.block].statements.len(); + let new_temp = self.promoted_cache.local_decls.push( + LocalDecl::new_temp(self.source_cache.local_decls[temp].ty, + self.source_cache.local_decls[temp].source_info.span)); debug!("promote({:?} @ {:?}/{:?}, {:?})", temp, loc, num_stmts, self.keep_original); @@ -843,7 +843,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // or duplicate it, depending on keep_original. if loc.statement_index < num_stmts { let (mut rvalue, source_info) = { - let statement = &mut self.source[loc.block].statements[loc.statement_index]; + let statement = &mut self.source_cache[loc.block].statements[loc.statement_index]; let rhs = match statement.kind { StatementKind::Assign(box(_, ref mut rhs)) => rhs, _ => { @@ -864,9 +864,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.assign(new_temp, rvalue, source_info.span); } else { let terminator = if self.keep_original { - self.source[loc.block].terminator().clone() + self.source_cache[loc.block].terminator().clone() } else { - let terminator = self.source[loc.block].terminator_mut(); + let terminator = self.source_cache[loc.block].terminator_mut(); let target = match terminator.kind { TerminatorKind::Call { destination: Some((_, target)), .. } => target, ref kind => { @@ -888,10 +888,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.visit_operand(arg, loc); } - let last = self.promoted.basic_blocks().last().unwrap(); + let last = self.promoted_cache.basic_blocks().last().unwrap(); let new_target = self.new_block(); - *self.promoted[last].terminator_mut() = Terminator { + *self.promoted_cache[last].terminator_mut() = Terminator { kind: TerminatorKind::Call { func, args, @@ -919,9 +919,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { def_id: DefId, candidate: Candidate, next_promoted_id: usize, - ) -> Option> { + ) -> Option> { let mut operand = { - let promoted = &mut self.promoted; + let promoted = &mut self.promoted_cache; let promoted_id = Promoted::new(next_promoted_id); let tcx = self.tcx; let mut promoted_place = |ty, span| { @@ -940,7 +940,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { projection: List::empty(), } }; - let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); + let (blocks, local_decls) = self.source_cache.basic_blocks_and_local_decls_mut(); match candidate { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; @@ -1004,9 +1004,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { statement_index: usize::MAX }); - let span = self.promoted.span; + let span = self.promoted_cache.span; self.assign(RETURN_PLACE, Rvalue::Use(operand), span); - Some(self.promoted) + Some(self.promoted_cache) } } @@ -1040,11 +1040,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { pub fn promote_candidates<'tcx>( def_id: DefId, - body: &mut Body<'tcx>, + body_cache: &mut BodyCache<'tcx>, tcx: TyCtxt<'tcx>, mut temps: IndexVec, candidates: Vec, -) -> IndexVec> { +) -> IndexVec> { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); @@ -1054,7 +1054,7 @@ pub fn promote_candidates<'tcx>( match candidate { Candidate::Repeat(Location { block, statement_index }) | Candidate::Ref(Location { block, statement_index }) => { - match &body[block].statements[statement_index].kind { + match &body_cache[block].statements[statement_index].kind { StatementKind::Assign(box(place, _)) => { if let Some(local) = place.as_local() { if temps[local] == TempState::PromotedOut { @@ -1072,25 +1072,26 @@ pub fn promote_candidates<'tcx>( // Declare return place local so that `mir::Body::new` doesn't complain. let initial_locals = iter::once( - LocalDecl::new_return_place(tcx.types.never, body.span) + LocalDecl::new_return_place(tcx.types.never, body_cache.span) ).collect(); let promoter = Promoter { - promoted: Body::new( + promoted_cache: BodyCache::new(Body::new( IndexVec::new(), // FIXME: maybe try to filter this to avoid blowing up // memory usage? - body.source_scopes.clone(), + body_cache.source_scopes.clone(), + body_cache.source_scope_local_data.clone(), initial_locals, IndexVec::new(), 0, vec![], - body.span, + body_cache.span, vec![], - body.generator_kind, - ), + body_cache.generator_kind, + )), tcx, - source: body, + source_cache: body_cache, temps: &mut temps, keep_original: false }; @@ -1103,7 +1104,7 @@ pub fn promote_candidates<'tcx>( // Eliminate assignments to, and drops of promoted temps. let promoted = |index: Local| temps[index] == TempState::PromotedOut; - for block in body.basic_blocks_mut() { + for block in body_cache.basic_blocks_mut() { block.statements.retain(|statement| { match &statement.kind { StatementKind::Assign(box(place, _)) => { diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 130393e2c4c86..3a7d7d17f0693 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -9,18 +9,18 @@ use crate::util::patch::MirPatch; /// code for these. pub struct RemoveNoopLandingPads; -pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) { if tcx.sess.no_landing_pads() { return } - debug!("remove_noop_landing_pads({:?})", body); + debug!("remove_noop_landing_pads({:?})", body_cache.body()); - RemoveNoopLandingPads.remove_nop_landing_pads(body) + RemoveNoopLandingPads.remove_nop_landing_pads(body_cache) } impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { - remove_noop_landing_pads(tcx, body); + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + remove_noop_landing_pads(tcx, body_cache); } } @@ -84,26 +84,26 @@ impl RemoveNoopLandingPads { } } - fn remove_nop_landing_pads(&self, body: &mut Body<'_>) { + fn remove_nop_landing_pads(&self, body_cache: &mut BodyCache<'_>) { // make sure there's a single resume block let resume_block = { - let patch = MirPatch::new(body); + let patch = MirPatch::new(body_cache); let resume_block = patch.resume_block(); - patch.apply(body); + patch.apply(body_cache); resume_block }; debug!("remove_noop_landing_pads: resume block is {:?}", resume_block); let mut jumps_folded = 0; let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks().len()); + let mut nop_landing_pads = BitSet::new_empty(body_cache.basic_blocks().len()); // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. - let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); + let postorder: Vec<_> = traversal::postorder(body_cache).map(|(bb, _)| bb).collect(); for bb in postorder { debug!(" processing {:?}", bb); - for target in body[bb].terminator_mut().successors_mut() { + for target in body_cache[bb].terminator_mut().successors_mut() { if *target != resume_block && nop_landing_pads.contains(*target) { debug!(" folding noop jump to {:?} to resume block", target); *target = resume_block; @@ -111,7 +111,7 @@ impl RemoveNoopLandingPads { } } - match body[bb].terminator_mut().unwind_mut() { + match body_cache[bb].terminator_mut().unwind_mut() { Some(unwind) => { if *unwind == Some(resume_block) { debug!(" removing noop landing pad"); @@ -123,7 +123,7 @@ impl RemoveNoopLandingPads { _ => {} } - let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); + let is_nop_landing_pad = self.is_nop_landing_pad(bb, body_cache, &nop_landing_pads); if is_nop_landing_pad { nop_landing_pads.insert(bb); } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index aada7641df67a..87fcef69238d8 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -5,7 +5,7 @@ use syntax_pos::Span; use rustc::ty::{self, TyCtxt, Ty}; use rustc::hir::def_id::DefId; -use rustc::mir::{self, Body, Location, Local}; +use rustc::mir::{self, Body, BodyCache, Location, Local}; use rustc_index::bit_set::BitSet; use crate::transform::{MirPass, MirSource}; @@ -26,7 +26,7 @@ use crate::dataflow::has_rustc_mir_with; pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -37,37 +37,37 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(body, tcx).unwrap(); + let move_data = MoveData::gather_moves(body_cache, tcx).unwrap(); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); let flow_inits = - do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, - MaybeInitializedPlaces::new(tcx, body, &mdpe), + do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, + MaybeInitializedPlaces::new(tcx, body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_uninits = - do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, body, &mdpe), + do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, + MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_def_inits = - do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, - DefinitelyInitializedPlaces::new(tcx, body, &mdpe), + do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, + DefinitelyInitializedPlaces::new(tcx, body_cache, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_indirectly_mut = - do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, - IndirectlyMutableLocals::new(tcx, body, param_env), + do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, + IndirectlyMutableLocals::new(tcx, body_cache, param_env), |_, i| DebugFormatted::new(&i)); if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() { - sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_inits); + sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_inits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_uninit).is_some() { - sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_uninits); + sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_uninits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { - sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_def_inits); + sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_def_inits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() { - sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_indirectly_mut); + sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_indirectly_mut); } if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 040bc5c309a9b..75016cf1746c9 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -43,12 +43,12 @@ impl SimplifyCfg { } } -pub fn simplify_cfg(body: &mut Body<'_>) { - CfgSimplifier::new(body).simplify(); - remove_dead_blocks(body); +pub fn simplify_cfg(body_cache: &mut BodyCache<'_>) { + CfgSimplifier::new(body_cache).simplify(); + remove_dead_blocks(body_cache); // FIXME: Should probably be moved into some kind of pass manager - body.basic_blocks_mut().raw.shrink_to_fit(); + body_cache.basic_blocks_mut().raw.shrink_to_fit(); } impl<'tcx> MirPass<'tcx> for SimplifyCfg { @@ -56,9 +56,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { Cow::Borrowed(&self.label) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { - debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); - simplify_cfg(body); + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body_cache.body()); + simplify_cfg(body_cache); } } @@ -68,14 +68,14 @@ pub struct CfgSimplifier<'a, 'tcx> { } impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { - pub fn new(body: &'a mut Body<'tcx>) -> Self { - let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks()); + pub fn new(body_cache: &'a mut BodyCache<'tcx>) -> Self { + let mut pred_count = IndexVec::from_elem(0u32, body_cache.basic_blocks()); // we can't use mir.predecessors() here because that counts // dead blocks, which we don't want to. pred_count[START_BLOCK] = 1; - for (_, data) in traversal::preorder(body) { + for (_, data) in traversal::preorder(body_cache) { if let Some(ref term) = data.terminator { for &tgt in term.successors() { pred_count[tgt] += 1; @@ -83,7 +83,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } - let basic_blocks = body.basic_blocks_mut(); + let basic_blocks = body_cache.basic_blocks_mut(); CfgSimplifier { basic_blocks, @@ -260,13 +260,13 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } -pub fn remove_dead_blocks(body: &mut Body<'_>) { - let mut seen = BitSet::new_empty(body.basic_blocks().len()); - for (bb, _) in traversal::preorder(body) { +pub fn remove_dead_blocks(body_cache: &mut BodyCache<'_>) { + let mut seen = BitSet::new_empty(body_cache.basic_blocks().len()); + for (bb, _) in traversal::preorder(body_cache.body()) { seen.insert(bb.index()); } - let basic_blocks = body.basic_blocks_mut(); + let basic_blocks = body_cache.basic_blocks_mut(); let num_blocks = basic_blocks.len(); let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); @@ -293,27 +293,27 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { trace!("running SimplifyLocals on {:?}", source); let locals = { let mut marker = DeclMarker { - locals: BitSet::new_empty(body.local_decls.len()), - body, + locals: BitSet::new_empty(body_cache.local_decls.len()), + body: body_cache, }; - marker.visit_body(body); + marker.visit_body(body_cache.read_only()); // Return pointer and arguments are always live marker.locals.insert(RETURN_PLACE); - for arg in body.args_iter() { + for arg in body_cache.args_iter() { marker.locals.insert(arg); } marker.locals }; - let map = make_local_map(&mut body.local_decls, locals); + let map = make_local_map(&mut body_cache.local_decls, locals); // Update references to all vars and tmps now - LocalUpdater { map, tcx }.visit_body(body); - body.local_decls.shrink_to_fit(); + LocalUpdater { map, tcx }.visit_body(body_cache); + body_cache.local_decls.shrink_to_fit(); } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 0a509666d34ae..df5d40484bf28 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -19,9 +19,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { Cow::Borrowed(&self.label) } - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { let param_env = tcx.param_env(src.def_id()); - for block in body.basic_blocks_mut() { + for block in body_cache.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { TerminatorKind::SwitchInt { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 28f68ac2de037..d3fbfaf384a91 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -37,14 +37,14 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - let mut patch = MirPatch::new(body); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + let mut patch = MirPatch::new(body_cache); let param_env = tcx.param_env(src.def_id()); { - let mut visitor = UniformArrayMoveOutVisitor{body, patch: &mut patch, tcx, param_env}; - visitor.visit_body(body); + let mut visitor = UniformArrayMoveOutVisitor{ body: body_cache, patch: &mut patch, tcx, param_env}; + visitor.visit_body(body_cache.read_only()); } - patch.apply(body); + patch.apply(body_cache); } } @@ -184,18 +184,18 @@ pub struct RestoreSubsliceArrayMoveOut<'tcx> { } impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - let mut patch = MirPatch::new(body); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + let mut patch = MirPatch::new(body_cache); let param_env = tcx.param_env(src.def_id()); { let mut visitor = RestoreDataCollector { - locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls), + locals_use: IndexVec::from_elem(LocalUse::new(), &body_cache.local_decls), candidates: vec![], }; - visitor.visit_body(body); + visitor.visit_body(body_cache.read_only()); for candidate in &visitor.candidates { - let statement = &body[candidate.block].statements[candidate.statement_index]; + let statement = &body_cache[candidate.block].statements[candidate.statement_index]; if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind { if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval { let items : Vec<_> = items.iter().map(|item| { @@ -203,7 +203,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { if let Some(local) = place.as_local() { let local_use = &visitor.locals_use[local]; let opt_index_and_place = - Self::try_get_item_source(local_use, body); + Self::try_get_item_source(local_use, body_cache); // each local should be used twice: // in assign and in aggregate statements if local_use.use_count == 2 && opt_index_and_place.is_some() { @@ -218,7 +218,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2); let opt_size = opt_src_place.and_then(|src_place| { let src_ty = - Place::ty_from(src_place.base, src_place.projection, body, tcx).ty; + Place::ty_from(src_place.base, src_place.projection, body_cache.body(), tcx).ty; if let ty::Array(_, ref size_o) = src_ty.kind { size_o.try_eval_usize(tcx, param_env) } else { @@ -232,7 +232,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { } } } - patch.apply(body); + patch.apply(body_cache); } } diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs index 0092c3c86d713..f94bea2002461 100644 --- a/src/librustc_mir/util/collect_writes.rs +++ b/src/librustc_mir/util/collect_writes.rs @@ -12,7 +12,7 @@ crate trait FindAssignments { impl<'a, 'tcx> FindAssignments for ReadOnlyBodyCache<'a, 'tcx>{ fn find_assignments(&self, local: Local) -> Vec{ let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]}; - visitor.visit_body(self); + visitor.visit_body(*self); visitor.locations } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 11b61bcd48444..256ba94af44d2 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -30,7 +30,7 @@ impl DefUseAnalysis { } } - pub fn analyze(&mut self, body_cache: &ReadOnlyBodyCache<'_, '_>) { + pub fn analyze(&mut self, body_cache: ReadOnlyBodyCache<'_, '_>) { self.clear(); let mut finder = DefUseFinder { @@ -55,7 +55,7 @@ impl DefUseAnalysis { fn mutate_defs_and_uses( &self, local: Local, - body_cache: &mut BodyCache<&mut Body<'tcx>>, + body_cache: &mut BodyCache<'tcx>, new_local: Local, tcx: TyCtxt<'tcx>, ) { @@ -73,7 +73,7 @@ impl DefUseAnalysis { // FIXME(pcwalton): this should update the def-use chains. pub fn replace_all_defs_and_uses_with(&self, local: Local, - body_cache: &mut BodyCache<&mut Body<'tcx>>, + body_cache: &mut BodyCache<'tcx>, new_local: Local, tcx: TyCtxt<'tcx>) { self.mutate_defs_and_uses(local, body_cache, new_local, tcx) diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 87e6291a45486..37611561d58ef 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -57,7 +57,7 @@ pub struct LivenessResult { /// Computes which local variables are live within the given function /// `mir`, including drops. pub fn liveness_of_locals( - body_cache: &ReadOnlyBodyCache<'_, '_>, + body_cache: ReadOnlyBodyCache<'_, '_>, ) -> LivenessResult { let num_live_vars = body_cache.local_decls.len(); @@ -84,7 +84,7 @@ pub fn liveness_of_locals( // order when cycles are present, but the overhead of computing the reverse CFG may outweigh // any benefits. Benchmark this and find out. let mut dirty_queue: WorkQueue = WorkQueue::with_none(body_cache.basic_blocks().len()); - for (bb, _) in traversal::postorder(body_cache) { + for (bb, _) in traversal::postorder(body_cache.body()) { dirty_queue.insert(bb); } diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 01be0f598ed21..6e110b1177f14 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> { self.make_nop.push(loc); } - pub fn apply(self, body_cache: &mut BodyCache<&'_ mut Body<'tcx>>) { + pub fn apply(self, body_cache: &mut BodyCache<'tcx>) { debug!("MirPatch: make nops at: {:?}", self.make_nop); for loc in self.make_nop { body_cache.make_statement_nop(loc); From 4de31b26d1d4a1c20456fc9ca1d39d284c79f64c Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sun, 27 Oct 2019 21:15:02 -0400 Subject: [PATCH 28/47] Fix remaining compilation issues --- src/librustc/mir/cache.rs | 38 ++++++++++++++++--- src/librustc/mir/mod.rs | 4 +- src/librustc/query/mod.rs | 8 +++- src/librustc/ty/mod.rs | 4 +- src/librustc_metadata/rmeta/decoder.rs | 14 +++++-- src/librustc_mir/borrow_check/mod.rs | 8 ++-- .../nll/type_check/liveness/trace.rs | 3 +- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/borrow_check/prefixes.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 4 +- src/librustc_mir/shim.rs | 5 ++- src/librustc_mir/transform/check_unsafety.rs | 8 ++-- src/librustc_mir/transform/const_prop.rs | 6 +-- src/librustc_mir/transform/copy_prop.rs | 6 +-- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir/transform/inline.rs | 22 +++++------ src/librustc_mir/transform/instcombine.rs | 5 ++- src/librustc_mir/transform/mod.rs | 2 + src/librustc_mir/transform/simplify.rs | 3 +- .../transform/uniform_array_move_out.rs | 6 ++- 20 files changed, 102 insertions(+), 50 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 8958a31b51cb5..7a52dea787a2d 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -151,6 +151,16 @@ impl BodyCache<'tcx> { } } +#[macro_export] +macro_rules! read_only { + ($body_cache:expr) => { + { + $body_cache.ensure_predecessors(); + $body_cache.unwrap_read_only() + } + }; +} + impl BodyCache<'tcx> { pub fn ensure_predecessors(&mut self) { self.cache.ensure_predecessors(&self.body); @@ -160,12 +170,8 @@ impl BodyCache<'tcx> { self.cache.predecessors(&self.body) } - pub fn read_only(&self) -> ReadOnlyBodyCache<'_, '_> { - assert!(self.cache.predecessors.is_some(), ""); - ReadOnlyBodyCache { - cache: &self.cache, - body: &self.body, - } + pub fn unwrap_read_only(&self) -> ReadOnlyBodyCache<'_, 'tcx> { + ReadOnlyBodyCache::new(&self.cache, &self.body) } pub fn body(&self) -> &Body<'tcx> { @@ -176,6 +182,8 @@ impl BodyCache<'tcx> { &mut self.body } + pub fn cache(&self) -> &Cache { &self.cache } + pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { self.cache.basic_blocks_mut(&mut self.body) } @@ -223,6 +231,24 @@ pub struct ReadOnlyBodyCache<'a, 'tcx> { } impl ReadOnlyBodyCache<'a, 'tcx> { + fn new(cache: &'a Cache, body: &'a Body<'tcx>) -> Self { + assert!( + cache.predecessors.is_some(), + "Cannot construct ReadOnlyBodyCache without computed predecessors"); + Self { + cache, + body, + } + } + + pub fn from_external_cache(cache: &'a mut Cache, body: &'a Body<'tcx>) -> Self { + cache.ensure_predecessors(body); + Self { + cache, + body, + } + } + #[inline] pub fn predecessors(&self) -> &IndexVec> { self.cache.predecessors.as_ref().unwrap() diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b6d1c78cc4f57..fdc3adabf0c55 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -38,7 +38,9 @@ use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache}; +// TODO(nashenas88) Cache only exported for use in librustc_mir/transform/check_unsafety.rs +pub use crate::mir::cache::{BodyCache, Cache, ReadOnlyBodyCache}; +pub use crate::read_only; pub mod cache; pub mod interpret; diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index cdfdcee5823ec..2bf7caceb68e6 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -147,7 +147,13 @@ rustc_queries! { crate::mir::Promoted, crate::mir::BodyCache<'tcx> >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); - promoted.map(|p| &*tcx.arena.alloc(p)) + promoted.map(|p| { + let cache = tcx.arena.alloc(p); + for body_cache in cache.iter_mut() { + body_cache.ensure_predecessors(); + } + &*cache + }) } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f8feff0def972..cf9fd401e7b1b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2988,7 +2988,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyCache<'tcx, 'tcx> { match instance { ty::InstanceDef::Item(did) => { - self.optimized_mir(did).read_only() + self.optimized_mir(did).unwrap_read_only() } ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) | @@ -2998,7 +2998,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) => { - self.mir_shims(instance).read_only() + self.mir_shims(instance).unwrap_read_only() } } } diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 30dad03648c91..c163ff85563bd 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1080,12 +1080,14 @@ impl<'a, 'tcx> CrateMetadata { } fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyCache<'tcx> { - self.root.per_def.mir.get(self, id) + let mut cache = self.root.per_def.mir.get(self, id) .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) - .decode((self, tcx)) + .decode((self, tcx)); + cache.ensure_predecessors(); + cache } fn get_promoted_mir( @@ -1093,12 +1095,16 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> IndexVec> { - self.root.per_def.promoted_mir.get(self, id) + let mut cache = self.root.per_def.promoted_mir.get(self, id) .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) - .decode((self, tcx)) + .decode((self, tcx)); + for body_cache in cache.iter_mut() { + body_cache.ensure_predecessors(); + } + cache } fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 0170cc8b42abf..6205638c24a01 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -10,7 +10,7 @@ use rustc::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT}; use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ ClearCrossCrate, Local, Location, Body, BodyCache, Mutability, Operand, Place, PlaceBase, - PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind + PlaceElem, PlaceRef, ReadOnlyBodyCache, Static, StaticKind, read_only }; use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -167,8 +167,8 @@ fn do_mir_borrowck<'a, 'tcx>( let mut body_cache = BodyCache::new(body); let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted); - let body_cache = body_cache.read_only(); // no further changes - let promoted: IndexVec<_, _> = promoted.iter().map(|body_cache| body_cache.read_only()).collect(); + let body_cache = read_only!(body_cache); // no further changes + let promoted: IndexVec<_, _> = promoted.iter_mut().map(|body_cache| read_only!(body_cache)).collect(); let location_table = &LocationTable::new(&body_cache); @@ -492,7 +492,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx type FlowState = Flows<'cx, 'tcx>; fn body(&self) -> &'cx Body<'tcx> { - &self.body_cache + self.body_cache.body() } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 9a0392ab1d836..1eaa82ec08e27 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -302,7 +302,8 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - for &pred_block in self.cx.body_cache.predecessors_for(block).iter() { + let body_cache = self.cx.body_cache; + for &pred_block in body_cache.predecessors_for(block).iter() { debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,); // Check whether the variable is (at least partially) diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 92efd383c3c81..e1750af6693c1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -540,7 +540,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. - let parent_body = mem::replace(&mut self.body, &promoted_body_cache); + let parent_body = mem::replace(&mut self.body, promoted_body_cache.body()); // Use new sets of constraints and closure bounds so that we can // modify their locations. diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index aa02c0641e351..ccd6d285a7bc7 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -56,7 +56,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, - body: &self.body_cache, + body: self.body_cache.body(), tcx: self.infcx.tcx, } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 043ba09f52a9a..044e3c4a9b329 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -303,11 +303,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); if let Some(promoted) = promoted { - return Ok(self.tcx.promoted_mir(did)[promoted].read_only()); + return Ok(self.tcx.promoted_mir(did)[promoted].unwrap_read_only()); } match instance { ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { - Ok(self.tcx.optimized_mir(did).read_only()) + Ok(self.tcx.optimized_mir(did).unwrap_read_only()) } else { throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id))) }, diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 8f97a4e7f5c89..0f91b8b28bcf0 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -125,6 +125,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx debug!("make_shim({:?}) = {:?}", instance, result.body()); + result.ensure_predecessors(); tcx.arena.alloc(result) } @@ -928,5 +929,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> { |_, _| Ok(()), ); - tcx.arena.alloc(BodyCache::new(body)) + let mut body_cache = BodyCache::new(body); + body_cache.ensure_predecessors(); + tcx.arena.alloc(body_cache) } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 78628474bce97..d2d4eef1164e4 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -516,7 +516,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult // N.B., this borrow is valid because all the consumers of // `mir_built` force this. - let body = &tcx.mir_built(def_id).borrow(); + let body_cache = &tcx.mir_built(def_id).borrow(); let param_env = tcx.param_env(def_id); @@ -527,8 +527,10 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false), }; - let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env); - checker.visit_body(body.read_only()); + let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body_cache, tcx, param_env); + let mut cache = body_cache.cache().clone(); + let read_only_cache = ReadOnlyBodyCache::from_external_cache(&mut cache, body_cache.body()); + checker.visit_body(read_only_cache); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); UnsafetyCheckResult { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f79f375a7e846..fdfbe59f078b7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -10,7 +10,7 @@ use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp, Rvalue. StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache, - RETURN_PLACE + read_only, RETURN_PLACE }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -93,7 +93,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // That would require an uniform one-def no-mutation analysis // and RPO (or recursing when needing the value of a local). let mut optimization_finder = ConstPropagator::new( - body_cache.read_only(), + read_only!(body_cache), dummy_body, tcx, source @@ -285,7 +285,7 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> { impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new( - body_cache: ReadOnlyBodyCache<'mir, 'tcx>, + body_cache: ReadOnlyBodyCache<'_, 'tcx>, dummy_body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 637f4792029a2..decd3f65c8128 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -21,7 +21,7 @@ use rustc::mir::{ Constant, Local, LocalKind, Location, Place, Body, BodyCache, Operand, Rvalue, - StatementKind + StatementKind, read_only }; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; @@ -40,10 +40,10 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { let mut def_use_analysis = DefUseAnalysis::new(body_cache); loop { - def_use_analysis.analyze(body_cache.read_only()); + def_use_analysis.analyze(read_only!(body_cache)); if eliminate_self_assignments(body_cache, &def_use_analysis) { - def_use_analysis.analyze(body_cache.read_only()); + def_use_analysis.analyze(read_only!(body_cache)); } let mut changed = false; diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 503d24e56ae7b..343cd8e47b28d 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -759,7 +759,7 @@ fn compute_layout<'tcx>( // Use a liveness analysis to compute locals which are live across a suspension point let LivenessInfo { live_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness - } = locals_live_across_suspend_points(tcx, body_cache.read_only(), source, movable); + } = locals_live_across_suspend_points(tcx, read_only!(body_cache), source, movable); // Erase regions from the types passed in from typeck so we can compare them with // MIR types diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index c1c3d39bdc086..f4f7584bfabd1 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -514,7 +514,7 @@ impl Inliner<'tcx> { &self, args: Vec>, callsite: &CallSite<'tcx>, - caller_body: &mut Body<'tcx>, + caller_body_cache: &mut BodyCache<'tcx>, ) -> Vec { let tcx = self.tcx; @@ -543,12 +543,12 @@ impl Inliner<'tcx> { // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. if tcx.is_closure(callsite.callee) { let mut args = args.into_iter(); - let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); - let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); + let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); + let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); assert!(args.next().is_none()); let tuple = Place::from(tuple); - let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body, tcx).ty.kind { + let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body_cache.body(), tcx).ty.kind { s } else { bug!("Closure arguments are not passed as a tuple"); @@ -568,13 +568,13 @@ impl Inliner<'tcx> { )); // Spill to a local to make e.g., `tmp0`. - self.create_temp_if_necessary(tuple_field, callsite, caller_body) + self.create_temp_if_necessary(tuple_field, callsite, caller_body_cache) }); closure_ref_arg.chain(tuple_tmp_args).collect() } else { args.into_iter() - .map(|a| self.create_temp_if_necessary(a, callsite, caller_body)) + .map(|a| self.create_temp_if_necessary(a, callsite, caller_body_cache)) .collect() } } @@ -585,14 +585,14 @@ impl Inliner<'tcx> { &self, arg: Operand<'tcx>, callsite: &CallSite<'tcx>, - caller_body: &mut Body<'tcx>, + caller_body_cache: &mut BodyCache<'tcx>, ) -> Local { // FIXME: Analysis of the usage of the arguments to avoid // unnecessary temporaries. if let Operand::Move(place) = &arg { if let Some(local) = place.as_local() { - if caller_body.local_kind(local) == LocalKind::Temp { + if caller_body_cache.local_kind(local) == LocalKind::Temp { // Reuse the operand if it's a temporary already return local; } @@ -603,16 +603,16 @@ impl Inliner<'tcx> { // Otherwise, create a temporary for the arg let arg = Rvalue::Use(arg); - let ty = arg.ty(caller_body, self.tcx); + let ty = arg.ty(caller_body_cache.body(), self.tcx); let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span); - let arg_tmp = caller_body.local_decls.push(arg_tmp); + let arg_tmp = caller_body_cache.local_decls.push(arg_tmp); let stmt = Statement { source_info: callsite.location, kind: StatementKind::Assign(box(Place::from(arg_tmp), arg)), }; - caller_body[callsite.bb].statements.push(stmt); + caller_body_cache[callsite.bb].statements.push(stmt); arg_tmp } } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index e466b0cb77b72..d8c5c2e0bcab4 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -2,7 +2,7 @@ use rustc::mir::{ Constant, Location, Place, PlaceBase, PlaceRef, Body, BodyCache, Operand, ProjectionElem, - Rvalue, Local + Rvalue, Local, read_only }; use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::ty::{self, TyCtxt}; @@ -24,8 +24,9 @@ impl<'tcx> MirPass<'tcx> for InstCombine { // read-only so that we can do global analyses on the MIR in the process (e.g. // `Place::ty()`). let optimizations = { + let read_only_cache = read_only!(body_cache); let mut optimization_finder = OptimizationFinder::new(body_cache, tcx); - optimization_finder.visit_body(body_cache.read_only()); + optimization_finder.visit_body(read_only_cache); optimization_finder.optimizations }; diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 97c4efc08a375..6c0badff89ebc 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -334,6 +334,7 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { let (body, _) = tcx.mir_validated(def_id); let mut body_cache = body.steal(); run_optimization_passes(tcx, &mut body_cache, def_id, None); + body_cache.ensure_predecessors(); tcx.arena.alloc(body_cache) } @@ -348,6 +349,7 @@ fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec MirPass<'tcx> for SimplifyLocals { fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { trace!("running SimplifyLocals on {:?}", source); let locals = { + let read_only_cache = read_only!(body_cache); let mut marker = DeclMarker { locals: BitSet::new_empty(body_cache.local_decls.len()), body: body_cache, }; - marker.visit_body(body_cache.read_only()); + marker.visit_body(read_only_cache); // Return pointer and arguments are always live marker.locals.insert(RETURN_PLACE); for arg in body_cache.args_iter() { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index d3fbfaf384a91..784ccf5a6b688 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -41,8 +41,9 @@ impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { let mut patch = MirPatch::new(body_cache); let param_env = tcx.param_env(src.def_id()); { + let read_only_cache = read_only!(body_cache); let mut visitor = UniformArrayMoveOutVisitor{ body: body_cache, patch: &mut patch, tcx, param_env}; - visitor.visit_body(body_cache.read_only()); + visitor.visit_body(read_only_cache); } patch.apply(body_cache); } @@ -188,11 +189,12 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { let mut patch = MirPatch::new(body_cache); let param_env = tcx.param_env(src.def_id()); { + let read_only_cache = read_only!(body_cache); let mut visitor = RestoreDataCollector { locals_use: IndexVec::from_elem(LocalUse::new(), &body_cache.local_decls), candidates: vec![], }; - visitor.visit_body(body_cache.read_only()); + visitor.visit_body(read_only_cache); for candidate in &visitor.candidates { let statement = &body_cache[candidate.block].statements[candidate.statement_index]; From 35590b5cc8135b21e8cbb50d059febba5136d41b Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sun, 27 Oct 2019 22:45:02 -0400 Subject: [PATCH 29/47] Fix typos caused during rebase --- src/librustc_mir/borrow_check/conflict_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 4 ++-- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/no_landing_pads.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index b44ef1c1706a4..d9686ac21929b 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -244,7 +244,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } let span = if let Some(local) = place.as_local() { - let decl = &self.body.local_decls[local]; + let decl = &self.body_cache.local_decls[local]; Some(decl.source_info.span) } else { None diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 6205638c24a01..426c019059645 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1152,7 +1152,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // (e.g., `x = ...`) so long as it has never been initialized // before (at this point in the flow). if let Some(local) = place_span.0.as_local() { - if let Mutability::Not = self.body+cache.local_decls[local].mutability { + if let Mutability::Not = self.body_cache.local_decls[local].mutability { // check for reassignments to immutable local variables self.check_if_reassignment_to_immutable_state( location, @@ -1306,7 +1306,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Operand::Move(ref place) | Operand::Copy(ref place) => { match place.as_local() { Some(local) if !self.body_cache.local_decls[local].is_user_variable() => { - if self.body.local_decls[local].ty.is_mutable_ptr() { + if self.body_cache.local_decls[local].ty.is_mutable_ptr() { // The variable will be marked as mutable by the borrow. return; } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index fdfbe59f078b7..ddd9ccbe64a5a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -8,7 +8,7 @@ use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, BodyCache, Operand, Local, UnOp, - Rvalue. StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, + Rvalue, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, SourceScope, SourceScopeData, LocalDecl, BasicBlock, ReadOnlyBodyCache, read_only, RETURN_PLACE }; diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 07dd4120528ad..4f290f487b9c7 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -18,7 +18,7 @@ impl<'tcx> NoLandingPads<'tcx> { impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - no_landing_pads(tcx, body) + no_landing_pads(tcx, body_cache) } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index e409bb0842903..3b4b50c657be2 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -831,7 +831,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.temps[temp] = TempState::PromotedOut; } - let num_stmts = self.source_cacje[loc.block].statements.len(); + let num_stmts = self.source_cache[loc.block].statements.len(); let new_temp = self.promoted_cache.local_decls.push( LocalDecl::new_temp(self.source_cache.local_decls[temp].ty, self.source_cache.local_decls[temp].source_info.span)); From 67b7a78231c84f9e864d7074f2fc8f092290873b Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 28 Oct 2019 18:16:25 -0400 Subject: [PATCH 30/47] Fix tidy errors --- src/librustc/mir/cache.rs | 11 ++++- src/librustc/mir/mod.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 6 ++- src/librustc_mir/borrow_check/borrow_set.rs | 3 +- .../borrow_check/conflict_errors.rs | 44 ++++++++++++++----- .../borrow_check/error_reporting.rs | 21 ++++++--- src/librustc_mir/borrow_check/mod.rs | 10 +++-- .../borrow_check/mutability_errors.rs | 8 +++- src/librustc_mir/borrow_check/nll/mod.rs | 8 +++- .../borrow_check/nll/type_check/mod.rs | 19 ++++++-- .../dataflow/impls/storage_liveness.rs | 4 +- src/librustc_mir/shim.rs | 4 +- src/librustc_mir/transform/add_call_guards.rs | 4 +- .../transform/add_moves_for_packed_drops.rs | 4 +- .../transform/cleanup_post_borrowck.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 4 +- src/librustc_mir/transform/copy_prop.rs | 16 ++++--- src/librustc_mir/transform/deaggregator.rs | 4 +- src/librustc_mir/transform/dump_mir.rs | 5 ++- src/librustc_mir/transform/generator.rs | 12 +++-- src/librustc_mir/transform/inline.rs | 13 ++++-- src/librustc_mir/transform/mod.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 14 +++++- src/librustc_mir/transform/simplify.rs | 8 +++- .../transform/uniform_array_move_out.rs | 11 +++-- src/librustc_mir/util/liveness.rs | 3 +- 26 files changed, 182 insertions(+), 62 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 7a52dea787a2d..204b3d9f7e3af 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -43,7 +43,11 @@ macro_rules! get_predecessors { macro_rules! impl_predecessor_locations { ( ( $($pub:ident)? ) $name:ident $($mutability:ident)?) => { - $($pub)? fn $name<'a>(&'a $($mutability)? self, loc: Location, body: &'a Body<'a>) -> impl Iterator + 'a { + $($pub)? fn $name<'a>( + &'a $($mutability)? self, + loc: Location, + body: &'a Body<'a> + ) -> impl Iterator + 'a { let if_zero_locations = if loc.statement_index == 0 { let predecessor_blocks = get_predecessors!($($mutability)? self, loc.block, body); let num_predecessor_blocks = predecessor_blocks.len(); @@ -119,7 +123,10 @@ impl Cache { impl_predecessor_locations!(() unwrap_predecessor_locations); #[inline] - pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec> { + pub fn basic_blocks_mut<'a, 'tcx>( + &mut self, + body: &'a mut Body<'tcx> + ) -> &'a mut IndexVec> { debug!("bbm: Clearing predecessors cache for body at: {:?}", body.span.data()); self.invalidate_predecessors(); &mut body.basic_blocks diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index fdc3adabf0c55..1b1c7573484f9 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -38,7 +38,7 @@ use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -// TODO(nashenas88) Cache only exported for use in librustc_mir/transform/check_unsafety.rs +// FIXME(nashenas88) Cache only exported for use in librustc_mir/transform/check_unsafety.rs pub use crate::mir::cache::{BodyCache, Cache, ReadOnlyBodyCache}; pub use crate::read_only; diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 281539277cb77..0790526e9f96b 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -591,7 +591,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir.body(), tcx); + let place_ty = mir::Place::ty_from( + place_ref.base, + place_ref.projection, + self.mir.body(), + tcx); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index d1af7461f4754..1553131c5d615 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -106,7 +106,8 @@ impl LocalsStateAtExit { if locals_are_invalidated_at_exit { LocalsStateAtExit::AllAreInvalidated } else { - let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body_cache.local_decls.len())); + let mut has_storage_dead + = HasStorageDead(BitSet::new_empty(body_cache.local_decls.len())); has_storage_dead.visit_body(body_cache); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index d9686ac21929b..7f2d6a68d02c7 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -205,9 +205,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } - let ty = - Place::ty_from(used_place.base, used_place.projection, self.body_cache.body(), self.infcx.tcx) - .ty; + let ty = Place::ty_from( + used_place.base, + used_place.projection, + self.body_cache.body(), + self.infcx.tcx + ).ty; let needs_note = match ty.kind { ty::Closure(id, _) => { let tables = self.infcx.tcx.typeck_tables_of(id); @@ -619,7 +622,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Define a small closure that we can use to check if the type of a place // is a union. let union_ty = |place_base, place_projection| { - let ty = Place::ty_from(place_base, place_projection, self.body_cache.body(), self.infcx.tcx).ty; + let ty = Place::ty_from( + place_base, + place_projection, + self.body_cache.body(), + self.infcx.tcx + ).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) }; let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned()); @@ -1174,11 +1182,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; // FIXME use a better heuristic than Spans - let reference_desc = if return_span == self.body_cache.source_info(borrow.reserve_location).span { - "reference to" - } else { - "value referencing" - }; + let reference_desc + = if return_span == self.body_cache.source_info(borrow.reserve_location).span { + "reference to" + } else { + "value referencing" + }; let (place_desc, note) = if let Some(place_desc) = opt_place_desc { let local_kind = if let Some(local) = borrow.borrowed_place.as_local() { @@ -1623,7 +1632,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::LocalStorageDead | StorageDeadOrDrop::BoxedStorageDead => { assert!( - Place::ty_from(&place.base, proj_base, self.body_cache.body(), tcx).ty.is_box(), + Place::ty_from( + &place.base, + proj_base, + self.body_cache.body(), + tcx + ).ty.is_box(), "Drop of value behind a reference or raw pointer" ); StorageDeadOrDrop::BoxedStorageDead @@ -1631,7 +1645,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { StorageDeadOrDrop::Destructor(_) => base_access, }, ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = Place::ty_from(&place.base, proj_base, self.body_cache.body(), tcx).ty; + let base_ty = Place::ty_from( + &place.base, + proj_base, + self.body_cache.body(), + tcx + ).ty; match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor @@ -1734,7 +1753,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Next, look through the rest of the block, checking if we are assigning the // `target` (that is, the place that contains our borrow) to anything. let mut annotated_closure = None; - for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] { + for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] + { debug!( "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", target, stmt diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 8267e5c1c4bd2..3b394f853a7fd 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -369,8 +369,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, field) } ProjectionElem::Downcast(_, variant_index) => { - let base_ty = - Place::ty_from(place.base, place.projection, self.body_cache.body(), self.infcx.tcx).ty; + let base_ty = Place::ty_from( + place.base, + place.projection, + self.body_cache.body(), + self.infcx.tcx).ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } ProjectionElem::Field(_, field_type) => { @@ -498,9 +501,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, .. }) = bbd.terminator { - if let Some(source) - = BorrowedContentSource::from_call(func.ty(self.body_cache.body(), tcx), tcx) - { + if let Some(source) = BorrowedContentSource::from_call( + func.ty(self.body_cache.body(), tcx), + tcx + ) { return source; } } @@ -512,7 +516,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find an overloaded deref or index, then assume it's a // built in deref and check the type of the base. - let base_ty = Place::ty_from(deref_base.base, deref_base.projection, self.body_cache.body(), tcx).ty; + let base_ty = Place::ty_from( + deref_base.base, + deref_base.projection, + self.body_cache.body(), + tcx + ).ty; if base_ty.is_unsafe_ptr() { BorrowedContentSource::DerefRawPointer } else if base_ty.is_mutable_ptr() { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 426c019059645..1ff26acd361b5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -168,7 +168,10 @@ fn do_mir_borrowck<'a, 'tcx>( let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted); let body_cache = read_only!(body_cache); // no further changes - let promoted: IndexVec<_, _> = promoted.iter_mut().map(|body_cache| read_only!(body_cache)).collect(); + let promoted: IndexVec<_, _> = promoted + .iter_mut() + .map(|body_cache| read_only!(body_cache)) + .collect(); let location_table = &LocationTable::new(&body_cache); @@ -303,7 +306,7 @@ fn do_mir_borrowck<'a, 'tcx>( let mut initial_diag = mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow); - let scope = mbcx.body.source_info(location).scope; + let scope = mbcx.body_cache.source_info(location).scope; let lint_root = match &mbcx.body_cache.source_scopes[scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => id, @@ -339,7 +342,8 @@ fn do_mir_borrowck<'a, 'tcx>( debug!("mbcx.used_mut: {:?}", mbcx.used_mut); let used_mut = mbcx.used_mut; - for local in mbcx.body_cache.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { + for local in mbcx.body_cache.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) + { let local_decl = &mbcx.body_cache.local_decls[local]; let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index feaa5fd3a5519..0ec72150d97b3 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -61,8 +61,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(&the_place_err.base, proj_base, self.body_cache.body(), self.infcx.tcx).ty - )); + Place::ty_from( + &the_place_err.base, + proj_base, + self.body_cache.body(), + self.infcx.tcx + ).ty)); item_msg = format!("`{}`", access_place_desc.unwrap()); if self.is_upvar_field_projection(access_place.as_ref()).is_some() { diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index bf11d348409ca..519b59304b768 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -298,7 +298,13 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // We also have a `#[rustc_nll]` annotation that causes us to dump // information - dump_annotation(infcx, body_cache.body(), def_id, ®ioncx, &closure_region_requirements, errors_buffer); + dump_annotation( + infcx, + body_cache.body(), + def_id, + ®ioncx, + &closure_region_requirements, + errors_buffer); (regioncx, polonius_output, closure_region_requirements) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index e1750af6693c1..7200f8d8ae595 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -168,8 +168,17 @@ pub(crate) fn type_check<'tcx>( &mut borrowck_context, &universal_region_relations, |mut cx| { - cx.equate_inputs_and_outputs(body_cache.body(), universal_regions, &normalized_inputs_and_output); - liveness::generate(&mut cx, body_cache, elements, flow_inits, move_data, location_table); + cx.equate_inputs_and_outputs( + body_cache.body(), + universal_regions, + &normalized_inputs_and_output); + liveness::generate( + &mut cx, + body_cache, + elements, + flow_inits, + move_data, + location_table); translate_outlives_facts(cx.borrowck_context); }, @@ -535,7 +544,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place_ty } - fn sanitize_promoted(&mut self, promoted_body_cache: ReadOnlyBodyCache<'b, 'tcx>, location: Location) { + fn sanitize_promoted( + &mut self, + promoted_body_cache: ReadOnlyBodyCache<'b, 'tcx>, + location: Location + ) { // Determine the constraints from the promoted MIR by running the type // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index fc344f9b25259..3f76d0e3a3cec 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -87,7 +87,9 @@ impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { ) -> Self { RequiresStorage { body_cache, - borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body_cache.body())), + borrowed_locals: RefCell::new( + DataflowResultsCursor::new(borrowed_locals, body_cache.body()) + ), } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 0f91b8b28bcf0..9b54c66e1e572 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -165,7 +165,9 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span) .collect() } -fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) -> BodyCache<'tcx> { +fn build_drop_shim<'tcx>( + tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option> +) -> BodyCache<'tcx> { debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); // Check if this is a generator, if so, return the drop glue for it diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 071ad002c169d..48aa53a58c9b5 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -31,7 +31,9 @@ pub use self::AddCallGuards::*; */ impl<'tcx> MirPass<'tcx> for AddCallGuards { - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { self.add_call_guards(body_cache); } } diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index aebd632978ad1..21bc679b9a039 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -46,7 +46,9 @@ impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { } } -pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>, def_id: DefId) { +pub fn add_moves_for_packed_drops<'tcx>( + tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>, def_id: DefId +) { let patch = add_moves_for_packed_drops_patch(tcx, body_cache, def_id); patch.apply(body_cache); } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 3ea41816ebefe..23ab2c28063bb 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -29,7 +29,9 @@ pub struct DeleteNonCodegenStatements<'tcx> { } impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { let mut delete = DeleteNonCodegenStatements { tcx }; delete.visit_body(body_cache); } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ddd9ccbe64a5a..3ea97ff68fd3f 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -42,7 +42,9 @@ const MAX_ALLOC_LIMIT: u64 = 1024; pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { return; diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index decd3f65c8128..d2f83eeadeb84 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -31,7 +31,9 @@ use crate::util::def_use::DefUseAnalysis; pub struct CopyPropagation; impl<'tcx> MirPass<'tcx> for CopyPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { @@ -100,7 +102,10 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { let maybe_action = match operand { Operand::Copy(ref src_place) | Operand::Move(ref src_place) => { - Action::local_copy(&body_cache, &def_use_analysis, src_place) + Action::local_copy( + &body_cache, + &def_use_analysis, + src_place) } Operand::Constant(ref src_constant) => { Action::constant(src_constant) @@ -129,8 +134,8 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } } - changed = - action.perform(body_cache, &def_use_analysis, dest_local, location, tcx) || changed; + changed = action.perform(body_cache, &def_use_analysis, dest_local, location, tcx) + || changed; // FIXME(pcwalton): Update the use-def chains to delete the instructions instead of // regenerating the chains. break @@ -273,7 +278,8 @@ impl<'tcx> Action<'tcx> { } // Replace all uses of the destination local with the source local. - def_use_analysis.replace_all_defs_and_uses_with(dest_local, body_cache, src_local, tcx); + def_use_analysis + .replace_all_defs_and_uses_with(dest_local, body_cache, src_local, tcx); // Finally, zap the now-useless assignment instruction. debug!(" Deleting assignment"); diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 3d0bf6192dc49..5ad034539e0e2 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -6,7 +6,9 @@ use crate::util::expand_aggregate; pub struct Deaggregator; impl<'tcx> MirPass<'tcx> for Deaggregator { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 987f0fde2e379..3dbebf885f70e 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -18,8 +18,9 @@ impl<'tcx> MirPass<'tcx> for Marker { Cow::Borrowed(self.0) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body_cache: &mut BodyCache<'tcx>) { - } + fn run_pass( + &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body_cache: &mut BodyCache<'tcx> + ) {} } pub struct Disambiguator { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 343cd8e47b28d..c79178dcac78f 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -860,7 +860,9 @@ fn insert_switch<'tcx>( } } -fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body_cache: &mut BodyCache<'tcx>) { +fn elaborate_generator_drops<'tcx>( + tcx: TyCtxt<'tcx>, def_id: DefId, body_cache: &mut BodyCache<'tcx> +) { use crate::util::elaborate_drops::{elaborate_drop, Unwind}; use crate::util::patch::MirPatch; use crate::shim::DropShimElaborator; @@ -993,7 +995,9 @@ fn create_generator_drop_shim<'tcx>( body_cache } -fn insert_term_block<'tcx>(body_cache: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { +fn insert_term_block<'tcx>( + body_cache: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx> +) -> BasicBlock { let term_block = BasicBlock::new(body_cache.basic_blocks().len()); let source_info = source_info(body_cache); body_cache.basic_blocks_mut().push(BasicBlockData { @@ -1164,7 +1168,9 @@ where } impl<'tcx> MirPass<'tcx> for StateTransform { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { let yield_ty = if let Some(yield_ty) = body_cache.yield_ty { yield_ty } else { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index f4f7584bfabd1..6721982e8469e 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -38,7 +38,9 @@ struct CallSite<'tcx> { } impl<'tcx> MirPass<'tcx> for Inline { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { Inliner { tcx, source }.run_pass(body_cache); } @@ -136,7 +138,8 @@ impl Inliner<'tcx> { debug!("attempting to inline callsite {:?} - success", callsite); // Add callsites from inlined function - for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated().skip(start) { + for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated().skip(start) + { if let Some(new_callsite) = self.get_valid_function_call(bb, bb_data, caller_body_cache, @@ -543,8 +546,10 @@ impl Inliner<'tcx> { // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. if tcx.is_closure(callsite.callee) { let mut args = args.into_iter(); - let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); - let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); + let self_ + = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); + let tuple + = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); assert!(args.next().is_none()); let tuple = Place::from(tuple); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 6c0badff89ebc..3b2cea53d1c50 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -338,7 +338,7 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { tcx.arena.alloc(body_cache) } -fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec> { +fn promoted_mir(tcx: TyCtxt, def_id: DefId) -> &IndexVec { if tcx.is_constructor(def_id) { return tcx.intern_promoted(IndexVec::new()); } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 87fcef69238d8..6e877d2fb74e0 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -64,10 +64,20 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_uninits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { - sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_def_inits); + sanity_check_via_rustc_peek( + tcx, + body_cache.body(), + def_id, + &attributes, + &flow_def_inits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() { - sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_indirectly_mut); + sanity_check_via_rustc_peek( + tcx, + body_cache.body(), + def_id, + &attributes, + &flow_indirectly_mut); } if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index e2cf9538f1fe6..949059f19aeda 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -56,7 +56,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { Cow::Borrowed(&self.label) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body_cache.body()); simplify_cfg(body_cache); } @@ -293,7 +295,9 @@ pub fn remove_dead_blocks(body_cache: &mut BodyCache<'_>) { pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass( + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + ) { trace!("running SimplifyLocals on {:?}", source); let locals = { let read_only_cache = read_only!(body_cache); diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 784ccf5a6b688..62a2f269facc1 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -42,7 +42,8 @@ impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { let param_env = tcx.param_env(src.def_id()); { let read_only_cache = read_only!(body_cache); - let mut visitor = UniformArrayMoveOutVisitor{ body: body_cache, patch: &mut patch, tcx, param_env}; + let mut visitor + = UniformArrayMoveOutVisitor{ body: body_cache, patch: &mut patch, tcx, param_env}; visitor.visit_body(read_only_cache); } patch.apply(body_cache); @@ -219,8 +220,12 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2); let opt_size = opt_src_place.and_then(|src_place| { - let src_ty = - Place::ty_from(src_place.base, src_place.projection, body_cache.body(), tcx).ty; + let src_ty = Place::ty_from( + src_place.base, + src_place.projection, + body_cache.body(), + tcx + ).ty; if let ty::Array(_, ref size_o) = src_ty.kind { size_o.try_eval_usize(tcx, param_env) } else { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 37611561d58ef..1773dbd2e34a1 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -83,7 +83,8 @@ pub fn liveness_of_locals( // FIXME(ecstaticmorse): Reverse post-order on the reverse CFG may generate a better iteration // order when cycles are present, but the overhead of computing the reverse CFG may outweigh // any benefits. Benchmark this and find out. - let mut dirty_queue: WorkQueue = WorkQueue::with_none(body_cache.basic_blocks().len()); + let mut dirty_queue: WorkQueue + = WorkQueue::with_none(body_cache.basic_blocks().len()); for (bb, _) in traversal::postorder(body_cache.body()) { dirty_queue.insert(bb); } From ab657e3b6bc147f06ccf79b5a82f33107bfc668b Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 28 Oct 2019 19:32:56 -0400 Subject: [PATCH 31/47] Fix typo --- src/librustc_mir/transform/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 3b2cea53d1c50..1265a1a838624 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -338,7 +338,7 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { tcx.arena.alloc(body_cache) } -fn promoted_mir(tcx: TyCtxt, def_id: DefId) -> &IndexVec { +fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec> { if tcx.is_constructor(def_id) { return tcx.intern_promoted(IndexVec::new()); } From e54c610f8543348b92665a86f0c642bdfbd75197 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 4 Nov 2019 09:03:02 -0500 Subject: [PATCH 32/47] Fix compilation errors created during rebase --- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 830b7da8c0373..5609047c5c4d3 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -28,7 +28,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead // of putting everything in allocas just so we can use llvm.dbg.declare. if fx.cx.sess().opts.debuginfo == DebugInfo::Full { - if mir.local_kind(local) == mir::LocalKind::Arg { + if fx.mir.local_kind(local) == mir::LocalKind::Arg { analyzer.not_ssa(local); continue; } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 2a012cd2ed943..43c2d27449fe0 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -171,7 +171,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( funclets, locals: IndexVec::new(), debug_context, - per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), + per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir_body), }; let memory_locals = analyze::non_ssa_locals(&fx); From c42bdb8c7465389a4d71d88ff8d910d6307be9ba Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 4 Nov 2019 19:52:19 -0500 Subject: [PATCH 33/47] Undo minor changes that weren't needed, fix one lifetime typo --- src/librustc_codegen_ssa/mir/analyze.rs | 9 +++-- src/librustc_codegen_ssa/mir/block.rs | 38 ++++++++++--------- src/librustc_codegen_ssa/mir/mod.rs | 7 ++-- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +-- .../graph/reference.rs | 1 + 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 5609047c5c4d3..d6fa67b053354 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -17,13 +17,14 @@ use super::FunctionCx; use crate::traits::*; pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - fx: &FunctionCx<'a, 'tcx, Bx> + fx: &FunctionCx<'a, 'tcx, Bx>, ) -> BitSet { + let mir = fx.mir; let mut analyzer = LocalAnalyzer::new(fx); - analyzer.visit_body(fx.mir); + analyzer.visit_body(mir); - for (local, decl) in fx.mir.local_decls.iter_enumerated() + for (local, decl) in mir.local_decls.iter_enumerated() { // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead // of putting everything in allocas just so we can use llvm.dbg.declare. @@ -65,7 +66,7 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { first_assignment: IndexVec, } -impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { +impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self { let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index f661e7bba806f..2d41c8426decc 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - target: mir::BasicBlock + target: mir::BasicBlock, ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; let lltarget = fx.blocks[target]; @@ -66,7 +66,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( &self, fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - target: mir::BasicBlock + target: mir::BasicBlock, ) -> Bx::BasicBlock { let (lltarget, is_cleanupret) = self.lltarget(fx, target); if is_cleanupret { @@ -153,7 +153,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { // a loop. fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( &self, - mir: mir::ReadOnlyBodyCache<'_, 'tcx>, + mir: mir::ReadOnlyBodyCache<'b, 'tcx>, bx: &mut Bx, targets: &[mir::BasicBlock], ) { @@ -173,9 +173,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Codegen implementations for some terminator variants. impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Generates code for a `Resume` terminator. - fn codegen_resume_terminator<'c>( + fn codegen_resume_terminator<'b>( &mut self, - helper: TerminatorCodegenHelper<'c, 'tcx>, + helper: TerminatorCodegenHelper<'b, 'tcx>, mut bx: Bx, ) { if let Some(funclet) = helper.funclet(self) { @@ -201,9 +201,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - fn codegen_switchint_terminator<'c>( + fn codegen_switchint_terminator<'b>( &mut self, - helper: TerminatorCodegenHelper<'c, 'tcx>, + helper: TerminatorCodegenHelper<'b, 'tcx>, mut bx: Bx, discr: &mir::Operand<'tcx>, switch_ty: Ty<'tcx>, @@ -316,9 +316,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } - fn codegen_drop_terminator<'c>( + fn codegen_drop_terminator<'b>( &mut self, - helper: TerminatorCodegenHelper<'c, 'tcx>, + helper: TerminatorCodegenHelper<'b, 'tcx>, mut bx: Bx, location: &mir::Place<'tcx>, target: mir::BasicBlock, @@ -367,9 +367,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { unwind); } - fn codegen_assert_terminator<'c>( + fn codegen_assert_terminator<'b>( &mut self, - helper: TerminatorCodegenHelper<'c, 'tcx>, + helper: TerminatorCodegenHelper<'b, 'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, cond: &mir::Operand<'tcx>, @@ -446,9 +446,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); } - fn codegen_call_terminator<'c>( + fn codegen_call_terminator<'b>( &mut self, - helper: TerminatorCodegenHelper<'c, 'tcx>, + helper: TerminatorCodegenHelper<'b, 'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, @@ -581,7 +581,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Prepare the return value destination let ret_dest = if let Some((ref dest, _)) = *destination { let is_intrinsic = intrinsic.is_some(); - self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, is_intrinsic) + self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, + is_intrinsic) } else { ReturnDest::Nothing }; @@ -805,7 +806,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, mut bx: Bx, bb: mir::BasicBlock, - terminator: &mir::Terminator<'tcx>, + terminator: &mir::Terminator<'tcx> ) { debug!("codegen_terminator: {:?}", terminator); @@ -834,7 +835,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { - self.codegen_switchint_terminator(helper, bx, discr, switch_ty, values, targets); + self.codegen_switchint_terminator(helper, bx, discr, switch_ty, + values, targets); } mir::TerminatorKind::Return => { @@ -1034,7 +1036,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// No-op in MSVC SEH scheme. fn landing_pad_to( &mut self, - target_bb: mir::BasicBlock, + target_bb: mir::BasicBlock ) -> Bx::BasicBlock { if let Some(block) = self.landing_pads[target_bb] { return block; @@ -1103,7 +1105,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, dest: &mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, - llargs: &mut Vec, is_intrinsic: bool, + llargs: &mut Vec, is_intrinsic: bool ) -> ReturnDest<'tcx, Bx::Value> { // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 43c2d27449fe0..9549749f5120e 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -323,13 +323,14 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, memory_locals: &BitSet, ) -> Vec> { + let mir = fx.mir; let mut idx = 0; let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - fx.mir.args_iter().enumerate().map(|(arg_index, local)| { - let arg_decl = &fx.mir.local_decls[local]; + mir.args_iter().enumerate().map(|(arg_index, local)| { + let arg_decl = &mir.local_decls[local]; - if Some(local) == fx.mir.spread_arg { + if Some(local) == mir.spread_arg { // This argument (e.g., the last argument in the "rust-call" ABI) // is a tuple that was spread at the ABI level and now we have // to reconstruct it into a tuple local variable, from multiple diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 680c5b873b02e..fb5fc561b08de 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -696,11 +696,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn rvalue_creates_operand( - &self, - rvalue: &mir::Rvalue<'tcx>, - span: Span, - ) -> bool { + pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Ref(..) | mir::Rvalue::Len(..) | diff --git a/src/librustc_data_structures/graph/reference.rs b/src/librustc_data_structures/graph/reference.rs index eab217692d049..9442bb3cdec3b 100644 --- a/src/librustc_data_structures/graph/reference.rs +++ b/src/librustc_data_structures/graph/reference.rs @@ -21,6 +21,7 @@ impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G { (**self).successors(node) } } + impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G { fn predecessors(&self, node: Self::Node) From 595d161d36b5126e75840c29ce0413a07feebd02 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 6 Nov 2019 00:04:53 -0500 Subject: [PATCH 34/47] Remove BodyCache.body and rely on Deref as much as possible for ReadOnlyBodyCache --- src/librustc/mir/cache.rs | 22 +++++++++++-------- src/librustc/mir/visit.rs | 12 ++++------ src/librustc/ty/mod.rs | 2 +- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 9 ++++---- src/librustc_codegen_ssa/mir/mod.rs | 2 +- src/librustc_codegen_ssa/mir/place.rs | 5 +++-- src/librustc_codegen_ssa/mir/rvalue.rs | 6 ++--- src/librustc_mir/borrow_check/borrow_set.rs | 2 +- .../borrow_check/conflict_errors.rs | 10 ++++----- .../borrow_check/error_reporting.rs | 6 ++--- src/librustc_mir/borrow_check/mod.rs | 8 ++++--- src/librustc_mir/borrow_check/move_errors.rs | 8 +++---- .../borrow_check/mutability_errors.rs | 8 +++---- .../borrow_check/nll/explain_borrow/mod.rs | 2 +- .../borrow_check/nll/invalidation.rs | 2 +- src/librustc_mir/borrow_check/nll/mod.rs | 14 ++++++------ .../borrow_check/nll/region_infer/mod.rs | 1 - .../borrow_check/nll/type_check/mod.rs | 6 ++--- src/librustc_mir/borrow_check/prefixes.rs | 8 +++---- src/librustc_mir/monomorphize/collector.rs | 3 +-- src/librustc_mir/shim.rs | 8 +++---- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir/transform/generator.rs | 4 ++-- src/librustc_mir/transform/inline.rs | 6 ++--- .../transform/remove_noop_landing_pads.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 8 +++---- src/librustc_mir/transform/simplify.rs | 4 ++-- .../transform/uniform_array_move_out.rs | 2 +- src/librustc_mir/util/liveness.rs | 2 +- 30 files changed, 89 insertions(+), 87 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 204b3d9f7e3af..e7ca7d6a95f5f 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -2,7 +2,7 @@ use rustc_index::vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use crate::ich::StableHashingContext; -use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors}; +use crate::mir::{BasicBlock, BasicBlockData, Body, HasLocalDecls, LocalDecls, Location, Successors}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use std::iter; @@ -181,14 +181,6 @@ impl BodyCache<'tcx> { ReadOnlyBodyCache::new(&self.cache, &self.body) } - pub fn body(&self) -> &Body<'tcx> { - &self.body - } - - pub fn body_mut(&mut self) -> &mut Body<'tcx> { - &mut self.body - } - pub fn cache(&self) -> &Cache { &self.cache } pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { @@ -231,6 +223,12 @@ impl<'tcx> DerefMut for BodyCache<'tcx> { } } +impl<'tcx> HasLocalDecls<'tcx> for BodyCache<'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx> { + &self.body.local_decls + } +} + #[derive(Copy, Clone, Debug)] pub struct ReadOnlyBodyCache<'a, 'tcx> { cache: &'a Cache, @@ -349,6 +347,12 @@ impl Index for ReadOnlyBodyCache<'a, 'tcx> { } } +impl<'a, 'tcx> HasLocalDecls<'tcx> for ReadOnlyBodyCache<'a, 'tcx> { + fn local_decls(&self) -> &LocalDecls<'tcx> { + &self.body.local_decls + } +} + CloneTypeFoldableAndLiftImpls! { Cache, } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 68694f1b71711..18776778ebb91 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -254,14 +254,10 @@ macro_rules! make_mir_visitor { fn super_body( &mut self, - body_cache: body_cache_type!($($mutability)? '_, 'tcx) + $($mutability)? body_cache: body_cache_type!($($mutability)? '_, 'tcx) ) { - macro_rules! body { - (mut) => (body_cache.body_mut()); - () => (body_cache.body()); - } - let span = body_cache.body().span; - if let Some(yield_ty) = &$($mutability)? body!($($mutability)?).yield_ty { + let span = body_cache.span; + if let Some(yield_ty) = &$($mutability)? body_cache.yield_ty { self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE, @@ -279,7 +275,7 @@ macro_rules! make_mir_visitor { self.visit_basic_block_data(bb, data); } - let body = body!($($mutability)?); + let body: & $($mutability)? Body<'_> = & $($mutability)? body_cache; for scope in &$($mutability)? body.source_scopes { self.visit_source_scope_data(scope); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cf9fd401e7b1b..c9a934e9ebd84 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3023,7 +3023,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> { - self.optimized_mir(def_id).body().generator_layout.as_ref().unwrap() + self.optimized_mir(def_id).generator_layout.as_ref().unwrap() } /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index d6fa67b053354..782c0f7e13903 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -131,7 +131,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir.body(), cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, &self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 2d41c8426decc..0920de7d903f2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -324,7 +324,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(self.mir.body(), bx.tcx()).ty; + let ty = location.ty(&self.mir, bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); @@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir.body(), bx.tcx()); + let op_ty = op_arg.ty(&self.mir, bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); @@ -569,7 +569,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // a NOP let target = destination.as_ref().unwrap().1; helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) + helper.funclet_br(self, &mut bx, target) } return; } @@ -791,7 +791,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bb: mir::BasicBlock, ) { let mut bx = self.build_block(bb); - let data = &self.mir.body()[bb]; + let mir = self.mir; + let data = &mir[bb]; debug!("codegen_block({:?}={:?})", bb, data); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 9549749f5120e..9374c829e4f96 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -156,7 +156,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }).collect(); let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); - let mir_body = mir.body(); + let mir_body: &Body<'_> = &mir; let mut fx = FunctionCx { instance, mir, diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 0790526e9f96b..5ea08edd035be 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -594,8 +594,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let place_ty = mir::Place::ty_from( place_ref.base, place_ref.projection, - self.mir.body(), - tcx); + &self.mir, + tcx, + ); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index fb5fc561b08de..fa157a0c35f90 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(self.mir.body(), bx.tcx()); + let discr_ty = rvalue.ty(&self.mir, bx.tcx()); let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { @@ -513,7 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(self.mir.body(), self.cx.tcx()); + let ty = rvalue.ty(&self.mir, self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -710,7 +710,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(self.mir.body(), self.cx.tcx()); + let ty = rvalue.ty(&self.mir, self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 1553131c5d615..aaf067a53610e 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -130,7 +130,7 @@ impl<'tcx> BorrowSet<'tcx> { ) -> Self { let mut visitor = GatherBorrows { tcx, - body: body_cache.body(), + body: &body_cache, idx_vec: IndexVec::new(), location_map: Default::default(), activation_map: Default::default(), diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 7f2d6a68d02c7..9dac6d70dff85 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -208,7 +208,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from( used_place.base, used_place.projection, - self.body_cache.body(), + &self.body_cache, self.infcx.tcx ).ty; let needs_note = match ty.kind { @@ -225,7 +225,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mpi = self.move_data.moves[move_out_indices[0]].path; let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(self.body_cache.body(), self.infcx.tcx).ty; + let ty = place.ty(&self.body_cache, self.infcx.tcx).ty; let opt_name = self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); let note_msg = match opt_name { @@ -625,7 +625,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from( place_base, place_projection, - self.body_cache.body(), + &self.body_cache, self.infcx.tcx ).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) @@ -1635,7 +1635,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Place::ty_from( &place.base, proj_base, - self.body_cache.body(), + &self.body_cache, tcx ).ty.is_box(), "Drop of value behind a reference or raw pointer" @@ -1648,7 +1648,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( &place.base, proj_base, - self.body_cache.body(), + &self.body_cache, tcx ).ty; match base_ty.kind { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 3b394f853a7fd..3515c4bfe09d1 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -372,7 +372,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( place.base, place.projection, - self.body_cache.body(), + &self.body_cache, self.infcx.tcx).ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } @@ -502,7 +502,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }) = bbd.terminator { if let Some(source) = BorrowedContentSource::from_call( - func.ty(self.body_cache.body(), tcx), + func.ty(&self.body_cache, tcx), tcx ) { return source; @@ -519,7 +519,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( deref_base.base, deref_base.projection, - self.body_cache.body(), + &self.body_cache, tcx ).ty; if base_ty.is_unsafe_ptr() { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 1ff26acd361b5..a6fc3e0b21abe 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -646,7 +646,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx let tcx = self.infcx.tcx; // Compute the type with accurate region information. - let drop_place_ty = drop_place.ty(self.body_cache.body(), self.infcx.tcx); + let drop_place_ty = drop_place.ty(&self.body_cache, self.infcx.tcx); // Erase the regions. let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; @@ -990,7 +990,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut error_reported = false; let tcx = self.infcx.tcx; - let body = self.body_cache.body(); + let body_cache = self.body_cache; + let body: &Body<'_> = &body_cache; let param_env = self.param_env; let location_table = self.location_table.start_index(location); let borrow_set = self.borrow_set.clone(); @@ -1341,7 +1342,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => bug!("temporary initialized in arguments"), }; - let bbd = &self.body_cache.body()[loc.block]; + let body_cache = self.body_cache; + let bbd = &body_cache[loc.block]; let stmt = &bbd.statements[loc.statement_index]; debug!("temporary assigned in: stmt={:?}", stmt); diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 5907da09c671a..f5ef37bb0f4e8 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. - let ty = deref_target_place.ty(self.body_cache.body(), self.infcx.tcx).ty; + let ty = deref_target_place.ty(&self.body_cache, self.infcx.tcx).ty; let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); @@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let move_ty = format!( "{:?}", - move_place.ty(self.body_cache.body(), self.infcx.tcx).ty, + move_place.ty(&self.body_cache, self.infcx.tcx).ty, ); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { let is_option = move_ty.starts_with("std::option::Option"); @@ -454,7 +454,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.is_empty() { - let place_ty = move_from.ty(self.body_cache.body(), self.infcx.tcx).ty; + let place_ty = move_from.ty(&self.body_cache, self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -482,7 +482,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // No binding. Nothing to suggest. GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => { let span = use_spans.var_or_use(); - let place_ty = original_path.ty(self.body_cache.body(), self.infcx.tcx).ty; + let place_ty = original_path.ty(&self.body_cache, self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 0ec72150d97b3..bae5d2e174258 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Place::ty_from( &the_place_err.base, proj_base, - self.body_cache.body(), + &self.body_cache, self.infcx.tcx ).ty)); @@ -115,7 +115,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Place::ty_from( the_place_err.base, the_place_err.projection, - self.body_cache.body(), + &self.body_cache, self.infcx.tcx ) .ty @@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(base, proj_base, self.body_cache.body(), self.infcx.tcx).ty, + Place::ty_from(base, proj_base, &self.body_cache, self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -304,7 +304,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(base, proj_base, self.body_cache.body(), self.infcx.tcx).ty + Place::ty_from(base, proj_base, &self.body_cache, self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 4097bfeeb3599..1e07f354b83f7 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -237,7 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let regioncx = &self.nonlexical_regioncx; - let body = self.body_cache.body(); + let body: &Body<'_> = &self.body_cache; let tcx = self.infcx.tcx; let borrow_region_vid = borrow.region; diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 8d5466e545d52..a2929fe474762 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -38,7 +38,7 @@ pub(super) fn generate_invalidates<'tcx>( param_env, tcx, location_table, - body: body_cache.body(), + body: &body_cache, dominators, }; ig.visit_body(body_cache); diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 519b59304b768..ff28a27911b69 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -181,7 +181,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(body_cache.body())); + let elements + = &Rc::new(RegionValueElements::new(&body_cache)); // Run the MIR type-checker. let MirTypeckResults { @@ -206,7 +207,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); - populate_polonius_move_facts(all_facts, move_data, location_table, body_cache.body()); + populate_polonius_move_facts(all_facts, move_data, location_table, &body_cache); } // Create the region inference context, taking ownership of the @@ -230,7 +231,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( &mut liveness_constraints, &mut all_facts, location_table, - body_cache.body(), + &body_cache, borrow_set, ); @@ -239,7 +240,6 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( universal_regions, placeholder_indices, universal_region_relations, - body_cache.body(), outlives_constraints, member_constraints, closure_bounds_mapping, @@ -284,14 +284,14 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let closure_region_requirements = - regioncx.solve(infcx, body_cache.body(), local_names, upvars, def_id, errors_buffer); + regioncx.solve(infcx, &body_cache, local_names, upvars, def_id, errors_buffer); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, MirSource::item(def_id), - body_cache.body(), + &body_cache, ®ioncx, &closure_region_requirements, ); @@ -300,7 +300,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // information dump_annotation( infcx, - body_cache.body(), + &body_cache, def_id, ®ioncx, &closure_region_requirements, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index d44e85fa7900d..bd9e97e5b633b 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -239,7 +239,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { universal_regions: Rc>, placeholder_indices: Rc, universal_region_relations: Rc>, - _body: &Body<'tcx>, outlives_constraints: OutlivesConstraintSet, member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, closure_bounds_mapping: FxHashMap< diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 7200f8d8ae595..5190e0f939f34 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -169,7 +169,7 @@ pub(crate) fn type_check<'tcx>( &universal_region_relations, |mut cx| { cx.equate_inputs_and_outputs( - body_cache.body(), + &body_cache, universal_regions, &normalized_inputs_and_output); liveness::generate( @@ -201,7 +201,7 @@ fn type_check_internal<'a, 'tcx, R>( borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, universal_region_relations: &'a UniversalRegionRelations<'tcx>, mut extra: impl FnMut(&mut TypeChecker<'a, 'tcx>) -> R, -) -> R where { +) -> R { let mut checker = TypeChecker::new( infcx, body_cache.body(), @@ -220,7 +220,7 @@ fn type_check_internal<'a, 'tcx, R>( if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(body_cache.body()); + checker.typeck_mir(&body_cache); } extra(&mut checker) diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index ccd6d285a7bc7..82763df749240 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -11,7 +11,7 @@ use super::MirBorrowckCtxt; use rustc::hir; use rustc::ty::{self, TyCtxt}; -use rustc::mir::{Body, Place, PlaceBase, PlaceRef, ProjectionElem}; +use rustc::mir::{Place, PlaceBase, PlaceRef, ProjectionElem, ReadOnlyBodyCache}; pub trait IsPrefixOf<'cx, 'tcx> { fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool; @@ -26,7 +26,7 @@ impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> { } pub(super) struct Prefixes<'cx, 'tcx> { - body: &'cx Body<'tcx>, + body_cache: ReadOnlyBodyCache<'cx, 'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, next: Option>, @@ -56,7 +56,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, - body: self.body_cache.body(), + body_cache: self.body_cache, tcx: self.infcx.tcx, } } @@ -143,7 +143,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // derefs, except we stop at the deref of a shared // reference. - let ty = Place::ty_from(cursor.base, proj_base, self.body, self.tcx).ty; + let ty = Place::ty_from(cursor.base, proj_base, &self.body_cache, self.tcx).ty; match ty.kind { ty::RawPtr(_) | ty::Ref( diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index ecfbe529b9566..67de4ce168c02 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1249,11 +1249,10 @@ fn collect_neighbours<'tcx>( ) { debug!("collect_neighbours: {:?}", instance.def_id()); let body_cache = tcx.instance_mir(instance.def); - let body = body_cache.body(); MirNeighborCollector { tcx, - body: &body, + body: &body_cache, output, param_substs: instance.substs, }.visit_body(body_cache); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 9b54c66e1e572..43600d6a5d8ee 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -113,7 +113,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx bug!("creating shims from intrinsics ({:?}) is unsupported", instance) } }; - debug!("make_shim({:?}) = untransformed {:?}", instance, result.body()); + debug!("make_shim({:?}) = untransformed {:?}", instance, result); run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, @@ -123,7 +123,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx &add_call_guards::CriticalCallEdges, ]); - debug!("make_shim({:?}) = {:?}", instance, result.body()); + debug!("make_shim({:?}) = {:?}", instance, result); result.ensure_predecessors(); tcx.arena.alloc(result) @@ -220,8 +220,8 @@ fn build_drop_shim<'tcx>( let patch = { let param_env = tcx.param_env(def_id).with_reveal_all(); let mut elaborator = DropShimElaborator { - body: body_cache.body(), - patch: MirPatch::new(body_cache.body()), + body: &body_cache, + patch: MirPatch::new(&body_cache), tcx, param_env }; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d2d4eef1164e4..9e314dbc6e893 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -529,7 +529,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult }; let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body_cache, tcx, param_env); let mut cache = body_cache.cache().clone(); - let read_only_cache = ReadOnlyBodyCache::from_external_cache(&mut cache, body_cache.body()); + let read_only_cache = ReadOnlyBodyCache::from_external_cache(&mut cache, body_cache); checker.visit_body(read_only_cache); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index c79178dcac78f..f9b8b3d6aec52 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -487,7 +487,7 @@ fn locals_live_across_suspend_points( ) -> LivenessInfo { let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); let def_id = source.def_id(); - let body = body_cache.body(); + let body: &Body<'_> = &body_cache; // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. @@ -932,7 +932,7 @@ fn create_generator_drop_shim<'tcx>( ) -> BodyCache<'tcx> { let mut body_cache = body_cache.clone(); - let source_info = source_info(body_cache.body()); + let source_info = source_info(&body_cache); let mut cases = create_cases(&mut body_cache, transform, |point| point.drop); diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 6721982e8469e..922b0937065c4 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -448,7 +448,7 @@ impl Inliner<'tcx> { BorrowKind::Mut { allow_two_phase_borrow: false }, destination.0); - let ty = dest.ty(caller_body.body(), self.tcx); + let ty = dest.ty(caller_body, self.tcx); let temp = LocalDecl::new_temp(ty, callsite.location.span); @@ -553,7 +553,7 @@ impl Inliner<'tcx> { assert!(args.next().is_none()); let tuple = Place::from(tuple); - let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body_cache.body(), tcx).ty.kind { + let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body_cache, tcx).ty.kind { s } else { bug!("Closure arguments are not passed as a tuple"); @@ -608,7 +608,7 @@ impl Inliner<'tcx> { // Otherwise, create a temporary for the arg let arg = Rvalue::Use(arg); - let ty = arg.ty(caller_body_cache.body(), self.tcx); + let ty = arg.ty(caller_body_cache, self.tcx); let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span); let arg_tmp = caller_body_cache.local_decls.push(arg_tmp); diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 3a7d7d17f0693..386e04bc0839a 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -13,7 +13,7 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCa if tcx.sess.no_landing_pads() { return } - debug!("remove_noop_landing_pads({:?})", body_cache.body()); + debug!("remove_noop_landing_pads({:?})", body_cache); RemoveNoopLandingPads.remove_nop_landing_pads(body_cache) } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 6e877d2fb74e0..de8a8ceed311a 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -58,15 +58,15 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { |_, i| DebugFormatted::new(&i)); if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() { - sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_inits); + sanity_check_via_rustc_peek(tcx, body_cache, def_id, &attributes, &flow_inits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_uninit).is_some() { - sanity_check_via_rustc_peek(tcx, body_cache.body(), def_id, &attributes, &flow_uninits); + sanity_check_via_rustc_peek(tcx, body_cache, def_id, &attributes, &flow_uninits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { sanity_check_via_rustc_peek( tcx, - body_cache.body(), + body_cache, def_id, &attributes, &flow_def_inits); @@ -74,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() { sanity_check_via_rustc_peek( tcx, - body_cache.body(), + body_cache, def_id, &attributes, &flow_indirectly_mut); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 949059f19aeda..3057d67f9ef57 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { fn run_pass( &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> ) { - debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body_cache.body()); + debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body_cache); simplify_cfg(body_cache); } } @@ -264,7 +264,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pub fn remove_dead_blocks(body_cache: &mut BodyCache<'_>) { let mut seen = BitSet::new_empty(body_cache.basic_blocks().len()); - for (bb, _) in traversal::preorder(body_cache.body()) { + for (bb, _) in traversal::preorder(body_cache) { seen.insert(bb.index()); } diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 62a2f269facc1..d4d24347f726c 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -223,7 +223,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { let src_ty = Place::ty_from( src_place.base, src_place.projection, - body_cache.body(), + body_cache, tcx ).ty; if let ty::Array(_, ref size_o) = src_ty.kind { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 1773dbd2e34a1..56a31337a0860 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -85,7 +85,7 @@ pub fn liveness_of_locals( // any benefits. Benchmark this and find out. let mut dirty_queue: WorkQueue = WorkQueue::with_none(body_cache.basic_blocks().len()); - for (bb, _) in traversal::postorder(body_cache.body()) { + for (bb, _) in traversal::postorder(&body_cache) { dirty_queue.insert(bb); } From b2fe254c989b053c4320c023b101b8736a50866c Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 6 Nov 2019 12:00:46 -0500 Subject: [PATCH 35/47] Remove HasLocalDecls impl from BodyCache's, properly reborrow to Body, rename all body_cache back to body --- src/librustc/mir/cache.rs | 20 +- src/librustc/mir/mod.rs | 6 +- src/librustc/mir/visit.rs | 20 +- src/librustc/query/mod.rs | 4 +- src/librustc/ty/context.rs | 4 +- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 4 +- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +- src/librustc_metadata/rmeta/decoder.rs | 4 +- src/librustc_mir/borrow_check/borrow_set.rs | 14 +- .../borrow_check/conflict_errors.rs | 56 ++--- .../borrow_check/error_reporting.rs | 32 +-- src/librustc_mir/borrow_check/mod.rs | 80 +++---- src/librustc_mir/borrow_check/move_errors.rs | 20 +- .../borrow_check/mutability_errors.rs | 32 +-- .../borrow_check/nll/explain_borrow/mod.rs | 16 +- .../borrow_check/nll/invalidation.rs | 8 +- src/librustc_mir/borrow_check/nll/mod.rs | 28 +-- .../borrow_check/nll/region_infer/values.rs | 6 +- src/librustc_mir/borrow_check/nll/renumber.rs | 6 +- .../nll/type_check/liveness/local_use_map.rs | 8 +- .../nll/type_check/liveness/mod.rs | 8 +- .../nll/type_check/liveness/polonius.rs | 6 +- .../nll/type_check/liveness/trace.rs | 28 +-- .../borrow_check/nll/type_check/mod.rs | 50 ++-- src/librustc_mir/borrow_check/prefixes.rs | 6 +- src/librustc_mir/borrow_check/used_muts.rs | 2 +- src/librustc_mir/const_eval.rs | 4 +- src/librustc_mir/dataflow/impls/borrows.rs | 4 +- src/librustc_mir/dataflow/impls/mod.rs | 8 +- .../dataflow/impls/storage_liveness.rs | 22 +- src/librustc_mir/monomorphize/collector.rs | 6 +- src/librustc_mir/shim.rs | 18 +- src/librustc_mir/transform/add_call_guards.rs | 15 +- .../transform/add_moves_for_packed_drops.rs | 12 +- src/librustc_mir/transform/add_retag.rs | 6 +- src/librustc_mir/transform/check_unsafety.rs | 8 +- .../transform/cleanup_post_borrowck.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 34 +-- src/librustc_mir/transform/copy_prop.rs | 36 +-- src/librustc_mir/transform/deaggregator.rs | 4 +- src/librustc_mir/transform/dump_mir.rs | 2 +- src/librustc_mir/transform/elaborate_drops.rs | 10 +- src/librustc_mir/transform/erase_regions.rs | 4 +- src/librustc_mir/transform/generator.rs | 225 +++++++++--------- src/librustc_mir/transform/inline.rs | 62 ++--- src/librustc_mir/transform/instcombine.rs | 8 +- src/librustc_mir/transform/mod.rs | 30 +-- src/librustc_mir/transform/no_landing_pads.rs | 8 +- src/librustc_mir/transform/promote_consts.rs | 62 ++--- .../transform/remove_noop_landing_pads.rs | 26 +- src/librustc_mir/transform/rustc_peek.rs | 30 +-- src/librustc_mir/transform/simplify.rs | 46 ++-- .../transform/simplify_branches.rs | 4 +- .../transform/uniform_array_move_out.rs | 26 +- src/librustc_mir/util/def_use.rs | 12 +- src/librustc_mir/util/liveness.rs | 16 +- src/librustc_mir/util/patch.rs | 18 +- 59 files changed, 618 insertions(+), 630 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index e7ca7d6a95f5f..09c18d714f2c7 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -2,7 +2,7 @@ use rustc_index::vec::IndexVec; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use crate::ich::StableHashingContext; -use crate::mir::{BasicBlock, BasicBlockData, Body, HasLocalDecls, LocalDecls, Location, Successors}; +use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use std::iter; @@ -160,10 +160,10 @@ impl BodyCache<'tcx> { #[macro_export] macro_rules! read_only { - ($body_cache:expr) => { + ($body:expr) => { { - $body_cache.ensure_predecessors(); - $body_cache.unwrap_read_only() + $body.ensure_predecessors(); + $body.unwrap_read_only() } }; } @@ -223,12 +223,6 @@ impl<'tcx> DerefMut for BodyCache<'tcx> { } } -impl<'tcx> HasLocalDecls<'tcx> for BodyCache<'tcx> { - fn local_decls(&self) -> &LocalDecls<'tcx> { - &self.body.local_decls - } -} - #[derive(Copy, Clone, Debug)] pub struct ReadOnlyBodyCache<'a, 'tcx> { cache: &'a Cache, @@ -347,12 +341,6 @@ impl Index for ReadOnlyBodyCache<'a, 'tcx> { } } -impl<'a, 'tcx> HasLocalDecls<'tcx> for ReadOnlyBodyCache<'a, 'tcx> { - fn local_decls(&self) -> &LocalDecls<'tcx> { - &self.body.local_decls - } -} - CloneTypeFoldableAndLiftImpls! { Cache, } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1b1c7573484f9..ea858c80db79b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2602,7 +2602,7 @@ impl Location { pub fn is_predecessor_of<'tcx>( &self, other: Location, - body_cache: ReadOnlyBodyCache<'_, 'tcx> + body: ReadOnlyBodyCache<'_, 'tcx> ) -> bool { // If we are in the same block as the other location and are an earlier statement // then we are a predecessor of `other`. @@ -2611,13 +2611,13 @@ impl Location { } // If we're in another block, then we want to check that block is a predecessor of `other`. - let mut queue: Vec = body_cache.predecessors_for(other.block).to_vec(); + let mut queue: Vec = body.predecessors_for(other.block).to_vec(); let mut visited = FxHashSet::default(); while let Some(block) = queue.pop() { // If we haven't visited this block before, then make sure we visit it's predecessors. if visited.insert(block) { - queue.extend(body_cache.predecessors_for(block).iter().cloned()); + queue.extend(body.predecessors_for(block).iter().cloned()); } else { continue; } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 18776778ebb91..47a1d67d5d6db 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -82,9 +82,9 @@ macro_rules! make_mir_visitor { fn visit_body( &mut self, - body_cache: body_cache_type!($($mutability)? '_, 'tcx) + body: body_cache_type!($($mutability)? '_, 'tcx) ) { - self.super_body(body_cache); + self.super_body(body); } fn visit_basic_block_data(&mut self, @@ -254,10 +254,10 @@ macro_rules! make_mir_visitor { fn super_body( &mut self, - $($mutability)? body_cache: body_cache_type!($($mutability)? '_, 'tcx) + $($mutability)? body: body_cache_type!($($mutability)? '_, 'tcx) ) { - let span = body_cache.span; - if let Some(yield_ty) = &$($mutability)? body_cache.yield_ty { + let span = body.span; + if let Some(yield_ty) = &$($mutability)? body.yield_ty { self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE, @@ -268,14 +268,14 @@ macro_rules! make_mir_visitor { // than a for-loop, to avoid calling `body::Body::invalidate` for // each basic block. macro_rules! basic_blocks { - (mut) => (body_cache.basic_blocks_mut().iter_enumerated_mut()); - () => (body_cache.basic_blocks().iter_enumerated()); + (mut) => (body.basic_blocks_mut().iter_enumerated_mut()); + () => (body.basic_blocks().iter_enumerated()); }; for (bb, data) in basic_blocks!($($mutability)?) { self.visit_basic_block_data(bb, data); } - let body: & $($mutability)? Body<'_> = & $($mutability)? body_cache; + let body: & $($mutability)? Body<'_> = & $($mutability)? body; for scope in &$($mutability)? body.source_scopes { self.visit_source_scope_data(scope); } @@ -808,10 +808,10 @@ macro_rules! make_mir_visitor { fn visit_location( &mut self, - body_cache: body_cache_type!($($mutability)? '_, 'tcx), + body: body_cache_type!($($mutability)? '_, 'tcx), location: Location ) { - let basic_block = & $($mutability)? body_cache[location.block]; + let basic_block = & $($mutability)? body[location.block]; if basic_block.statements.len() == location.statement_index { if let Some(ref $($mutability)? terminator) = basic_block.terminator { self.visit_terminator(terminator, location) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2bf7caceb68e6..a6d7e5c9291dc 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -149,8 +149,8 @@ rustc_queries! { >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); promoted.map(|p| { let cache = tcx.arena.alloc(p); - for body_cache in cache.iter_mut() { - body_cache.ensure_predecessors(); + for body in cache.iter_mut() { + body.ensure_predecessors(); } &*cache }) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 07d86a5f86a4f..6a0002cd80fd0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1083,8 +1083,8 @@ impl<'tcx> TyCtxt<'tcx> { &self.hir_map } - pub fn alloc_steal_mir(self, mir_cache: BodyCache<'tcx>) -> &'tcx Steal> { - self.arena.alloc(Steal::new(mir_cache)) + pub fn alloc_steal_mir(self, mir: BodyCache<'tcx>) -> &'tcx Steal> { + self.arena.alloc(Steal::new(mir)) } pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 782c0f7e13903..f15456e0ff841 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -131,7 +131,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, &self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, &*self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 0920de7d903f2..ce59bf1d61d8b 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -324,7 +324,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(&self.mir, bx.tcx()).ty; + let ty = location.ty(&*self.mir, bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); @@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(&self.mir, bx.tcx()); + let op_ty = op_arg.ty(&*self.mir, bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5ea08edd035be..9dd4d0ec22f23 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -594,7 +594,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let place_ty = mir::Place::ty_from( place_ref.base, place_ref.projection, - &self.mir, + &*self.mir, tcx, ); self.monomorphize(&place_ty.ty) diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index fa157a0c35f90..3bae027e7634d 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(&self.mir, bx.tcx()); + let discr_ty = rvalue.ty(&*self.mir, bx.tcx()); let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { @@ -513,7 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(&self.mir, self.cx.tcx()); + let ty = rvalue.ty(&*self.mir, self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -710,7 +710,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(&self.mir, self.cx.tcx()); + let ty = rvalue.ty(&*self.mir, self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index c163ff85563bd..42db642cd4ddb 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1101,8 +1101,8 @@ impl<'a, 'tcx> CrateMetadata { bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) .decode((self, tcx)); - for body_cache in cache.iter_mut() { - body_cache.ensure_predecessors(); + for body in cache.iter_mut() { + body.ensure_predecessors(); } cache } diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index aaf067a53610e..802464ce86b86 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -90,7 +90,7 @@ crate enum LocalsStateAtExit { impl LocalsStateAtExit { fn build( locals_are_invalidated_at_exit: bool, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, move_data: &MoveData<'tcx> ) -> Self { struct HasStorageDead(BitSet); @@ -107,8 +107,8 @@ impl LocalsStateAtExit { LocalsStateAtExit::AllAreInvalidated } else { let mut has_storage_dead - = HasStorageDead(BitSet::new_empty(body_cache.local_decls.len())); - has_storage_dead.visit_body(body_cache); + = HasStorageDead(BitSet::new_empty(body.local_decls.len())); + has_storage_dead.visit_body(body); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { if let Some(index) = move_data.base_local(move_out.path) { @@ -124,23 +124,23 @@ impl LocalsStateAtExit { impl<'tcx> BorrowSet<'tcx> { pub fn build( tcx: TyCtxt<'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, locals_are_invalidated_at_exit: bool, move_data: &MoveData<'tcx>, ) -> Self { let mut visitor = GatherBorrows { tcx, - body: &body_cache, + body: &body, idx_vec: IndexVec::new(), location_map: Default::default(), activation_map: Default::default(), local_map: Default::default(), pending_activations: Default::default(), locals_state_at_exit: - LocalsStateAtExit::build(locals_are_invalidated_at_exit, body_cache, move_data), + LocalsStateAtExit::build(locals_are_invalidated_at_exit, body, move_data), }; - for (block, block_data) in traversal::preorder(&body_cache) { + for (block, block_data) in traversal::preorder(&body) { visitor.visit_basic_block_data(block, block_data); } diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 9dac6d70dff85..2170bd7e7a44c 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -208,7 +208,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from( used_place.base, used_place.projection, - &self.body_cache, + &*self.body, self.infcx.tcx ).ty; let needs_note = match ty.kind { @@ -225,7 +225,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mpi = self.move_data.moves[move_out_indices[0]].path; let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(&self.body_cache, self.infcx.tcx).ty; + let ty = place.ty(&*self.body, self.infcx.tcx).ty; let opt_name = self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); let note_msg = match opt_name { @@ -247,7 +247,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } let span = if let Some(local) = place.as_local() { - let decl = &self.body_cache.local_decls[local]; + let decl = &self.body.local_decls[local]; Some(decl.source_info.span) } else { None @@ -317,7 +317,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ).add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, "", @@ -359,7 +359,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, "", @@ -581,7 +581,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, first_borrow_desc, @@ -625,7 +625,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from( place_base, place_projection, - &self.body_cache, + &*self.body, self.infcx.tcx ).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) @@ -746,7 +746,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assert!(root_place.projection.is_empty()); let proper_span = match root_place.base { - PlaceBase::Local(local) => self.body_cache.local_decls[*local].source_info.span, + PlaceBase::Local(local) => self.body.local_decls[*local].source_info.span, _ => drop_span, }; @@ -973,7 +973,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, "", @@ -999,7 +999,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); explanation.add_explanation_to_diagnostic( - self.infcx.tcx, &self.body_cache, &self.local_names, &mut err, "", None); + self.infcx.tcx, &self.body, &self.local_names, &mut err, "", None); } err @@ -1059,7 +1059,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, "", @@ -1146,7 +1146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, "", @@ -1183,7 +1183,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME use a better heuristic than Spans let reference_desc - = if return_span == self.body_cache.source_info(borrow.reserve_location).span { + = if return_span == self.body.source_info(borrow.reserve_location).span { "reference to" } else { "value referencing" @@ -1191,7 +1191,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let (place_desc, note) = if let Some(place_desc) = opt_place_desc { let local_kind = if let Some(local) = borrow.borrowed_place.as_local() { - match self.body_cache.local_kind(local) { + match self.body.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Temp => bug!("temporary or return pointer with a name"), LocalKind::Var => "local variable ", @@ -1224,7 +1224,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { bug!("try_report_cannot_return_reference_to_local: not a local") }; - match self.body_cache.local_kind(*local) { + match self.body.local_kind(*local) { LocalKind::ReturnPointer | LocalKind::Temp => ( "temporary value".to_string(), "temporary value created here".to_string(), @@ -1382,7 +1382,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec { let mut stack = Vec::new(); - stack.extend(self.body_cache.predecessor_locations(location).map(|predecessor| { + stack.extend(self.body.predecessor_locations(location).map(|predecessor| { let is_back_edge = location.dominates(predecessor, &self.dominators); (predecessor, is_back_edge) })); @@ -1401,7 +1401,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // check for moves - let stmt_kind = self.body_cache[location.block] + let stmt_kind = self.body[location.block] .statements .get(location.statement_index) .map(|s| &s.kind); @@ -1456,7 +1456,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut any_match = false; drop_flag_effects::for_location_inits( self.infcx.tcx, - &self.body_cache, + &self.body, self.move_data, location, |m| { @@ -1469,7 +1469,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { continue 'dfs; } - stack.extend(self.body_cache.predecessor_locations(location).map(|predecessor| { + stack.extend(self.body.predecessor_locations(location).map(|predecessor| { let back_edge = location.dominates(predecessor, &self.dominators); (predecessor, is_back_edge || back_edge) })); @@ -1521,7 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, loan, None) .add_explanation_to_diagnostic( self.infcx.tcx, - &self.body_cache, + &self.body, &self.local_names, &mut err, "", @@ -1546,8 +1546,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { let (from_arg, local_decl, local_name) = match err_place.as_local() { Some(local) => ( - self.body_cache.local_kind(local) == LocalKind::Arg, - Some(&self.body_cache.local_decls[local]), + self.body.local_kind(local) == LocalKind::Arg, + Some(&self.body.local_decls[local]), self.local_names[local], ), None => (false, None, None), @@ -1635,7 +1635,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Place::ty_from( &place.base, proj_base, - &self.body_cache, + &*self.body, tcx ).ty.is_box(), "Drop of value behind a reference or raw pointer" @@ -1648,7 +1648,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( &place.base, proj_base, - &self.body_cache, + &*self.body, tcx ).ty; match base_ty.kind { @@ -1738,7 +1738,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location ); if let Some(&Statement { kind: StatementKind::Assign(box(ref reservation, _)), ..}) - = &self.body_cache[location.block].statements.get(location.statement_index) + = &self.body[location.block].statements.get(location.statement_index) { debug!( "annotate_argument_and_return_for_borrow: reservation={:?}", @@ -1746,14 +1746,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Check that the initial assignment of the reserve location is into a temporary. let mut target = match reservation.as_local() { - Some(local) if self.body_cache.local_kind(local) == LocalKind::Temp => local, + Some(local) if self.body.local_kind(local) == LocalKind::Temp => local, _ => return None, }; // Next, look through the rest of the block, checking if we are assigning the // `target` (that is, the place that contains our borrow) to anything. let mut annotated_closure = None; - for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] + for stmt in &self.body[location.block].statements[location.statement_index + 1..] { debug!( "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", @@ -1879,7 +1879,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Check the terminator if we didn't find anything in the statements. - let terminator = &self.body_cache[location.block].terminator(); + let terminator = &self.body[location.block].terminator(); debug!( "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", target, terminator diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 3515c4bfe09d1..cc15d236b2325 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -39,7 +39,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); - for stmt in &self.body_cache[location.block].statements[location.statement_index..] { + for stmt in &self.body[location.block].statements[location.statement_index..] { debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); if let StatementKind::Assign(box(into, Rvalue::Use(from))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); @@ -53,7 +53,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Check if we are attempting to call a closure after it has been invoked. - let terminator = self.body_cache[location.block].terminator(); + let terminator = self.body[location.block].terminator(); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); if let TerminatorKind::Call { func: Operand::Constant(box Constant { @@ -76,7 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); - if let ty::Closure(did, _) = self.body_cache.local_decls[closure].ty.kind { + if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -99,7 +99,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if we are just moving a closure after it has been invoked. if let Some(target) = target { - if let ty::Closure(did, _) = self.body_cache.local_decls[target].ty.kind { + if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -332,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have /// a name, or its name was generated by the compiler, then `Err` is returned fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> { - let decl = &self.body_cache.local_decls[local]; + let decl = &self.body.local_decls[local]; match self.local_names[local] { Some(name) if !decl.from_compiler_desugaring() => { buf.push_str(&name.as_str()); @@ -350,7 +350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { base: PlaceBase::Local(local), projection: [], } => { - let local = &self.body_cache.local_decls[*local]; + let local = &self.body.local_decls[*local]; self.describe_field_from_ty(&local.ty, field, None) } PlaceRef { @@ -372,7 +372,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( place.base, place.projection, - &self.body_cache, + &*self.body, self.infcx.tcx).ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } @@ -484,7 +484,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => continue, }; - let bbd = &self.body_cache[loc.block]; + let bbd = &self.body[loc.block]; let is_terminator = bbd.statements.len() == loc.statement_index; debug!( "borrowed_content_source: loc={:?} is_terminator={:?}", @@ -502,7 +502,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }) = bbd.terminator { if let Some(source) = BorrowedContentSource::from_call( - func.ty(&self.body_cache, tcx), + func.ty(&*self.body, tcx), tcx ) { return source; @@ -519,7 +519,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( deref_base.base, deref_base.projection, - &self.body_cache, + &*self.body, tcx ).ty; if base_ty.is_unsafe_ptr() { @@ -776,9 +776,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> UseSpans { use self::UseSpans::*; - let stmt = match self.body_cache[location.block].statements.get(location.statement_index) { + let stmt = match self.body[location.block].statements.get(location.statement_index) { Some(stmt) => stmt, - None => return OtherUse(self.body_cache.source_info(location).span), + None => return OtherUse(self.body.source_info(location).span), }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); @@ -816,7 +816,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use self::UseSpans::*; debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); - let target = match self.body_cache[location.block] + let target = match self.body[location.block] .statements .get(location.statement_index) { @@ -833,12 +833,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => return OtherUse(use_span), }; - if self.body_cache.local_kind(target) != LocalKind::Temp { + if self.body.local_kind(target) != LocalKind::Temp { // operands are always temporaries. return OtherUse(use_span); } - for stmt in &self.body_cache[location.block].statements[location.statement_index + 1..] { + for stmt in &self.body[location.block].statements[location.statement_index + 1..] { if let StatementKind::Assign( box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { @@ -910,7 +910,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Helper to retrieve span(s) of given borrow from the current MIR /// representation pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans { - let span = self.body_cache.source_info(borrow.reserve_location).span; + let span = self.body.source_info(borrow.reserve_location).span; self.borrow_spans(span, borrow.reserve_location) } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a6fc3e0b21abe..da08de7690ab2 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -162,22 +162,22 @@ fn do_mir_borrowck<'a, 'tcx>( // requires first making our own copy of the MIR. This copy will // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. - let body: Body<'tcx> = input_body.clone(); + let body_clone: Body<'tcx> = input_body.clone(); let mut promoted = input_promoted.clone(); - let mut body_cache = BodyCache::new(body); + let mut body = BodyCache::new(body_clone); let free_regions = - nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body_cache, &mut promoted); - let body_cache = read_only!(body_cache); // no further changes + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); + let body = read_only!(body); // no further changes let promoted: IndexVec<_, _> = promoted .iter_mut() - .map(|body_cache| read_only!(body_cache)) + .map(|body| read_only!(body)) .collect(); - let location_table = &LocationTable::new(&body_cache); + let location_table = &LocationTable::new(&body); let mut errors_buffer = Vec::new(); let (move_data, move_errors): (MoveData<'tcx>, Option, MoveError<'tcx>)>>) = - match MoveData::gather_moves(&body_cache, tcx) { + match MoveData::gather_moves(&body, tcx) { Ok(move_data) => (move_data, None), Err((move_data, move_errors)) => (move_data, Some(move_errors)), }; @@ -187,27 +187,27 @@ fn do_mir_borrowck<'a, 'tcx>( param_env, }; - let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, - &body_cache, + &body, def_id, &attributes, &dead_unwinds, - MaybeInitializedPlaces::new(tcx, &body_cache, &mdpe), + MaybeInitializedPlaces::new(tcx, &body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build( - tcx, body_cache, locals_are_invalidated_at_exit, &mdpe.move_data)); + tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( infcx, def_id, free_regions, - body_cache, + body, &promoted, &local_names, &upvars, @@ -228,29 +228,29 @@ fn do_mir_borrowck<'a, 'tcx>( let flow_borrows = FlowAtLocation::new(do_dataflow( tcx, - &body_cache, + &body, def_id, &attributes, &dead_unwinds, - Borrows::new(tcx, &body_cache, param_env, regioncx.clone(), &borrow_set), + Borrows::new(tcx, &body, param_env, regioncx.clone(), &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); let flow_uninits = FlowAtLocation::new(do_dataflow( tcx, - &body_cache, + &body, def_id, &attributes, &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, &body_cache, &mdpe), + MaybeUninitializedPlaces::new(tcx, &body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, - &body_cache, + &body, def_id, &attributes, &dead_unwinds, - EverInitializedPlaces::new(tcx, &body_cache, &mdpe), + EverInitializedPlaces::new(tcx, &body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); @@ -262,11 +262,11 @@ fn do_mir_borrowck<'a, 'tcx>( _ => true, }; - let dominators = body_cache.dominators(); + let dominators = body.dominators(); let mut mbcx = MirBorrowckCtxt { infcx, - body_cache, + body, mir_def_id: def_id, param_env, move_data: &mdpe.move_data, @@ -306,8 +306,8 @@ fn do_mir_borrowck<'a, 'tcx>( let mut initial_diag = mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow); - let scope = mbcx.body_cache.source_info(location).scope; - let lint_root = match &mbcx.body_cache.source_scopes[scope].local_data { + let scope = mbcx.body.source_info(location).scope; + let lint_root = match &mbcx.body.source_scopes[scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => id, }; @@ -329,22 +329,22 @@ fn do_mir_borrowck<'a, 'tcx>( // would have a chance of erroneously adding non-user-defined mutable vars // to the set. let temporary_used_locals: FxHashSet = mbcx.used_mut.iter() - .filter(|&local| !mbcx.body_cache.local_decls[*local].is_user_variable()) + .filter(|&local| !mbcx.body.local_decls[*local].is_user_variable()) .cloned() .collect(); // For the remaining unused locals that are marked as mutable, we avoid linting any that // were never initialized. These locals may have been removed as unreachable code; or will be // linted as unused variables. - let unused_mut_locals = mbcx.body_cache.mut_vars_iter() + let unused_mut_locals = mbcx.body.mut_vars_iter() .filter(|local| !mbcx.used_mut.contains(local)) .collect(); mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); let used_mut = mbcx.used_mut; - for local in mbcx.body_cache.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) + for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) { - let local_decl = &mbcx.body_cache.local_decls[local]; + let local_decl = &mbcx.body.local_decls[local]; let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data { ClearCrossCrate::Set(data) => data.lint_root, _ => continue, @@ -405,7 +405,7 @@ fn do_mir_borrowck<'a, 'tcx>( crate struct MirBorrowckCtxt<'cx, 'tcx> { crate infcx: &'cx InferCtxt<'cx, 'tcx>, - body_cache: ReadOnlyBodyCache<'cx, 'tcx>, + body: ReadOnlyBodyCache<'cx, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, move_data: &'cx MoveData<'tcx>, @@ -496,7 +496,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx type FlowState = Flows<'cx, 'tcx>; fn body(&self) -> &'cx Body<'tcx> { - self.body_cache.body() + self.body.body() } fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) { @@ -646,7 +646,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx let tcx = self.infcx.tcx; // Compute the type with accurate region information. - let drop_place_ty = drop_place.ty(&self.body_cache, self.infcx.tcx); + let drop_place_ty = drop_place.ty(&*self.body, self.infcx.tcx); // Erase the regions. let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; @@ -990,8 +990,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut error_reported = false; let tcx = self.infcx.tcx; - let body_cache = self.body_cache; - let body: &Body<'_> = &body_cache; + let body = self.body; + let body: &Body<'_> = &body; let param_env = self.param_env; let location_table = self.location_table.start_index(location); let borrow_set = self.borrow_set.clone(); @@ -1157,7 +1157,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // (e.g., `x = ...`) so long as it has never been initialized // before (at this point in the flow). if let Some(local) = place_span.0.as_local() { - if let Mutability::Not = self.body_cache.local_decls[local].mutability { + if let Mutability::Not = self.body.local_decls[local].mutability { // check for reassignments to immutable local variables self.check_if_reassignment_to_immutable_state( location, @@ -1310,8 +1310,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match *operand { Operand::Move(ref place) | Operand::Copy(ref place) => { match place.as_local() { - Some(local) if !self.body_cache.local_decls[local].is_user_variable() => { - if self.body_cache.local_decls[local].ty.is_mutable_ptr() { + Some(local) if !self.body.local_decls[local].is_user_variable() => { + if self.body.local_decls[local].ty.is_mutable_ptr() { // The variable will be marked as mutable by the borrow. return; } @@ -1342,8 +1342,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => bug!("temporary initialized in arguments"), }; - let body_cache = self.body_cache; - let bbd = &body_cache[loc.block]; + let body = self.body; + let bbd = &body[loc.block]; let stmt = &bbd.statements[loc.statement_index]; debug!("temporary assigned in: stmt={:?}", stmt); @@ -1462,7 +1462,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if places_conflict::borrow_conflicts_with_place( self.infcx.tcx, self.param_env, - &self.body_cache, + &self.body, place, borrow.kind, root_place, @@ -1542,7 +1542,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) { // And, if so, report an error. let init = &self.move_data.inits[init_index]; - let span = init.span(&self.body_cache); + let span = init.span(&self.body); self.report_illegal_reassignment( location, place_span, span, place_span.0 ); @@ -1865,7 +1865,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { this.move_data.moves[*moi].source.is_predecessor_of( - location, this.body_cache, + location, this.body, ) }) { return; @@ -2069,7 +2069,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { base: PlaceBase::Local(local), projection: [], } => { - let local = &self.body_cache.local_decls[*local]; + let local = &self.body.local_decls[*local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { LocalMutationIsAllowed::Yes => Ok(RootPlace { diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index f5ef37bb0f4e8..388a8abd5fc1f 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -90,13 +90,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // flow could be used. if let Some(StatementKind::Assign( box(place, Rvalue::Use(Operand::Move(move_from))) - )) = self.body_cache.basic_blocks()[location.block] + )) = self.body.basic_blocks()[location.block] .statements .get(location.statement_index) .map(|stmt| &stmt.kind) { if let Some(local) = place.as_local() { - let local_decl = &self.body_cache.local_decls[local]; + let local_decl = &self.body.local_decls[local]; // opt_match_place is the // match_span is the span of the expression being matched on // match *x.y { ... } match_place is Some(*x.y) @@ -112,7 +112,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { pat_span: _, }, ))) = local_decl.local_info { - let stmt_source_info = self.body_cache.source_info(location); + let stmt_source_info = self.body.source_info(location); self.append_binding_error( grouped_errors, kind, @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. - let ty = deref_target_place.ty(&self.body_cache, self.infcx.tcx).ty; + let ty = deref_target_place.ty(&*self.body, self.infcx.tcx).ty; let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); @@ -318,7 +318,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { base: PlaceBase::Local(local), projection: [], } = deref_base { - let decl = &self.body_cache.local_decls[*local]; + let decl = &self.body.local_decls[*local]; if decl.is_ref_for_guard() { let mut err = self.cannot_move_out_of( span, @@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let move_ty = format!( "{:?}", - move_place.ty(&self.body_cache, self.infcx.tcx).ty, + move_place.ty(&*self.body, self.infcx.tcx).ty, ); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { let is_option = move_ty.starts_with("std::option::Option"); @@ -454,7 +454,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.is_empty() { - let place_ty = move_from.ty(&self.body_cache, self.infcx.tcx).ty; + let place_ty = move_from.ty(&*self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -482,7 +482,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // No binding. Nothing to suggest. GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => { let span = use_spans.var_or_use(); - let place_ty = original_path.ty(&self.body_cache, self.infcx.tcx).ty; + let place_ty = original_path.ty(&*self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -510,7 +510,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ) { let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); for local in binds_to { - let bind_to = &self.body_cache.local_decls[*local]; + let bind_to = &self.body.local_decls[*local]; if let LocalInfo::User( ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { pat_span, @@ -559,7 +559,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { binds_to: &[Local], ) { for (j, local) in binds_to.into_iter().enumerate() { - let bind_to = &self.body_cache.local_decls[*local]; + let bind_to = &self.body.local_decls[*local]; let binding_span = bind_to.source_info.span; if j == 0 { diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index bae5d2e174258..348c788eb33ae 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Place::ty_from( &the_place_err.base, proj_base, - &self.body_cache, + &*self.body, self.infcx.tcx ).ty)); @@ -110,12 +110,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { proj_base.is_empty() && !self.upvars.is_empty() { item_msg = format!("`{}`", access_place_desc.unwrap()); - debug_assert!(self.body_cache.local_decls[Local::new(1)].ty.is_region_ptr()); + debug_assert!(self.body.local_decls[Local::new(1)].ty.is_region_ptr()); debug_assert!(is_closure_or_generator( Place::ty_from( the_place_err.base, the_place_err.projection, - &self.body_cache, + &*self.body, self.infcx.tcx ) .ty @@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(base, proj_base, &self.body_cache, self.infcx.tcx).ty, + Place::ty_from(base, proj_base, &*self.body, self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -246,7 +246,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { base: PlaceBase::Local(local), projection: [], } if { - self.body_cache.local_decls.get(*local).map(|local_decl| { + self.body.local_decls.get(*local).map(|local_decl| { if let LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(kind) )) = local_decl.local_info { @@ -281,12 +281,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [], - } if self.body_cache.local_decls[*local].can_be_made_mutable() => { + } if self.body.local_decls[*local].can_be_made_mutable() => { // ... but it doesn't make sense to suggest it on // variables that are `ref x`, `ref mut x`, `&self`, // or `&mut self` (such variables are simply not // mutable). - let local_decl = &self.body_cache.local_decls[*local]; + let local_decl = &self.body.local_decls[*local]; assert_eq!(local_decl.mutability, Mutability::Not); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -304,7 +304,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(base, proj_base, &self.body_cache, self.infcx.tcx).ty + Place::ty_from(base, proj_base, &*self.body, self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); @@ -350,7 +350,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref], - } if self.body_cache.local_decls[*local].is_ref_for_guard() => { + } if self.body.local_decls[*local].is_ref_for_guard() => { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.note( "variables bound in patterns are immutable until the end of the pattern guard", @@ -365,9 +365,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref], - } if self.body.local_decls[*local].is_user_variable() => + } if self.body_cache.local_decls[*local].is_user_variable.is_some() => { - let local_decl = &self.body_cache.local_decls[*local]; + let local_decl = &self.body.local_decls[*local]; let suggestion = match local_decl.local_info { LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => { Some(suggest_ampmut_self(self.infcx.tcx, local_decl)) @@ -381,7 +381,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, ))) => Some(suggest_ampmut( self.infcx.tcx, - self.body_cache, + self.body, *local, local_decl, opt_ty_info, @@ -455,7 +455,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_help( - self.body_cache.span, + self.body.span, "consider changing this to accept closures that implement `FnMut`" ); } @@ -533,14 +533,14 @@ fn suggest_ampmut_self<'tcx>( // by trying (3.), then (2.) and finally falling back on (1.). fn suggest_ampmut<'tcx>( tcx: TyCtxt<'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, local: Local, local_decl: &mir::LocalDecl<'tcx>, opt_ty_info: Option, ) -> (Span, String) { - let locations = body_cache.find_assignments(local); + let locations = body.find_assignments(local); if !locations.is_empty() { - let assignment_rhs_span = body_cache.source_info(locations[0]).span; + let assignment_rhs_span = body.source_info(locations[0]).span; if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { if let (true, Some(ws_pos)) = ( src.starts_with("&'"), diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 1e07f354b83f7..43aabac00bcfa 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -237,7 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let regioncx = &self.nonlexical_regioncx; - let body: &Body<'_> = &self.body_cache; + let body: &Body<'_> = &self.body; let tcx = self.infcx.tcx; let borrow_region_vid = borrow.region; @@ -297,7 +297,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) { let (category, from_closure, span, region_name) = self.nonlexical_regioncx.free_region_constraint_info( - &self.body_cache, + &self.body, &self.local_names, &self.upvars, self.mir_def_id, @@ -365,7 +365,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return outmost_back_edge; } - let block = &self.body_cache.basic_blocks()[location.block]; + let block = &self.body.basic_blocks()[location.block]; if location.statement_index < block.statements.len() { let successor = location.successor_within_block(); @@ -427,7 +427,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if loop_head.dominates(from, &self.dominators) { - let block = &self.body_cache.basic_blocks()[from.block]; + let block = &self.body.basic_blocks()[from.block]; if from.statement_index < block.statements.len() { let successor = from.successor_within_block(); @@ -475,7 +475,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (LaterUseKind::ClosureCapture, var_span) } UseSpans::OtherUse(span) => { - let block = &self.body_cache.basic_blocks()[location.block]; + let block = &self.body.basic_blocks()[location.block]; let kind = if let Some(&Statement { kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), @@ -498,7 +498,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Operand::Copy(place) | Operand::Move(place) => { if let Some(l) = place.as_local() { - let local_decl = &self.body_cache.local_decls[l]; + let local_decl = &self.body.local_decls[l]; if self.local_names[l].is_none() { local_decl.source_info.span } else { @@ -528,7 +528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool { // Start at the reserve location, find the place that we want to see cast to a trait object. let location = borrow.reserve_location; - let block = &self.body_cache[location.block]; + let block = &self.body[location.block]; let stmt = block.statements.get(location.statement_index); debug!( "was_captured_by_trait_object: location={:?} stmt={:?}", @@ -558,7 +558,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); while let Some(current_location) = queue.pop() { debug!("was_captured_by_trait: target={:?}", target); - let block = &self.body_cache[current_location.block]; + let block = &self.body[current_location.block]; // We need to check the current location to find out if it is a terminator. let is_terminator = current_location.statement_index == block.statements.len(); if !is_terminator { diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index a2929fe474762..98679f236db50 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -22,7 +22,7 @@ pub(super) fn generate_invalidates<'tcx>( param_env: ty::ParamEnv<'tcx>, all_facts: &mut Option, location_table: &LocationTable, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, borrow_set: &BorrowSet<'tcx>, ) { if all_facts.is_none() { @@ -31,17 +31,17 @@ pub(super) fn generate_invalidates<'tcx>( } if let Some(all_facts) = all_facts { - let dominators = body_cache.dominators(); + let dominators = body.dominators(); let mut ig = InvalidationGenerator { all_facts, borrow_set, param_env, tcx, location_table, - body: &body_cache, + body: &body, dominators, }; - ig.visit_body(body_cache); + ig.visit_body(body); } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index ff28a27911b69..16182fe24fa4f 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -55,7 +55,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, promoted: &mut IndexVec>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -64,10 +64,10 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( let universal_regions = UniversalRegions::new(infcx, def_id, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body_cache, promoted); + renumber::renumber_mir(infcx, body, promoted); let source = MirSource::item(def_id); - mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body_cache, |_, _| Ok(())); + mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); universal_regions } @@ -158,8 +158,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, def_id: DefId, universal_regions: UniversalRegions<'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, - promoted_cache: &IndexVec>, + body: ReadOnlyBodyCache<'_, 'tcx>, + promoted: &IndexVec>, local_names: &IndexVec>, upvars: &[Upvar], location_table: &LocationTable, @@ -182,7 +182,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); let elements - = &Rc::new(RegionValueElements::new(&body_cache)); + = &Rc::new(RegionValueElements::new(&body)); // Run the MIR type-checker. let MirTypeckResults { @@ -191,8 +191,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( } = type_check::type_check( infcx, param_env, - body_cache, - promoted_cache, + body, + promoted, def_id, &universal_regions, location_table, @@ -207,7 +207,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); - populate_polonius_move_facts(all_facts, move_data, location_table, &body_cache); + populate_polonius_move_facts(all_facts, move_data, location_table, &body); } // Create the region inference context, taking ownership of the @@ -231,7 +231,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( &mut liveness_constraints, &mut all_facts, location_table, - &body_cache, + &body, borrow_set, ); @@ -254,7 +254,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( param_env, &mut all_facts, location_table, - body_cache, + body, borrow_set, ); @@ -284,14 +284,14 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let closure_region_requirements = - regioncx.solve(infcx, &body_cache, local_names, upvars, def_id, errors_buffer); + regioncx.solve(infcx, &body, local_names, upvars, def_id, errors_buffer); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, MirSource::item(def_id), - &body_cache, + &body, ®ioncx, &closure_region_requirements, ); @@ -300,7 +300,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // information dump_annotation( infcx, - &body_cache, + &body, def_id, ®ioncx, &closure_region_requirements, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 16d2eca8f20e4..b4414c514c532 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -92,7 +92,7 @@ impl RegionValueElements { /// Pushes all predecessors of `index` onto `stack`. crate fn push_predecessors( &self, - body_cache: ReadOnlyBodyCache<'_, '_>, + body: ReadOnlyBodyCache<'_, '_>, index: PointIndex, stack: &mut Vec, ) { @@ -104,9 +104,9 @@ impl RegionValueElements { // If this is a basic block head, then the predecessors are // the terminators of other basic blocks stack.extend( - body_cache.predecessors_for(block) + body.predecessors_for(block) .iter() - .map(|&pred_bb| body_cache.terminator_loc(pred_bb)) + .map(|&pred_bb| body.terminator_loc(pred_bb)) .map(|pred_loc| self.point_from_location(pred_loc)), ); } else { diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 882b825c5284e..db15d2c54fdbc 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -9,11 +9,11 @@ use rustc_index::vec::IndexVec; /// inference variables, returning the number of variables created. pub fn renumber_mir<'tcx>( infcx: &InferCtxt<'_, 'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, promoted: &mut IndexVec>, ) { debug!("renumber_mir()"); - debug!("renumber_mir: body.arg_count={:?}", body_cache.arg_count); + debug!("renumber_mir: body.arg_count={:?}", body.arg_count); let mut visitor = NLLVisitor { infcx }; @@ -21,7 +21,7 @@ pub fn renumber_mir<'tcx>( visitor.visit_body(body); } - visitor.visit_body(body_cache); + visitor.visit_body(body); } /// Replaces all regions appearing in `value` with fresh inference diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 0cd5dd8059495..d6aa31449daa7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -60,9 +60,9 @@ impl LocalUseMap { crate fn build( live_locals: &Vec, elements: &RegionValueElements, - body_cache: ReadOnlyBodyCache<'_, '_>, + body: ReadOnlyBodyCache<'_, '_>, ) -> Self { - let nones = IndexVec::from_elem_n(None, body_cache.local_decls.len()); + let nones = IndexVec::from_elem_n(None, body.local_decls.len()); let mut local_use_map = LocalUseMap { first_def_at: nones.clone(), first_use_at: nones.clone(), @@ -75,11 +75,11 @@ impl LocalUseMap { } let mut locals_with_use_data: IndexVec = - IndexVec::from_elem_n(false, body_cache.local_decls.len()); + IndexVec::from_elem_n(false, body.local_decls.len()); live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } - .visit_body(body_cache); + .visit_body(body); local_use_map } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 2dea6797ec748..dfd505f6b613a 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -28,7 +28,7 @@ mod trace; /// performed before pub(super) fn generate<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -41,14 +41,14 @@ pub(super) fn generate<'tcx>( &typeck.borrowck_context.universal_regions, &typeck.borrowck_context.constraints.outlives_constraints, ); - let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body_cache); + let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body); let facts_enabled = AllFacts::enabled(typeck.tcx()); let polonius_drop_used = if facts_enabled { let mut drop_used = Vec::new(); polonius::populate_access_facts( typeck, - body_cache, + body, location_table, move_data, &mut drop_used, @@ -61,7 +61,7 @@ pub(super) fn generate<'tcx>( if !live_locals.is_empty() || facts_enabled { trace::trace( typeck, - body_cache, + body, elements, flow_inits, move_data, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index c17fbf0cdc9f8..e67de6c99f026 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -97,7 +97,7 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, drop_used: &mut Vec<(Local, Location)>, @@ -113,14 +113,14 @@ pub(super) fn populate_access_facts( location_table, move_data, } - .visit_body(body_cache); + .visit_body(body); facts.var_drop_used.extend(drop_used.iter().map(|&(local, location)| { (local, location_table.mid_index(location)) })); } - for (local, local_decl) in body_cache.local_decls.iter_enumerated() { + for (local, local_decl) in body.local_decls.iter_enumerated() { add_var_uses_regions(typeck, local, local_decl.ty); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 1eaa82ec08e27..229cbed64c272 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -32,7 +32,7 @@ use std::rc::Rc; /// this respects `#[may_dangle]` annotations). pub(super) fn trace( typeck: &mut TypeChecker<'_, 'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, elements: &Rc, flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, @@ -41,11 +41,11 @@ pub(super) fn trace( ) { debug!("trace()"); - let local_use_map = &LocalUseMap::build(&live_locals, elements, body_cache); + let local_use_map = &LocalUseMap::build(&live_locals, elements, body); let cx = LivenessContext { typeck, - body_cache, + body, flow_inits, elements, local_use_map, @@ -71,7 +71,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { elements: &'me RegionValueElements, /// MIR we are analyzing. - body_cache: ReadOnlyBodyCache<'me, 'tcx>, + body: ReadOnlyBodyCache<'me, 'tcx>, /// Mapping to/from the various indices used for initialization tracking. move_data: &'me MoveData<'tcx>, @@ -135,7 +135,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { self.compute_use_live_points_for(local); self.compute_drop_live_points_for(local); - let local_ty = self.cx.body_cache.local_decls[local].ty; + let local_ty = self.cx.body.local_decls[local].ty; if !self.use_live_at.is_empty() { self.cx.add_use_live_facts_for(local_ty, &self.use_live_at); @@ -165,7 +165,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { for (local, location) in drop_used { if !live_locals.contains(&local) { - let local_ty = self.cx.body_cache.local_decls[local].ty; + let local_ty = self.cx.body.local_decls[local].ty; if local_ty.has_free_regions() { self.cx.add_drop_live_facts_for( local, @@ -211,7 +211,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } if self.use_live_at.insert(p) { - self.cx.elements.push_predecessors(self.cx.body_cache, p, &mut self.stack) + self.cx.elements.push_predecessors(self.cx.body, p, &mut self.stack) } } } @@ -234,7 +234,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // Find the drops where `local` is initialized. for drop_point in self.cx.local_use_map.drops(local) { let location = self.cx.elements.to_location(drop_point); - debug_assert_eq!(self.cx.body_cache.terminator_loc(location.block), location,); + debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); if self.cx.initialized_at_terminator(location.block, mpi) { if self.drop_live_at.insert(drop_point) { @@ -280,7 +280,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // block. One of them may be either a definition or use // live point. let term_location = self.cx.elements.to_location(term_point); - debug_assert_eq!(self.cx.body_cache.terminator_loc(term_location.block), term_location,); + debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,); let block = term_location.block; let entry_point = self.cx.elements.entry_point(term_location.block); for p in (entry_point..term_point).rev() { @@ -302,8 +302,8 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - let body_cache = self.cx.body_cache; - for &pred_block in body_cache.predecessors_for(block).iter() { + let body = self.cx.body; + for &pred_block in body.predecessors_for(block).iter() { debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,); // Check whether the variable is (at least partially) @@ -329,7 +329,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { continue; } - let pred_term_loc = self.cx.body_cache.terminator_loc(pred_block); + let pred_term_loc = self.cx.body.terminator_loc(pred_block); let pred_term_point = self.cx.elements.point_from_location(pred_term_loc); // If the terminator of this predecessor either *assigns* @@ -400,7 +400,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { // the effects of all statements. This is the only way to get // "just ahead" of a terminator. self.flow_inits.reset_to_entry_of(block); - for statement_index in 0..self.body_cache[block].statements.len() { + for statement_index in 0..self.body[block].statements.len() { let location = Location { block, statement_index }; self.flow_inits.reconstruct_statement_effect(location); self.flow_inits.apply_local_effect(location); @@ -472,7 +472,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { drop_data.dropck_result.report_overflows( self.typeck.infcx.tcx, - self.body_cache.source_info(*drop_locations.first().unwrap()).span, + self.body.source_info(*drop_locations.first().unwrap()).span, dropped_ty, ); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 5190e0f939f34..5a8fd3f707d6d 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -115,8 +115,8 @@ mod relate_tys; pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, - promoted_cache: &IndexVec>, + body: ReadOnlyBodyCache<'_, 'tcx>, + promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, location_table: &LocationTable, @@ -161,20 +161,20 @@ pub(crate) fn type_check<'tcx>( infcx, mir_def_id, param_env, - body_cache, - promoted_cache, + body, + promoted, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, &universal_region_relations, |mut cx| { cx.equate_inputs_and_outputs( - &body_cache, + &body, universal_regions, &normalized_inputs_and_output); liveness::generate( &mut cx, - body_cache, + body, elements, flow_inits, move_data, @@ -194,8 +194,8 @@ fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, - body_cache: ReadOnlyBodyCache<'a, 'tcx>, - promoted_cache: &'a IndexVec>, + body: ReadOnlyBodyCache<'a, 'tcx>, + promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -204,7 +204,7 @@ fn type_check_internal<'a, 'tcx, R>( ) -> R { let mut checker = TypeChecker::new( infcx, - body_cache.body(), + body.body(), mir_def_id, param_env, region_bound_pairs, @@ -213,14 +213,14 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body_cache.body(), promoted_cache); - verifier.visit_body(body_cache); + let mut verifier = TypeVerifier::new(&mut checker, body.body(), promoted); + verifier.visit_body(body); verifier.errors_reported }; if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(&body_cache); + checker.typeck_mir(&body); } extra(&mut checker) @@ -270,7 +270,7 @@ enum FieldAccessError { struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, - promoted_cache: &'b IndexVec>, + promoted: &'b IndexVec>, last_span: Span, mir_def_id: DefId, errors_reported: bool, @@ -394,15 +394,15 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - fn visit_body(&mut self, body_cache: ReadOnlyBodyCache<'_, 'tcx>) { - self.sanitize_type(&"return type", body_cache.return_ty()); - for local_decl in &body_cache.local_decls { + fn visit_body(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) { + self.sanitize_type(&"return type", body.return_ty()); + for local_decl in &body.local_decls { self.sanitize_type(local_decl, local_decl.ty); } if self.errors_reported { return; } - self.super_body(body_cache); + self.super_body(body); } } @@ -410,11 +410,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn new( cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, - promoted_cache: &'b IndexVec>, + promoted: &'b IndexVec>, ) -> Self { TypeVerifier { body, - promoted_cache, + promoted, mir_def_id: cx.mir_def_id, cx, last_span: body.span, @@ -473,7 +473,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { match kind { StaticKind::Promoted(promoted, _) => { if !self.errors_reported { - let promoted_body_cache = self.promoted_cache[*promoted]; + let promoted_body_cache = self.promoted[*promoted]; self.sanitize_promoted(promoted_body_cache, location); let promoted_ty = promoted_body_cache.return_ty(); @@ -546,14 +546,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn sanitize_promoted( &mut self, - promoted_body_cache: ReadOnlyBodyCache<'b, 'tcx>, + promoted_body: ReadOnlyBodyCache<'b, 'tcx>, location: Location ) { // Determine the constraints from the promoted MIR by running the type // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. - let parent_body = mem::replace(&mut self.body, promoted_body_cache.body()); + let parent_body = mem::replace(&mut self.body, promoted_body.body()); // Use new sets of constraints and closure bounds so that we can // modify their locations. @@ -561,7 +561,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let mut constraints = Default::default(); let mut closure_bounds = Default::default(); let mut liveness_constraints = LivenessValues::new( - Rc::new(RegionValueElements::new(&promoted_body_cache)), + Rc::new(RegionValueElements::new(&promoted_body)), ); // Don't try to add borrow_region facts for the promoted MIR @@ -583,12 +583,12 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { swap_constraints(self); - self.visit_body(promoted_body_cache); + self.visit_body(promoted_body); if !self.errors_reported { // if verifier failed, don't do further checks to avoid ICEs - self.cx.typeck_mir(&promoted_body_cache); + self.cx.typeck_mir(&promoted_body); } self.body = parent_body; diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 82763df749240..06b9d4dbde003 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -26,7 +26,7 @@ impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> { } pub(super) struct Prefixes<'cx, 'tcx> { - body_cache: ReadOnlyBodyCache<'cx, 'tcx>, + body: ReadOnlyBodyCache<'cx, 'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, next: Option>, @@ -56,7 +56,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, - body_cache: self.body_cache, + body: self.body, tcx: self.infcx.tcx, } } @@ -143,7 +143,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // derefs, except we stop at the deref of a shared // reference. - let ty = Place::ty_from(cursor.base, proj_base, &self.body_cache, self.tcx).ty; + let ty = Place::ty_from(cursor.base, proj_base, &*self.body, self.tcx).ty; match ty.kind { ty::RawPtr(_) | ty::Ref( diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index 27e6d803bd0ab..95471afb7884f 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -32,7 +32,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { never_initialized_mut_locals: &mut never_initialized_mut_locals, mbcx: self, }; - visitor.visit_body(visitor.mbcx.body_cache); + visitor.visit_body(visitor.mbcx.body); } // Take the union of the existed `used_mut` set with those variables we've found were diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 0a205be0c58de..2a4f1c89b3a1f 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -354,7 +354,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } // This is a const fn. Call it. Ok(Some(match ecx.load_mir(instance.def, None) { - Ok(body_cache) => body_cache.body(), + Ok(body) => body.body(), Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { return Err( @@ -697,7 +697,7 @@ pub fn const_eval_raw_provider<'tcx>( let res = ecx.load_mir(cid.instance.def, cid.promoted); res.and_then( - |body_cache| eval_body_using_ecx(&mut ecx, cid, body_cache.body()) + |body| eval_body_using_ecx(&mut ecx, cid, body.body()) ).and_then(|place| { Ok(RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index f2c0b7149614c..7e7652cdab5ce 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -153,8 +153,8 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } Borrows { - tcx: tcx, - body: body, + tcx, + body, param_env, borrow_set: borrow_set.clone(), borrows_out_of_scope_at_location, diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 6f860d00a22c2..0fb912b5fcbd8 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -71,7 +71,7 @@ pub struct MaybeInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - MaybeInitializedPlaces { tcx: tcx, body: body, mdpe: mdpe } + MaybeInitializedPlaces { tcx, body, mdpe } } } @@ -122,7 +122,7 @@ pub struct MaybeUninitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - MaybeUninitializedPlaces { tcx: tcx, body: body, mdpe: mdpe } + MaybeUninitializedPlaces { tcx, body, mdpe } } } @@ -172,7 +172,7 @@ pub struct DefinitelyInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - DefinitelyInitializedPlaces { tcx: tcx, body: body, mdpe: mdpe } + DefinitelyInitializedPlaces { tcx, body, mdpe } } } @@ -217,7 +217,7 @@ pub struct EverInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - EverInitializedPlaces { tcx: tcx, body: body, mdpe: mdpe } + EverInitializedPlaces { tcx, body, mdpe } } } diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 3f76d0e3a3cec..c4b97d12e6270 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -75,26 +75,26 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. pub struct RequiresStorage<'mir, 'tcx> { - body_cache: ReadOnlyBodyCache<'mir, 'tcx>, + body: ReadOnlyBodyCache<'mir, 'tcx>, borrowed_locals: RefCell>>, } impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { pub fn new( - body_cache: ReadOnlyBodyCache<'mir, 'tcx>, + body: ReadOnlyBodyCache<'mir, 'tcx>, borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>, ) -> Self { RequiresStorage { - body_cache, + body, borrowed_locals: RefCell::new( - DataflowResultsCursor::new(borrowed_locals, body_cache.body()) + DataflowResultsCursor::new(borrowed_locals, body.body()) ), } } pub fn body(&self) -> &Body<'tcx> { - &self.body_cache + &self.body } } @@ -102,13 +102,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { type Idx = Local; fn name() -> &'static str { "requires_storage" } fn bits_per_block(&self) -> usize { - self.body_cache.local_decls.len() + self.body.local_decls.len() } fn start_block_effect(&self, _sets: &mut BitSet) { // Nothing is live on function entry (generators only have a self // argument, and we don't care about that) - assert_eq!(1, self.body_cache.arg_count); + assert_eq!(1, self.body.arg_count); } fn before_statement_effect(&self, sets: &mut GenKillSet, loc: Location) { @@ -116,7 +116,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { // statement. self.check_for_borrow(sets, loc); - let stmt = &self.body_cache[loc.block].statements[loc.statement_index]; + let stmt = &self.body[loc.block].statements[loc.statement_index]; match stmt.kind { StatementKind::StorageDead(l) => sets.kill(l), StatementKind::Assign(box(ref place, _)) @@ -148,7 +148,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { if let TerminatorKind::Call { destination: Some((Place { base: PlaceBase::Local(local), .. }, _)), .. - } = self.body_cache[loc.block].terminator().kind { + } = self.body[loc.block].terminator().kind { sets.gen(local); } } @@ -161,7 +161,7 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { if let TerminatorKind::Call { destination: Some((ref place, _)), .. - } = self.body_cache[loc.block].terminator().kind { + } = self.body[loc.block].terminator().kind { if let Some(local) = place.as_local() { sets.kill(local); } @@ -189,7 +189,7 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { sets, borrowed_locals: &self.borrowed_locals, }; - visitor.visit_location(self.body_cache, loc); + visitor.visit_location(self.body, loc); } /// Gen locals that are newly borrowed. This includes borrowing any part of diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 67de4ce168c02..4fe53cf35e511 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1248,14 +1248,14 @@ fn collect_neighbours<'tcx>( output: &mut Vec>, ) { debug!("collect_neighbours: {:?}", instance.def_id()); - let body_cache = tcx.instance_mir(instance.def); + let body = tcx.instance_mir(instance.def); MirNeighborCollector { tcx, - body: &body_cache, + body: &body, output, param_substs: instance.substs, - }.visit_body(body_cache); + }.visit_body(body); } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 43600d6a5d8ee..0636d254c2f39 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -205,14 +205,14 @@ fn build_drop_shim<'tcx>( sig.inputs().len(), span); - let mut body_cache = BodyCache::new(body); + let mut body = BodyCache::new(body); if let Some(..) = ty { // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::from(Local::new(1+0)); if tcx.sess.opts.debugging_opts.mir_emit_retag { // Function arguments should be retagged, and we make this one raw. - body_cache.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { + body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, kind: StatementKind::Retag(RetagKind::Raw, box(dropee_ptr.clone())), }); @@ -220,8 +220,8 @@ fn build_drop_shim<'tcx>( let patch = { let param_env = tcx.param_env(def_id).with_reveal_all(); let mut elaborator = DropShimElaborator { - body: &body_cache, - patch: MirPatch::new(&body_cache), + body: &body, + patch: MirPatch::new(&body), tcx, param_env }; @@ -238,10 +238,10 @@ fn build_drop_shim<'tcx>( ); elaborator.patch }; - patch.apply(&mut body_cache); + patch.apply(&mut body); } - body_cache + body } fn new_body<'tcx>( @@ -931,7 +931,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> { |_, _| Ok(()), ); - let mut body_cache = BodyCache::new(body); - body_cache.ensure_predecessors(); - tcx.arena.alloc(body_cache) + let mut body = BodyCache::new(body); + body.ensure_predecessors(); + tcx.arena.alloc(body) } diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 48aa53a58c9b5..35238e2d08a2e 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -32,23 +32,22 @@ pub use self::AddCallGuards::*; impl<'tcx> MirPass<'tcx> for AddCallGuards { fn run_pass( - &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { - self.add_call_guards(body_cache); + self.add_call_guards(body); } } impl AddCallGuards { - pub fn add_call_guards(&self, body_cache: &mut BodyCache<'_>) { - let pred_count: IndexVec<_, _> = - body_cache.predecessors().iter().map(|ps| ps.len()).collect(); + pub fn add_call_guards(&self, body: &mut BodyCache<'_>) { + let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect(); // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); - let cur_len = body_cache.basic_blocks().len(); + let cur_len = body.basic_blocks().len(); - for block in body_cache.basic_blocks_mut() { + for block in body.basic_blocks_mut() { match block.terminator { Some(Terminator { kind: TerminatorKind::Call { @@ -80,6 +79,6 @@ impl AddCallGuards { debug!("Broke {} N edges", new_blocks.len()); - body_cache.basic_blocks_mut().extend(new_blocks); + body.basic_blocks_mut().extend(new_blocks); } } diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index 21bc679b9a039..98c6a5ed07780 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -40,17 +40,17 @@ use crate::util; pub struct AddMovesForPackedDrops; impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body_cache.span); - add_moves_for_packed_drops(tcx, body_cache, src.def_id()); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span); + add_moves_for_packed_drops(tcx, body, src.def_id()); } } pub fn add_moves_for_packed_drops<'tcx>( - tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>, def_id: DefId + tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>, def_id: DefId ) { - let patch = add_moves_for_packed_drops_patch(tcx, body_cache, def_id); - patch.apply(body_cache); + let patch = add_moves_for_packed_drops_patch(tcx, body, def_id); + patch.apply(body); } fn add_moves_for_packed_drops_patch<'tcx>( diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 25594ab20a91c..e6ad37ae11362 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -59,12 +59,12 @@ fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { } impl<'tcx> MirPass<'tcx> for AddRetag { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } - let (span, arg_count) = (body_cache.span, body_cache.arg_count); - let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut(); + let (span, arg_count) = (body.span, body.arg_count); + let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let needs_retag = |place: &Place<'tcx>| { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 9e314dbc6e893..85932bc5e5bc1 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -516,7 +516,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult // N.B., this borrow is valid because all the consumers of // `mir_built` force this. - let body_cache = &tcx.mir_built(def_id).borrow(); + let body = &tcx.mir_built(def_id).borrow(); let param_env = tcx.param_env(def_id); @@ -527,9 +527,9 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false), }; - let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body_cache, tcx, param_env); - let mut cache = body_cache.cache().clone(); - let read_only_cache = ReadOnlyBodyCache::from_external_cache(&mut cache, body_cache); + let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env); + let mut cache = body.cache().clone(); + let read_only_cache = ReadOnlyBodyCache::from_external_cache(&mut cache, body); checker.visit_body(read_only_cache); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 23ab2c28063bb..d9dd7c9d84776 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -30,10 +30,10 @@ pub struct DeleteNonCodegenStatements<'tcx> { impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { fn run_pass( - &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { let mut delete = DeleteNonCodegenStatements { tcx }; - delete.visit_body(body_cache); + delete.visit_body(body); } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 3ea97ff68fd3f..7c1318da7b01d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -43,7 +43,7 @@ pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { @@ -79,15 +79,15 @@ impl<'tcx> MirPass<'tcx> for ConstProp { let dummy_body = &Body::new( - body_cache.basic_blocks().clone(), - body_cache.source_scopes.clone(), - body_cache.local_decls.clone(), + body.basic_blocks().clone(), + body.source_scopes.clone(), + body.local_decls.clone(), Default::default(), - body_cache.arg_count, + body.arg_count, Default::default(), tcx.def_span(source.def_id()), Default::default(), - body_cache.generator_kind, + body.generator_kind, ); // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold @@ -95,12 +95,12 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // That would require an uniform one-def no-mutation analysis // and RPO (or recursing when needing the value of a local). let mut optimization_finder = ConstPropagator::new( - read_only!(body_cache), + read_only!(body), dummy_body, tcx, source ); - optimization_finder.visit_body(body_cache); + optimization_finder.visit_body(body); trace!("ConstProp done for {:?}", source.def_id()); } @@ -287,7 +287,7 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> { impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn new( - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, dummy_body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, @@ -296,7 +296,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let param_env = tcx.param_env(def_id); let span = tcx.def_span(def_id); let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ()); - let can_const_prop = CanConstProp::check(body_cache); + let can_const_prop = CanConstProp::check(body); let substs = &InternalSubsts::identity_for_item(tcx, def_id); @@ -328,9 +328,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { can_const_prop, // FIXME(eddyb) avoid cloning these two fields more than once, // by accessing them through `ecx` instead. - source_scopes: body_cache.source_scopes.clone(), + source_scopes: body.source_scopes.clone(), //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it - local_decls: body_cache.local_decls.clone(), + local_decls: body.local_decls.clone(), ret: ret.map(Into::into), } } @@ -681,10 +681,10 @@ struct CanConstProp { impl CanConstProp { /// returns true if `local` can be propagated - fn check(body_cache: ReadOnlyBodyCache<'_, '_>) -> IndexVec { + fn check(body: ReadOnlyBodyCache<'_, '_>) -> IndexVec { let mut cpv = CanConstProp { - can_const_prop: IndexVec::from_elem(true, &body_cache.local_decls), - found_assignment: IndexVec::from_elem(false, &body_cache.local_decls), + can_const_prop: IndexVec::from_elem(true, &body.local_decls), + found_assignment: IndexVec::from_elem(false, &body.local_decls), }; for (local, val) in cpv.can_const_prop.iter_enumerated_mut() { // cannot use args at all @@ -692,14 +692,14 @@ impl CanConstProp { // lint for x != y // FIXME(oli-obk): lint variables until they are used in a condition // FIXME(oli-obk): lint if return value is constant - let local_kind = body_cache.local_kind(local); + let local_kind = body.local_kind(local); *val = local_kind == LocalKind::Temp || local_kind == LocalKind::ReturnPointer; if !*val { trace!("local {:?} can't be propagated because it's not a temporary", local); } } - cpv.visit_body(body_cache); + cpv.visit_body(body); cpv.can_const_prop } } diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index d2f83eeadeb84..5e4caf2f36d2d 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -32,7 +32,7 @@ pub struct CopyPropagation; impl<'tcx> MirPass<'tcx> for CopyPropagation { fn run_pass( - &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. @@ -40,16 +40,16 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { return; } - let mut def_use_analysis = DefUseAnalysis::new(body_cache); + let mut def_use_analysis = DefUseAnalysis::new(body); loop { - def_use_analysis.analyze(read_only!(body_cache)); + def_use_analysis.analyze(read_only!(body)); - if eliminate_self_assignments(body_cache, &def_use_analysis) { - def_use_analysis.analyze(read_only!(body_cache)); + if eliminate_self_assignments(body, &def_use_analysis) { + def_use_analysis.analyze(read_only!(body)); } let mut changed = false; - for dest_local in body_cache.local_decls.indices() { + for dest_local in body.local_decls.indices() { debug!("considering destination local: {:?}", dest_local); let action; @@ -76,7 +76,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } // Conservatively gives up if the dest is an argument, // because there may be uses of the original argument value. - if body_cache.local_kind(dest_local) == LocalKind::Arg { + if body.local_kind(dest_local) == LocalKind::Arg { debug!(" Can't copy-propagate local: dest {:?} (argument)", dest_local); continue; @@ -84,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { let dest_place_def = dest_use_info.defs_not_including_drop().next().unwrap(); location = dest_place_def.location; - let basic_block = &body_cache[location.block]; + let basic_block = &body[location.block]; let statement_index = location.statement_index; let statement = match basic_block.statements.get(statement_index) { Some(statement) => statement, @@ -103,7 +103,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { Operand::Copy(ref src_place) | Operand::Move(ref src_place) => { Action::local_copy( - &body_cache, + &body, &def_use_analysis, src_place) } @@ -134,7 +134,7 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } } - changed = action.perform(body_cache, &def_use_analysis, dest_local, location, tcx) + changed = action.perform(body, &def_use_analysis, dest_local, location, tcx) || changed; // FIXME(pcwalton): Update the use-def chains to delete the instructions instead of // regenerating the chains. @@ -250,7 +250,7 @@ impl<'tcx> Action<'tcx> { } fn perform(self, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, def_use_analysis: &DefUseAnalysis, dest_local: Local, location: Location, @@ -268,22 +268,22 @@ impl<'tcx> Action<'tcx> { src_local); for place_use in &def_use_analysis.local_info(dest_local).defs_and_uses { if place_use.context.is_storage_marker() { - body_cache.make_statement_nop(place_use.location) + body.make_statement_nop(place_use.location) } } for place_use in &def_use_analysis.local_info(src_local).defs_and_uses { if place_use.context.is_storage_marker() { - body_cache.make_statement_nop(place_use.location) + body.make_statement_nop(place_use.location) } } // Replace all uses of the destination local with the source local. def_use_analysis - .replace_all_defs_and_uses_with(dest_local, body_cache, src_local, tcx); + .replace_all_defs_and_uses_with(dest_local, body, src_local, tcx); // Finally, zap the now-useless assignment instruction. debug!(" Deleting assignment"); - body_cache.make_statement_nop(location); + body.make_statement_nop(location); true } @@ -297,7 +297,7 @@ impl<'tcx> Action<'tcx> { let dest_local_info = def_use_analysis.local_info(dest_local); for place_use in &dest_local_info.defs_and_uses { if place_use.context.is_storage_marker() { - body_cache.make_statement_nop(place_use.location) + body.make_statement_nop(place_use.location) } } @@ -306,7 +306,7 @@ impl<'tcx> Action<'tcx> { src_constant, tcx); for dest_place_use in &dest_local_info.defs_and_uses { - visitor.visit_location(body_cache, dest_place_use.location) + visitor.visit_location(body, dest_place_use.location) } // Zap the assignment instruction if we eliminated all the uses. We won't have been @@ -317,7 +317,7 @@ impl<'tcx> Action<'tcx> { debug!(" {} of {} use(s) replaced; deleting assignment", visitor.uses_replaced, use_count); - body_cache.make_statement_nop(location); + body.make_statement_nop(location); true } else if visitor.uses_replaced == 0 { debug!(" No uses replaced; not deleting assignment"); diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 5ad034539e0e2..933936e7efff7 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -7,9 +7,9 @@ pub struct Deaggregator; impl<'tcx> MirPass<'tcx> for Deaggregator { fn run_pass( - &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { - let (basic_blocks, local_decls) = body_cache.basic_blocks_and_local_decls_mut(); + let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { bb.expand_statements(|stmt| { diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 3dbebf885f70e..13b3bb6da4ef9 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for Marker { } fn run_pass( - &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body_cache: &mut BodyCache<'tcx> + &self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut BodyCache<'tcx> ) {} } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 378d991025a8f..42daba93bd293 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -21,17 +21,17 @@ use syntax_pos::Span; pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - debug!("elaborate_drops({:?} @ {:?})", src, body_cache.span); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + debug!("elaborate_drops({:?} @ {:?})", src, body.span); let def_id = src.def_id(); let param_env = tcx.param_env(src.def_id()).with_reveal_all(); - let move_data = match MoveData::gather_moves(body_cache, tcx) { + let move_data = match MoveData::gather_moves(body, tcx) { Ok(move_data) => move_data, Err(_) => bug!("No `move_errors` should be allowed in MIR borrowck"), }; let elaborate_patch = { - let body = &*body_cache; + let body = &*body; let env = MoveDataParamEnv { move_data, param_env, @@ -56,7 +56,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { patch: MirPatch::new(body), }.elaborate() }; - elaborate_patch.apply(body_cache); + elaborate_patch.apply(body); } } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index ff07f65d22c43..882e67432a5ed 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -62,7 +62,7 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { pub struct EraseRegions; impl<'tcx> MirPass<'tcx> for EraseRegions { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - EraseRegionsVisitor::new(tcx).visit_body(body_cache); + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + EraseRegionsVisitor::new(tcx).visit_body(body); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index f9b8b3d6aec52..e55737e8859ef 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -378,9 +378,9 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { fn make_generator_state_argument_indirect<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, ) { - let gen_ty = body_cache.local_decls.raw[1].ty; + let gen_ty = body.local_decls.raw[1].ty; let region = ty::ReFree(ty::FreeRegion { scope: def_id, @@ -395,14 +395,14 @@ fn make_generator_state_argument_indirect<'tcx>( }); // Replace the by value generator argument - body_cache.local_decls.raw[1].ty = ref_gen_ty; + body.local_decls.raw[1].ty = ref_gen_ty; // Add a deref to accesses of the generator state - DerefArgVisitor { tcx }.visit_body(body_cache); + DerefArgVisitor { tcx }.visit_body(body); } -fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) { - let ref_gen_ty = body_cache.local_decls.raw[1].ty; +fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) { + let ref_gen_ty = body.local_decls.raw[1].ty; let pin_did = tcx.lang_items().pin_type().unwrap(); let pin_adt_ref = tcx.adt_def(pin_did); @@ -410,18 +410,18 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mu let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs); // Replace the by ref generator argument - body_cache.local_decls.raw[1].ty = pin_ref_gen_ty; + body.local_decls.raw[1].ty = pin_ref_gen_ty; // Add the Pin field access to accesses of the generator state - PinArgVisitor { ref_gen_ty, tcx }.visit_body(body_cache); + PinArgVisitor { ref_gen_ty, tcx }.visit_body(body); } fn replace_result_variable<'tcx>( ret_ty: Ty<'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, tcx: TyCtxt<'tcx>, ) -> Local { - let source_info = source_info(body_cache); + let source_info = source_info(body); let new_ret = LocalDecl { mutability: Mutability::Mut, ty: ret_ty, @@ -431,15 +431,15 @@ fn replace_result_variable<'tcx>( is_block_tail: None, local_info: LocalInfo::Other }; - let new_ret_local = Local::new(body_cache.local_decls.len()); - body_cache.local_decls.push(new_ret); - body_cache.local_decls.swap(RETURN_PLACE, new_ret_local); + let new_ret_local = Local::new(body.local_decls.len()); + body.local_decls.push(new_ret); + body.local_decls.swap(RETURN_PLACE, new_ret_local); RenameLocalVisitor { from: RETURN_PLACE, to: new_ret_local, tcx, - }.visit_body(body_cache); + }.visit_body(body); new_ret_local } @@ -481,60 +481,61 @@ struct LivenessInfo { fn locals_live_across_suspend_points( tcx: TyCtxt<'tcx>, - body_cache: ReadOnlyBodyCache<'_, 'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, source: MirSource<'tcx>, movable: bool, ) -> LivenessInfo { - let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); let def_id = source.def_id(); - let body: &Body<'_> = &body_cache; + let body_ref: &Body<'_> = &body; // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. - let storage_live_analysis = MaybeStorageLive::new(body); + let storage_live_analysis = MaybeStorageLive::new(body_ref); let storage_live_results = - do_dataflow(tcx, body, def_id, &[], &dead_unwinds, storage_live_analysis, + do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, storage_live_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); - let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body); + let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body_ref); // Find the MIR locals which do not use StorageLive/StorageDead statements. // The storage of these locals are always live. - let mut ignored = StorageIgnored(BitSet::new_filled(body_cache.local_decls.len())); - ignored.visit_body(body_cache); + let mut ignored = StorageIgnored(BitSet::new_filled(body.local_decls.len())); + ignored.visit_body(body); // Calculate the MIR locals which have been previously // borrowed (even if they are still active). - let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body); + let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body_ref); let borrowed_locals_results = - do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis, + do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, borrowed_locals_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); - let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body); + let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body_ref); // Calculate the MIR locals that we actually need to keep storage around // for. - let requires_storage_analysis = RequiresStorage::new(body_cache, &borrowed_locals_results); + let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results); let requires_storage_results = - do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis, + do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, requires_storage_analysis, |bd, p| DebugFormatted::new(&bd.body().local_decls[p])); - let mut requires_storage_cursor = DataflowResultsCursor::new(&requires_storage_results, body); + let mut requires_storage_cursor + = DataflowResultsCursor::new(&requires_storage_results, body_ref); // Calculate the liveness of MIR locals ignoring borrows. - let mut live_locals = liveness::LiveVarSet::new_empty(body_cache.local_decls.len()); + let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len()); let mut liveness = liveness::liveness_of_locals( - body_cache, + body, ); liveness::dump_mir( tcx, "generator_liveness", source, - body, + body_ref, &liveness, ); let mut storage_liveness_map = FxHashMap::default(); let mut live_locals_at_suspension_points = Vec::new(); - for (block, data) in body_cache.basic_blocks().iter_enumerated() { + for (block, data) in body.basic_blocks().iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { let loc = Location { block: block, @@ -594,7 +595,7 @@ fn locals_live_across_suspend_points( .collect(); let storage_conflicts = compute_storage_conflicts( - body, + body_ref, &live_locals, &ignored, requires_storage_results); @@ -750,7 +751,7 @@ fn compute_layout<'tcx>( upvars: &Vec>, interior: Ty<'tcx>, movable: bool, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, ) -> ( FxHashMap, VariantIdx, usize)>, GeneratorLayout<'tcx>, @@ -759,7 +760,7 @@ fn compute_layout<'tcx>( // Use a liveness analysis to compute locals which are live across a suspension point let LivenessInfo { live_locals, live_locals_at_suspension_points, storage_conflicts, storage_liveness - } = locals_live_across_suspend_points(tcx, read_only!(body_cache), source, movable); + } = locals_live_across_suspend_points(tcx, read_only!(body), source, movable); // Erase regions from the types passed in from typeck so we can compare them with // MIR types @@ -769,7 +770,7 @@ fn compute_layout<'tcx>( _ => bug!(), }; - for (local, decl) in body_cache.local_decls.iter_enumerated() { + for (local, decl) in body.local_decls.iter_enumerated() { // Ignore locals which are internal or not live if !live_locals.contains(local) || decl.internal { continue; @@ -778,7 +779,7 @@ fn compute_layout<'tcx>( // Sanity check that typeck knows about the type of locals which are // live across a suspension point if !allowed.contains(&decl.ty) && !allowed_upvars.contains(&decl.ty) { - span_bug!(body_cache.span, + span_bug!(body.span, "Broken MIR: generator contains type {} in MIR, \ but typeck only knows about {}", decl.ty, @@ -791,7 +792,7 @@ fn compute_layout<'tcx>( let mut tys = IndexVec::::new(); for (idx, local) in live_locals.iter().enumerate() { locals.push(local); - tys.push(body_cache.local_decls[local].ty); + tys.push(body.local_decls[local].ty); debug!("generator saved local {:?} => {:?}", GeneratorSavedLocal::from(idx), local); } @@ -829,13 +830,13 @@ fn compute_layout<'tcx>( } fn insert_switch<'tcx>( - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, cases: Vec<(usize, BasicBlock)>, transform: &TransformVisitor<'tcx>, default: TerminatorKind<'tcx>, ) { - let default_block = insert_term_block(body_cache, default); - let (assign, discr) = transform.get_discr(body_cache); + let default_block = insert_term_block(body, default); + let (assign, discr) = transform.get_discr(body); let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), switch_ty: transform.discr_ty, @@ -843,8 +844,8 @@ fn insert_switch<'tcx>( targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(), }; - let source_info = source_info(body_cache); - body_cache.basic_blocks_mut().raw.insert(0, BasicBlockData { + let source_info = source_info(body); + body.basic_blocks_mut().raw.insert(0, BasicBlockData { statements: vec![assign], terminator: Some(Terminator { source_info, @@ -853,7 +854,7 @@ fn insert_switch<'tcx>( is_cleanup: false, }); - let blocks = body_cache.basic_blocks_mut().iter_mut(); + let blocks = body.basic_blocks_mut().iter_mut(); for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) { *target = BasicBlock::new(target.index() + 1); @@ -861,7 +862,7 @@ fn insert_switch<'tcx>( } fn elaborate_generator_drops<'tcx>( - tcx: TyCtxt<'tcx>, def_id: DefId, body_cache: &mut BodyCache<'tcx> + tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut BodyCache<'tcx> ) { use crate::util::elaborate_drops::{elaborate_drop, Unwind}; use crate::util::patch::MirPatch; @@ -875,13 +876,13 @@ fn elaborate_generator_drops<'tcx>( let gen = self_arg(); let mut elaborator = DropShimElaborator { - body: body_cache, - patch: MirPatch::new(body_cache), + body, + patch: MirPatch::new(body), tcx, param_env }; - for (block, block_data) in body_cache.basic_blocks().iter_enumerated() { + for (block, block_data) in body.basic_blocks().iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { Terminator { source_info, @@ -918,7 +919,7 @@ fn elaborate_generator_drops<'tcx>( block, ); } - elaborator.patch.apply(body_cache); + elaborator.patch.apply(body); } fn create_generator_drop_shim<'tcx>( @@ -927,23 +928,23 @@ fn create_generator_drop_shim<'tcx>( def_id: DefId, source: MirSource<'tcx>, gen_ty: Ty<'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, drop_clean: BasicBlock, ) -> BodyCache<'tcx> { - let mut body_cache = body_cache.clone(); + let mut body = body.clone(); - let source_info = source_info(&body_cache); + let source_info = source_info(&body); - let mut cases = create_cases(&mut body_cache, transform, |point| point.drop); + let mut cases = create_cases(&mut body, transform, |point| point.drop); cases.insert(0, (UNRESUMED, drop_clean)); // The returned state and the poisoned state fall through to the default // case which is just to return - insert_switch(&mut body_cache, cases, &transform, TerminatorKind::Return); + insert_switch(&mut body, cases, &transform, TerminatorKind::Return); - for block in body_cache.basic_blocks_mut() { + for block in body.basic_blocks_mut() { let kind = &mut block.terminator_mut().kind; if let TerminatorKind::GeneratorDrop = *kind { *kind = TerminatorKind::Return; @@ -951,7 +952,7 @@ fn create_generator_drop_shim<'tcx>( } // Replace the return variable - body_cache.local_decls[RETURN_PLACE] = LocalDecl { + body.local_decls[RETURN_PLACE] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_unit(), user_ty: UserTypeProjections::none(), @@ -961,10 +962,10 @@ fn create_generator_drop_shim<'tcx>( local_info: LocalInfo::Other }; - make_generator_state_argument_indirect(tcx, def_id, &mut body_cache); + make_generator_state_argument_indirect(tcx, def_id, &mut body); // Change the generator argument from &mut to *mut - body_cache.local_decls[self_arg()] = LocalDecl { + body.local_decls[self_arg()] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, @@ -978,29 +979,29 @@ fn create_generator_drop_shim<'tcx>( }; if tcx.sess.opts.debugging_opts.mir_emit_retag { // Alias tracking must know we changed the type - body_cache.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { + body.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement { source_info, kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())), }) } - no_landing_pads(tcx, &mut body_cache); + no_landing_pads(tcx, &mut body); // Make sure we remove dead blocks to remove // unrelated code from the resume part of the function - simplify::remove_dead_blocks(&mut body_cache); + simplify::remove_dead_blocks(&mut body); - dump_mir(tcx, None, "generator_drop", &0, source, &mut body_cache, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(()) ); - body_cache + body } fn insert_term_block<'tcx>( - body_cache: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx> + body: &mut BodyCache<'tcx>, kind: TerminatorKind<'tcx> ) -> BasicBlock { - let term_block = BasicBlock::new(body_cache.basic_blocks().len()); - let source_info = source_info(body_cache); - body_cache.basic_blocks_mut().push(BasicBlockData { + let term_block = BasicBlock::new(body.basic_blocks().len()); + let source_info = source_info(body); + body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, @@ -1013,13 +1014,13 @@ fn insert_term_block<'tcx>( fn insert_panic_block<'tcx>( tcx: TyCtxt<'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, message: AssertMessage<'tcx>, ) -> BasicBlock { - let assert_block = BasicBlock::new(body_cache.basic_blocks().len()); + let assert_block = BasicBlock::new(body.basic_blocks().len()); let term = TerminatorKind::Assert { cond: Operand::Constant(box Constant { - span: body_cache.span, + span: body.span, user_ty: None, literal: ty::Const::from_bool(tcx, false), }), @@ -1029,8 +1030,8 @@ fn insert_panic_block<'tcx>( cleanup: None, }; - let source_info = source_info(body_cache); - body_cache.basic_blocks_mut().push(BasicBlockData { + let source_info = source_info(body); + body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, @@ -1047,10 +1048,10 @@ fn create_generator_resume_function<'tcx>( transform: TransformVisitor<'tcx>, def_id: DefId, source: MirSource<'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, ) { // Poison the generator when it unwinds - for block in body_cache.basic_blocks_mut() { + for block in body.basic_blocks_mut() { let source_info = block.terminator().source_info; if let &TerminatorKind::Resume = &block.terminator().kind { block.statements.push( @@ -1058,7 +1059,7 @@ fn create_generator_resume_function<'tcx>( } } - let mut cases = create_cases(body_cache, &transform, |point| Some(point.resume)); + let mut cases = create_cases(body, &transform, |point| Some(point.resume)); use rustc::mir::interpret::PanicInfo::{ ResumedAfterPanic, @@ -1072,25 +1073,25 @@ fn create_generator_resume_function<'tcx>( let generator_kind = body.generator_kind.unwrap(); cases.insert(1, (RETURNED, insert_panic_block( tcx, - body_cache, + body, ResumedAfterReturn(generator_kind)))); cases.insert(2, (POISONED, insert_panic_block( tcx, - body_cache, + body, ResumedAfterPanic(generator_kind)))); - insert_switch(body_cache, cases, &transform, TerminatorKind::Unreachable); + insert_switch(body, cases, &transform, TerminatorKind::Unreachable); - make_generator_state_argument_indirect(tcx, def_id, body_cache); - make_generator_state_argument_pinned(tcx, body_cache); + make_generator_state_argument_indirect(tcx, def_id, body); + make_generator_state_argument_pinned(tcx, body); - no_landing_pads(tcx, body_cache); + no_landing_pads(tcx, body); // Make sure we remove dead blocks to remove // unrelated code from the drop part of the function - simplify::remove_dead_blocks(body_cache); + simplify::remove_dead_blocks(body); - dump_mir(tcx, None, "generator_resume", &0, source, body_cache, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()) ); } fn source_info(body: &Body<'_>) -> SourceInfo { @@ -1100,18 +1101,18 @@ fn source_info(body: &Body<'_>) -> SourceInfo { } } -fn insert_clean_drop(body_cache: &mut BodyCache<'_>) -> BasicBlock { - let return_block = insert_term_block(body_cache, TerminatorKind::Return); +fn insert_clean_drop(body: &mut BodyCache<'_>) -> BasicBlock { + let return_block = insert_term_block(body, TerminatorKind::Return); // Create a block to destroy an unresumed generators. This can only destroy upvars. - let drop_clean = BasicBlock::new(body_cache.basic_blocks().len()); + let drop_clean = BasicBlock::new(body.basic_blocks().len()); let term = TerminatorKind::Drop { location: Place::from(self_arg()), target: return_block, unwind: None, }; - let source_info = source_info(body_cache); - body_cache.basic_blocks_mut().push(BasicBlockData { + let source_info = source_info(body); + body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, @@ -1124,23 +1125,23 @@ fn insert_clean_drop(body_cache: &mut BodyCache<'_>) -> BasicBlock { } fn create_cases<'tcx, F>( - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, transform: &TransformVisitor<'tcx>, target: F, ) -> Vec<(usize, BasicBlock)> where F: Fn(&SuspensionPoint) -> Option, { - let source_info = source_info(body_cache); + let source_info = source_info(body); transform.suspension_points.iter().filter_map(|point| { // Find the target for this suspension point, if applicable target(point).map(|target| { - let block = BasicBlock::new(body_cache.basic_blocks().len()); + let block = BasicBlock::new(body.basic_blocks().len()); let mut statements = Vec::new(); // Create StorageLive instructions for locals with live storage - for i in 0..(body_cache.local_decls.len()) { + for i in 0..(body.local_decls.len()) { let l = Local::new(i); if point.storage_liveness.contains(l) && !transform.remap.contains_key(&l) { statements.push(Statement { @@ -1151,7 +1152,7 @@ where } // Then jump to the real target - body_cache.basic_blocks_mut().push(BasicBlockData { + body.basic_blocks_mut().push(BasicBlockData { statements, terminator: Some(Terminator { source_info, @@ -1169,21 +1170,21 @@ where impl<'tcx> MirPass<'tcx> for StateTransform { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { - let yield_ty = if let Some(yield_ty) = body_cache.yield_ty { + let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty } else { // This only applies to generators return }; - assert!(body_cache.generator_drop.is_none()); + assert!(body.generator_drop.is_none()); let def_id = source.def_id(); // The first argument is the generator type passed by value - let gen_ty = body_cache.local_decls.raw[1].ty; + let gen_ty = body.local_decls.raw[1].ty; // Get the interior types and substs which typeck computed let (upvars, interior, discr_ty, movable) = match gen_ty.kind { @@ -1202,13 +1203,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.intern_substs(&[ yield_ty.into(), - body_cache.return_ty().into(), + body.return_ty().into(), ]); let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local // RETURN_PLACE then is a fresh unused local with type ret_ty. - let new_ret_local = replace_result_variable(ret_ty, body_cache, tcx); + let new_ret_local = replace_result_variable(ret_ty, body, tcx); // Extract locals which are live across suspension point into `layout` // `remap` gives a mapping from local indices onto generator struct indices @@ -1219,7 +1220,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { &upvars, interior, movable, - body_cache); + body); // Run the transformation which converts Places from Local to generator struct // accesses for locals in `remap`. @@ -1235,27 +1236,27 @@ impl<'tcx> MirPass<'tcx> for StateTransform { new_ret_local, discr_ty, }; - transform.visit_body(body_cache); + transform.visit_body(body); // Update our MIR struct to reflect the changed we've made - body_cache.yield_ty = None; - body_cache.arg_count = 1; - body_cache.spread_arg = None; - body_cache.generator_layout = Some(layout); + body.yield_ty = None; + body.arg_count = 1; + body.spread_arg = None; + body.generator_layout = Some(layout); // Insert `drop(generator_struct)` which is used to drop upvars for generators in // the unresumed state. // This is expanded to a drop ladder in `elaborate_generator_drops`. - let drop_clean = insert_clean_drop(body_cache); + let drop_clean = insert_clean_drop(body); - dump_mir(tcx, None, "generator_pre-elab", &0, source, body_cache, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_pre-elab", &0, source, body, |_, _| 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, body_cache); + elaborate_generator_drops(tcx, def_id, body); - dump_mir(tcx, None, "generator_post-transform", &0, source, body_cache, |_, _| Ok(()) ); + dump_mir(tcx, None, "generator_post-transform", &0, source, body, |_, _| 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, @@ -1263,12 +1264,12 @@ impl<'tcx> MirPass<'tcx> for StateTransform { def_id, source, gen_ty, - body_cache, + body, drop_clean); - body_cache.generator_drop = Some(box drop_shim); + body.generator_drop = Some(box drop_shim); // Create the Generator::resume function - create_generator_resume_function(tcx, transform, def_id, source, body_cache); + create_generator_resume_function(tcx, transform, def_id, source, body); } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 922b0937065c4..79cb7fb0b7692 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -39,10 +39,10 @@ struct CallSite<'tcx> { impl<'tcx> MirPass<'tcx> for Inline { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - Inliner { tcx, source }.run_pass(body_cache); + Inliner { tcx, source }.run_pass(body); } } } @@ -53,7 +53,7 @@ struct Inliner<'tcx> { } impl Inliner<'tcx> { - fn run_pass(&self, caller_body_cache: &mut BodyCache<'tcx>) { + fn run_pass(&self, caller_body: &mut BodyCache<'tcx>) { // Keep a queue of callsites to try inlining on. We take // advantage of the fact that queries detect cycles here to // allow us to try and fetch the fully optimized MIR of a @@ -75,10 +75,10 @@ impl Inliner<'tcx> { if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() { - for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated() { + for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() { if let Some(callsite) = self.get_valid_function_call(bb, bb_data, - caller_body_cache, + caller_body, param_env) { callsites.push_back(callsite); } @@ -129,20 +129,20 @@ impl Inliner<'tcx> { continue; }; - let start = caller_body_cache.basic_blocks().len(); + let start = caller_body.basic_blocks().len(); debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body); - if !self.inline_call(callsite, caller_body_cache, callee_body) { + if !self.inline_call(callsite, caller_body, callee_body) { debug!("attempting to inline callsite {:?} - failure", callsite); continue; } debug!("attempting to inline callsite {:?} - success", callsite); // Add callsites from inlined function - for (bb, bb_data) in caller_body_cache.basic_blocks().iter_enumerated().skip(start) + for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated().skip(start) { if let Some(new_callsite) = self.get_valid_function_call(bb, bb_data, - caller_body_cache, + caller_body, param_env) { // Don't inline the same function multiple times. if callsite.callee != new_callsite.callee { @@ -163,8 +163,8 @@ impl Inliner<'tcx> { // Simplify if we inlined anything. if changed { debug!("running simplify cfg on {:?}", self.source); - CfgSimplifier::new(caller_body_cache).simplify(); - remove_dead_blocks(caller_body_cache); + CfgSimplifier::new(caller_body).simplify(); + remove_dead_blocks(caller_body); } } @@ -381,22 +381,22 @@ impl Inliner<'tcx> { fn inline_call(&self, callsite: CallSite<'tcx>, caller_body: &mut BodyCache<'tcx>, - mut callee_body_cache: BodyCache<'tcx>) -> bool { + mut callee_body: BodyCache<'tcx>) -> bool { let terminator = caller_body[callsite.bb].terminator.take().unwrap(); match terminator.kind { // FIXME: Handle inlining of diverging calls TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { debug!("inlined {:?} into {:?}", callsite.callee, self.source); - let mut local_map = IndexVec::with_capacity(callee_body_cache.local_decls.len()); - let mut scope_map = IndexVec::with_capacity(callee_body_cache.source_scopes.len()); + let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); + let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); - for mut scope in callee_body_cache.source_scopes.iter().cloned() { + for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { scope.parent_scope = Some(callsite.location.scope); // FIXME(eddyb) is this really needed? // (also note that it's always overwritten below) - scope.span = callee_body_cache.span; + scope.span = callee_body.span; } // FIXME(eddyb) this doesn't seem right at all. @@ -408,8 +408,8 @@ impl Inliner<'tcx> { scope_map.push(idx); } - for loc in callee_body_cache.vars_and_temps_iter() { - let mut local = callee_body_cache.local_decls[loc].clone(); + for loc in callee_body.vars_and_temps_iter() { + let mut local = callee_body.local_decls[loc].clone(); local.source_info.scope = scope_map[local.source_info.scope]; @@ -448,7 +448,7 @@ impl Inliner<'tcx> { BorrowKind::Mut { allow_two_phase_borrow: false }, destination.0); - let ty = dest.ty(caller_body, self.tcx); + let ty = dest.ty(&**caller_body, self.tcx); let temp = LocalDecl::new_temp(ty, callsite.location.span); @@ -489,7 +489,7 @@ impl Inliner<'tcx> { caller_body.var_debug_info.push(var_debug_info); } - for (bb, mut block) in callee_body_cache.basic_blocks_mut().drain_enumerated(..) { + for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) { integrator.visit_basic_block_data(bb, &mut block); caller_body.basic_blocks_mut().push(block); } @@ -517,7 +517,7 @@ impl Inliner<'tcx> { &self, args: Vec>, callsite: &CallSite<'tcx>, - caller_body_cache: &mut BodyCache<'tcx>, + caller_body: &mut BodyCache<'tcx>, ) -> Vec { let tcx = self.tcx; @@ -547,13 +547,13 @@ impl Inliner<'tcx> { if tcx.is_closure(callsite.callee) { let mut args = args.into_iter(); let self_ - = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); + = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); let tuple - = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body_cache); + = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); assert!(args.next().is_none()); let tuple = Place::from(tuple); - let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body_cache, tcx).ty.kind { + let tuple_tys = if let ty::Tuple(s) = tuple.ty(&**caller_body, tcx).ty.kind { s } else { bug!("Closure arguments are not passed as a tuple"); @@ -573,13 +573,13 @@ impl Inliner<'tcx> { )); // Spill to a local to make e.g., `tmp0`. - self.create_temp_if_necessary(tuple_field, callsite, caller_body_cache) + self.create_temp_if_necessary(tuple_field, callsite, caller_body) }); closure_ref_arg.chain(tuple_tmp_args).collect() } else { args.into_iter() - .map(|a| self.create_temp_if_necessary(a, callsite, caller_body_cache)) + .map(|a| self.create_temp_if_necessary(a, callsite, caller_body)) .collect() } } @@ -590,14 +590,14 @@ impl Inliner<'tcx> { &self, arg: Operand<'tcx>, callsite: &CallSite<'tcx>, - caller_body_cache: &mut BodyCache<'tcx>, + caller_body: &mut BodyCache<'tcx>, ) -> Local { // FIXME: Analysis of the usage of the arguments to avoid // unnecessary temporaries. if let Operand::Move(place) = &arg { if let Some(local) = place.as_local() { - if caller_body_cache.local_kind(local) == LocalKind::Temp { + if caller_body.local_kind(local) == LocalKind::Temp { // Reuse the operand if it's a temporary already return local; } @@ -608,16 +608,16 @@ impl Inliner<'tcx> { // Otherwise, create a temporary for the arg let arg = Rvalue::Use(arg); - let ty = arg.ty(caller_body_cache, self.tcx); + let ty = arg.ty(&**caller_body, self.tcx); let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span); - let arg_tmp = caller_body_cache.local_decls.push(arg_tmp); + let arg_tmp = caller_body.local_decls.push(arg_tmp); let stmt = Statement { source_info: callsite.location, kind: StatementKind::Assign(box(Place::from(arg_tmp), arg)), }; - caller_body_cache[callsite.bb].statements.push(stmt); + caller_body[callsite.bb].statements.push(stmt); arg_tmp } } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index d8c5c2e0bcab4..bd237b5813298 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -14,7 +14,7 @@ use crate::transform::{MirPass, MirSource}; pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return @@ -24,14 +24,14 @@ impl<'tcx> MirPass<'tcx> for InstCombine { // read-only so that we can do global analyses on the MIR in the process (e.g. // `Place::ty()`). let optimizations = { - let read_only_cache = read_only!(body_cache); - let mut optimization_finder = OptimizationFinder::new(body_cache, tcx); + let read_only_cache = read_only!(body); + let mut optimization_finder = OptimizationFinder::new(body, tcx); optimization_finder.visit_body(read_only_cache); optimization_finder.optimizations }; // Then carry out those optimizations. - MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body_cache); + MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body); } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 1265a1a838624..05d9787531b2a 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -224,14 +224,14 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { // Unsafety check uses the raw mir, so make sure it is run let _ = tcx.unsafety_check_result(def_id); - let mut body_cache = tcx.mir_built(def_id).steal(); - run_passes(tcx, &mut body_cache, InstanceDef::Item(def_id), None, MirPhase::Const, &[ + let mut body = tcx.mir_built(def_id).steal(); + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Const, &[ // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, &uniform_array_move_out::UniformArrayMoveOut, ]); - tcx.alloc_steal_mir(body_cache) + tcx.alloc_steal_mir(body) } fn mir_validated( @@ -242,25 +242,25 @@ fn mir_validated( // this point, before we steal the mir-const result. let _ = tcx.mir_const_qualif(def_id); - let mut body_cache = tcx.mir_const(def_id).steal(); + let mut body = tcx.mir_const(def_id).steal(); let promote_pass = promote_consts::PromoteTemps::default(); - run_passes(tcx, &mut body_cache, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ // What we need to run borrowck etc. &promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); let promoted = promote_pass.promoted_fragments.into_inner(); - (tcx.alloc_steal_mir(body_cache), tcx.alloc_steal_promoted(promoted)) + (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } fn run_optimization_passes<'tcx>( tcx: TyCtxt<'tcx>, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, def_id: DefId, promoted: Option, ) { - run_passes(tcx, body_cache, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ + run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads::new(tcx), &simplify_branches::SimplifyBranches::new("initial"), @@ -332,10 +332,10 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyCache<'_> { tcx.ensure().mir_borrowck(def_id); let (body, _) = tcx.mir_validated(def_id); - let mut body_cache = body.steal(); - run_optimization_passes(tcx, &mut body_cache, def_id, None); - body_cache.ensure_predecessors(); - tcx.arena.alloc(body_cache) + let mut body = body.steal(); + run_optimization_passes(tcx, &mut body, def_id, None); + body.ensure_predecessors(); + tcx.arena.alloc(body) } fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec> { @@ -347,9 +347,9 @@ fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec NoLandingPads<'tcx> { } impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - no_landing_pads(tcx, body_cache) + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + no_landing_pads(tcx, body) } } -pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) { +pub fn no_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) { if tcx.sess.no_landing_pads() { - NoLandingPads::new(tcx).visit_body(body_cache); + NoLandingPads::new(tcx).visit_body(body); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 3b4b50c657be2..3a24f4a9fb1a4 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -770,8 +770,8 @@ pub fn validate_candidates( struct Promoter<'a, 'tcx> { tcx: TyCtxt<'tcx>, - source_cache: &'a mut BodyCache<'tcx>, - promoted_cache: BodyCache<'tcx>, + source: &'a mut BodyCache<'tcx>, + promoted: BodyCache<'tcx>, temps: &'a mut IndexVec, /// If true, all nested temps are also kept in the @@ -781,8 +781,8 @@ struct Promoter<'a, 'tcx> { impl<'a, 'tcx> Promoter<'a, 'tcx> { fn new_block(&mut self) -> BasicBlock { - let span = self.promoted_cache.span; - self.promoted_cache.basic_blocks_mut().push(BasicBlockData { + let span = self.promoted.span; + self.promoted.basic_blocks_mut().push(BasicBlockData { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo { @@ -796,8 +796,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) { - let last = self.promoted_cache.basic_blocks().last().unwrap(); - let data = &mut self.promoted_cache[last]; + let last = self.promoted.basic_blocks().last().unwrap(); + let data = &mut self.promoted[last]; data.statements.push(Statement { source_info: SourceInfo { span, @@ -808,7 +808,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn is_temp_kind(&self, local: Local) -> bool { - self.source_cache.local_kind(local) == LocalKind::Temp + self.source.local_kind(local) == LocalKind::Temp } /// Copies the initialization of this temp to the @@ -823,7 +823,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { location } state => { - span_bug!(self.promoted_cache.span, "{:?} not promotable: {:?}", + span_bug!(self.promoted.span, "{:?} not promotable: {:?}", temp, state); } }; @@ -831,10 +831,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.temps[temp] = TempState::PromotedOut; } - let num_stmts = self.source_cache[loc.block].statements.len(); - let new_temp = self.promoted_cache.local_decls.push( - LocalDecl::new_temp(self.source_cache.local_decls[temp].ty, - self.source_cache.local_decls[temp].source_info.span)); + let num_stmts = self.source[loc.block].statements.len(); + let new_temp = self.promoted.local_decls.push( + LocalDecl::new_temp(self.source.local_decls[temp].ty, + self.source.local_decls[temp].source_info.span)); debug!("promote({:?} @ {:?}/{:?}, {:?})", temp, loc, num_stmts, self.keep_original); @@ -843,7 +843,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // or duplicate it, depending on keep_original. if loc.statement_index < num_stmts { let (mut rvalue, source_info) = { - let statement = &mut self.source_cache[loc.block].statements[loc.statement_index]; + let statement = &mut self.source[loc.block].statements[loc.statement_index]; let rhs = match statement.kind { StatementKind::Assign(box(_, ref mut rhs)) => rhs, _ => { @@ -864,9 +864,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.assign(new_temp, rvalue, source_info.span); } else { let terminator = if self.keep_original { - self.source_cache[loc.block].terminator().clone() + self.source[loc.block].terminator().clone() } else { - let terminator = self.source_cache[loc.block].terminator_mut(); + let terminator = self.source[loc.block].terminator_mut(); let target = match terminator.kind { TerminatorKind::Call { destination: Some((_, target)), .. } => target, ref kind => { @@ -888,10 +888,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.visit_operand(arg, loc); } - let last = self.promoted_cache.basic_blocks().last().unwrap(); + let last = self.promoted.basic_blocks().last().unwrap(); let new_target = self.new_block(); - *self.promoted_cache[last].terminator_mut() = Terminator { + *self.promoted[last].terminator_mut() = Terminator { kind: TerminatorKind::Call { func, args, @@ -921,7 +921,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { next_promoted_id: usize, ) -> Option> { let mut operand = { - let promoted = &mut self.promoted_cache; + let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); let tcx = self.tcx; let mut promoted_place = |ty, span| { @@ -940,7 +940,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { projection: List::empty(), } }; - let (blocks, local_decls) = self.source_cache.basic_blocks_and_local_decls_mut(); + let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); match candidate { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; @@ -1004,9 +1004,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { statement_index: usize::MAX }); - let span = self.promoted_cache.span; + let span = self.promoted.span; self.assign(RETURN_PLACE, Rvalue::Use(operand), span); - Some(self.promoted_cache) + Some(self.promoted) } } @@ -1040,7 +1040,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { pub fn promote_candidates<'tcx>( def_id: DefId, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, tcx: TyCtxt<'tcx>, mut temps: IndexVec, candidates: Vec, @@ -1054,7 +1054,7 @@ pub fn promote_candidates<'tcx>( match candidate { Candidate::Repeat(Location { block, statement_index }) | Candidate::Ref(Location { block, statement_index }) => { - match &body_cache[block].statements[statement_index].kind { + match &body[block].statements[statement_index].kind { StatementKind::Assign(box(place, _)) => { if let Some(local) = place.as_local() { if temps[local] == TempState::PromotedOut { @@ -1072,26 +1072,26 @@ pub fn promote_candidates<'tcx>( // Declare return place local so that `mir::Body::new` doesn't complain. let initial_locals = iter::once( - LocalDecl::new_return_place(tcx.types.never, body_cache.span) + LocalDecl::new_return_place(tcx.types.never, body.span) ).collect(); let promoter = Promoter { - promoted_cache: BodyCache::new(Body::new( + promoted: BodyCache::new(Body::new( IndexVec::new(), // FIXME: maybe try to filter this to avoid blowing up // memory usage? - body_cache.source_scopes.clone(), - body_cache.source_scope_local_data.clone(), + body.source_scopes.clone(), + body.source_scope_local_data.clone(), initial_locals, IndexVec::new(), 0, vec![], - body_cache.span, + body.span, vec![], - body_cache.generator_kind, + body.generator_kind, )), tcx, - source_cache: body_cache, + source: body, temps: &mut temps, keep_original: false }; @@ -1104,7 +1104,7 @@ pub fn promote_candidates<'tcx>( // Eliminate assignments to, and drops of promoted temps. let promoted = |index: Local| temps[index] == TempState::PromotedOut; - for block in body_cache.basic_blocks_mut() { + for block in body.basic_blocks_mut() { block.statements.retain(|statement| { match &statement.kind { StatementKind::Assign(box(place, _)) => { diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 386e04bc0839a..c636aba9fc607 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -9,18 +9,18 @@ use crate::util::patch::MirPatch; /// code for these. pub struct RemoveNoopLandingPads; -pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body_cache: &mut BodyCache<'tcx>) { +pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyCache<'tcx>) { if tcx.sess.no_landing_pads() { return } - debug!("remove_noop_landing_pads({:?})", body_cache); + debug!("remove_noop_landing_pads({:?})", body); - RemoveNoopLandingPads.remove_nop_landing_pads(body_cache) + RemoveNoopLandingPads.remove_nop_landing_pads(body) } impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - remove_noop_landing_pads(tcx, body_cache); + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + remove_noop_landing_pads(tcx, body); } } @@ -84,26 +84,26 @@ impl RemoveNoopLandingPads { } } - fn remove_nop_landing_pads(&self, body_cache: &mut BodyCache<'_>) { + fn remove_nop_landing_pads(&self, body: &mut BodyCache<'_>) { // make sure there's a single resume block let resume_block = { - let patch = MirPatch::new(body_cache); + let patch = MirPatch::new(body); let resume_block = patch.resume_block(); - patch.apply(body_cache); + patch.apply(body); resume_block }; debug!("remove_noop_landing_pads: resume block is {:?}", resume_block); let mut jumps_folded = 0; let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitSet::new_empty(body_cache.basic_blocks().len()); + let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks().len()); // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. - let postorder: Vec<_> = traversal::postorder(body_cache).map(|(bb, _)| bb).collect(); + let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); for bb in postorder { debug!(" processing {:?}", bb); - for target in body_cache[bb].terminator_mut().successors_mut() { + for target in body[bb].terminator_mut().successors_mut() { if *target != resume_block && nop_landing_pads.contains(*target) { debug!(" folding noop jump to {:?} to resume block", target); *target = resume_block; @@ -111,7 +111,7 @@ impl RemoveNoopLandingPads { } } - match body_cache[bb].terminator_mut().unwind_mut() { + match body[bb].terminator_mut().unwind_mut() { Some(unwind) => { if *unwind == Some(resume_block) { debug!(" removing noop landing pad"); @@ -123,7 +123,7 @@ impl RemoveNoopLandingPads { _ => {} } - let is_nop_landing_pad = self.is_nop_landing_pad(bb, body_cache, &nop_landing_pads); + let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); if is_nop_landing_pad { nop_landing_pads.insert(bb); } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index de8a8ceed311a..794ced1cb0ef5 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -26,7 +26,7 @@ use crate::dataflow::has_rustc_mir_with; pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -37,36 +37,36 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(body_cache, tcx).unwrap(); + let move_data = MoveData::gather_moves(body, tcx).unwrap(); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = BitSet::new_empty(body_cache.basic_blocks().len()); + let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); let flow_inits = - do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, - MaybeInitializedPlaces::new(tcx, body_cache, &mdpe), + do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, + MaybeInitializedPlaces::new(tcx, body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_uninits = - do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, - MaybeUninitializedPlaces::new(tcx, body_cache, &mdpe), + do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, + MaybeUninitializedPlaces::new(tcx, body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_def_inits = - do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, - DefinitelyInitializedPlaces::new(tcx, body_cache, &mdpe), + do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, + DefinitelyInitializedPlaces::new(tcx, body, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_indirectly_mut = - do_dataflow(tcx, body_cache, def_id, &attributes, &dead_unwinds, - IndirectlyMutableLocals::new(tcx, body_cache, param_env), + do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds, + IndirectlyMutableLocals::new(tcx, body, param_env), |_, i| DebugFormatted::new(&i)); if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() { - sanity_check_via_rustc_peek(tcx, body_cache, def_id, &attributes, &flow_inits); + sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_inits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_uninit).is_some() { - sanity_check_via_rustc_peek(tcx, body_cache, def_id, &attributes, &flow_uninits); + sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_uninits); } if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { sanity_check_via_rustc_peek( tcx, - body_cache, + body, def_id, &attributes, &flow_def_inits); @@ -74,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() { sanity_check_via_rustc_peek( tcx, - body_cache, + body, def_id, &attributes, &flow_indirectly_mut); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 3057d67f9ef57..900752d3ce06c 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -43,12 +43,12 @@ impl SimplifyCfg { } } -pub fn simplify_cfg(body_cache: &mut BodyCache<'_>) { - CfgSimplifier::new(body_cache).simplify(); - remove_dead_blocks(body_cache); +pub fn simplify_cfg(body: &mut BodyCache<'_>) { + CfgSimplifier::new(body).simplify(); + remove_dead_blocks(body); // FIXME: Should probably be moved into some kind of pass manager - body_cache.basic_blocks_mut().raw.shrink_to_fit(); + body.basic_blocks_mut().raw.shrink_to_fit(); } impl<'tcx> MirPass<'tcx> for SimplifyCfg { @@ -57,10 +57,10 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { } fn run_pass( - &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { - debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body_cache); - simplify_cfg(body_cache); + debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); + simplify_cfg(body); } } @@ -70,14 +70,14 @@ pub struct CfgSimplifier<'a, 'tcx> { } impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { - pub fn new(body_cache: &'a mut BodyCache<'tcx>) -> Self { - let mut pred_count = IndexVec::from_elem(0u32, body_cache.basic_blocks()); + pub fn new(body: &'a mut BodyCache<'tcx>) -> Self { + let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks()); // we can't use mir.predecessors() here because that counts // dead blocks, which we don't want to. pred_count[START_BLOCK] = 1; - for (_, data) in traversal::preorder(body_cache) { + for (_, data) in traversal::preorder(body) { if let Some(ref term) = data.terminator { for &tgt in term.successors() { pred_count[tgt] += 1; @@ -85,7 +85,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } - let basic_blocks = body_cache.basic_blocks_mut(); + let basic_blocks = body.basic_blocks_mut(); CfgSimplifier { basic_blocks, @@ -262,13 +262,13 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } -pub fn remove_dead_blocks(body_cache: &mut BodyCache<'_>) { - let mut seen = BitSet::new_empty(body_cache.basic_blocks().len()); - for (bb, _) in traversal::preorder(body_cache) { +pub fn remove_dead_blocks(body: &mut BodyCache<'_>) { + let mut seen = BitSet::new_empty(body.basic_blocks().len()); + for (bb, _) in traversal::preorder(body) { seen.insert(bb.index()); } - let basic_blocks = body_cache.basic_blocks_mut(); + let basic_blocks = body.basic_blocks_mut(); let num_blocks = basic_blocks.len(); let mut replacements : Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); @@ -296,29 +296,29 @@ pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { fn run_pass( - &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx> + &self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx> ) { trace!("running SimplifyLocals on {:?}", source); let locals = { - let read_only_cache = read_only!(body_cache); + let read_only_cache = read_only!(body); let mut marker = DeclMarker { - locals: BitSet::new_empty(body_cache.local_decls.len()), - body: body_cache, + locals: BitSet::new_empty(body.local_decls.len()), + body, }; marker.visit_body(read_only_cache); // Return pointer and arguments are always live marker.locals.insert(RETURN_PLACE); - for arg in body_cache.args_iter() { + for arg in body.args_iter() { marker.locals.insert(arg); } marker.locals }; - let map = make_local_map(&mut body_cache.local_decls, locals); + let map = make_local_map(&mut body.local_decls, locals); // Update references to all vars and tmps now - LocalUpdater { map, tcx }.visit_body(body_cache); - body_cache.local_decls.shrink_to_fit(); + LocalUpdater { map, tcx }.visit_body(body); + body.local_decls.shrink_to_fit(); } } diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index df5d40484bf28..c8d0f37f9a509 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -19,9 +19,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { Cow::Borrowed(&self.label) } - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { let param_env = tcx.param_env(src.def_id()); - for block in body_cache.basic_blocks_mut() { + for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { TerminatorKind::SwitchInt { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index d4d24347f726c..3fc76ef6b00e0 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -37,16 +37,16 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - let mut patch = MirPatch::new(body_cache); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { - let read_only_cache = read_only!(body_cache); + let read_only_cache = read_only!(body); let mut visitor - = UniformArrayMoveOutVisitor{ body: body_cache, patch: &mut patch, tcx, param_env}; + = UniformArrayMoveOutVisitor{ body, patch: &mut patch, tcx, param_env}; visitor.visit_body(read_only_cache); } - patch.apply(body_cache); + patch.apply(body); } } @@ -186,19 +186,19 @@ pub struct RestoreSubsliceArrayMoveOut<'tcx> { } impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body_cache: &mut BodyCache<'tcx>) { - let mut patch = MirPatch::new(body_cache); + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { + let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { - let read_only_cache = read_only!(body_cache); + let read_only_cache = read_only!(body); let mut visitor = RestoreDataCollector { - locals_use: IndexVec::from_elem(LocalUse::new(), &body_cache.local_decls), + locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls), candidates: vec![], }; visitor.visit_body(read_only_cache); for candidate in &visitor.candidates { - let statement = &body_cache[candidate.block].statements[candidate.statement_index]; + let statement = &body[candidate.block].statements[candidate.statement_index]; if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind { if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval { let items : Vec<_> = items.iter().map(|item| { @@ -206,7 +206,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { if let Some(local) = place.as_local() { let local_use = &visitor.locals_use[local]; let opt_index_and_place = - Self::try_get_item_source(local_use, body_cache); + Self::try_get_item_source(local_use, body); // each local should be used twice: // in assign and in aggregate statements if local_use.use_count == 2 && opt_index_and_place.is_some() { @@ -223,7 +223,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { let src_ty = Place::ty_from( src_place.base, src_place.projection, - body_cache, + &**body, tcx ).ty; if let ty::Array(_, ref size_o) = src_ty.kind { @@ -239,7 +239,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut<'tcx> { } } } - patch.apply(body_cache); + patch.apply(body); } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 256ba94af44d2..632e92d67200a 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -30,7 +30,7 @@ impl DefUseAnalysis { } } - pub fn analyze(&mut self, body_cache: ReadOnlyBodyCache<'_, '_>) { + pub fn analyze(&mut self, body: ReadOnlyBodyCache<'_, '_>) { self.clear(); let mut finder = DefUseFinder { @@ -38,7 +38,7 @@ impl DefUseAnalysis { var_debug_info_index: 0, in_var_debug_info: false, }; - finder.visit_body(body_cache); + finder.visit_body(body); self.info = finder.info } @@ -55,7 +55,7 @@ impl DefUseAnalysis { fn mutate_defs_and_uses( &self, local: Local, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, new_local: Local, tcx: TyCtxt<'tcx>, ) { @@ -66,17 +66,17 @@ impl DefUseAnalysis { } // Update debuginfo as well, alongside defs/uses. for &i in &info.var_debug_info_indices { - visitor.visit_var_debug_info(&mut body_cache.var_debug_info[i]); + visitor.visit_var_debug_info(&mut body.var_debug_info[i]); } } // FIXME(pcwalton): this should update the def-use chains. pub fn replace_all_defs_and_uses_with(&self, local: Local, - body_cache: &mut BodyCache<'tcx>, + body: &mut BodyCache<'tcx>, new_local: Local, tcx: TyCtxt<'tcx>) { - self.mutate_defs_and_uses(local, body_cache, new_local, tcx) + self.mutate_defs_and_uses(local, body, new_local, tcx) } } diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 56a31337a0860..334975373e5f3 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -57,17 +57,17 @@ pub struct LivenessResult { /// Computes which local variables are live within the given function /// `mir`, including drops. pub fn liveness_of_locals( - body_cache: ReadOnlyBodyCache<'_, '_>, + body: ReadOnlyBodyCache<'_, '_>, ) -> LivenessResult { - let num_live_vars = body_cache.local_decls.len(); + let num_live_vars = body.local_decls.len(); - let def_use: IndexVec<_, DefsUses> = body_cache + let def_use: IndexVec<_, DefsUses> = body .basic_blocks() .iter() .map(|b| block(b, num_live_vars)) .collect(); - let mut outs: IndexVec<_, LiveVarSet> = body_cache + let mut outs: IndexVec<_, LiveVarSet> = body .basic_blocks() .indices() .map(|_| LiveVarSet::new_empty(num_live_vars)) @@ -84,18 +84,18 @@ pub fn liveness_of_locals( // order when cycles are present, but the overhead of computing the reverse CFG may outweigh // any benefits. Benchmark this and find out. let mut dirty_queue: WorkQueue - = WorkQueue::with_none(body_cache.basic_blocks().len()); - for (bb, _) in traversal::postorder(&body_cache) { + = WorkQueue::with_none(body.basic_blocks().len()); + for (bb, _) in traversal::postorder(&body) { dirty_queue.insert(bb); } // Add blocks which are not reachable from START_BLOCK to the work queue. These blocks will // be processed after the ones added above. - for bb in body_cache.basic_blocks().indices() { + for bb in body.basic_blocks().indices() { dirty_queue.insert(bb); } - let predecessors = body_cache.predecessors(); + let predecessors = body.predecessors(); while let Some(bb) = dirty_queue.pop() { // bits = use ∪ (bits - def) diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 6e110b1177f14..47bb0b699c048 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -127,21 +127,21 @@ impl<'tcx> MirPatch<'tcx> { self.make_nop.push(loc); } - pub fn apply(self, body_cache: &mut BodyCache<'tcx>) { + pub fn apply(self, body: &mut BodyCache<'tcx>) { debug!("MirPatch: make nops at: {:?}", self.make_nop); for loc in self.make_nop { - body_cache.make_statement_nop(loc); + body.make_statement_nop(loc); } debug!("MirPatch: {:?} new temps, starting from index {}: {:?}", - self.new_locals.len(), body_cache.local_decls.len(), self.new_locals); + self.new_locals.len(), body.local_decls.len(), self.new_locals); debug!("MirPatch: {} new blocks, starting from index {}", - self.new_blocks.len(), body_cache.basic_blocks().len()); - body_cache.basic_blocks_mut().extend(self.new_blocks); - body_cache.local_decls.extend(self.new_locals); + self.new_blocks.len(), body.basic_blocks().len()); + body.basic_blocks_mut().extend(self.new_blocks); + body.local_decls.extend(self.new_locals); for (src, patch) in self.patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); - body_cache[src].terminator_mut().kind = patch; + body[src].terminator_mut().kind = patch; } } @@ -159,9 +159,9 @@ impl<'tcx> MirPatch<'tcx> { stmt, loc, delta); loc.statement_index += delta; let source_info = Self::source_info_for_index( - &body_cache[loc.block], loc + &body[loc.block], loc ); - body_cache[loc.block].statements.insert( + body[loc.block].statements.insert( loc.statement_index, Statement { source_info, kind: stmt From 51b06656da0106c254466429fa1f9d58bc74ea72 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 6 Nov 2019 12:29:09 -0500 Subject: [PATCH 36/47] Fix typos caused during rebase --- src/librustc_codegen_ssa/mir/block.rs | 4 +- src/librustc_codegen_ssa/mir/block.rs.orig | 1257 ++++++++++++++++++++ src/librustc_codegen_ssa/mir/mod.rs.orig | 439 +++++++ 3 files changed, 1698 insertions(+), 2 deletions(-) create mode 100644 src/librustc_codegen_ssa/mir/block.rs.orig create mode 100644 src/librustc_codegen_ssa/mir/mod.rs.orig diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ce59bf1d61d8b..23a5b0cf32ac2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -362,7 +362,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.do_call(self, &mut bx, fn_ty, drop_fn, args, + helper.do_call(self, &mut bx, fn_abi, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); } @@ -779,7 +779,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some((_, target)) = destination.as_ref() { helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); } - helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, + helper.do_call(self, &mut bx, fn_abi, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), cleanup); } diff --git a/src/librustc_codegen_ssa/mir/block.rs.orig b/src/librustc_codegen_ssa/mir/block.rs.orig new file mode 100644 index 0000000000000..d715a4e0e09c5 --- /dev/null +++ b/src/librustc_codegen_ssa/mir/block.rs.orig @@ -0,0 +1,1257 @@ +use rustc_index::vec::Idx; +use rustc::middle::lang_items; +use rustc::ty::{self, Ty, TypeFoldable, Instance}; +use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnAbiExt}; +use rustc::mir::{self, PlaceBase, Static, StaticKind}; +use rustc::mir::interpret::PanicInfo; +use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::spec::abi::Abi; +use crate::base; +use crate::MemFlags; +use crate::common::{self, IntPredicate}; +use crate::meth; + +use crate::traits::*; + +use std::borrow::Cow; + +use syntax::{source_map::Span, symbol::Symbol}; + +use super::{FunctionCx, LocalRef}; +use super::place::PlaceRef; +use super::operand::OperandRef; +use super::operand::OperandValue::{Pair, Ref, Immediate}; + +/// Used by `FunctionCx::codegen_terminator` for emitting common patterns +/// e.g., creating a basic block, calling a function, etc. +struct TerminatorCodegenHelper<'a, 'tcx> { + bb: &'a mir::BasicBlock, + terminator: &'a mir::Terminator<'tcx>, + funclet_bb: Option, +} + +impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { + /// Returns the associated funclet from `FunctionCx::funclets` for the + /// `funclet_bb` member if it is not `None`. + fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + &self, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + ) -> Option<&'c Bx::Funclet> { + match self.funclet_bb { + Some(funcl) => fx.funclets[funcl].as_ref(), + None => None, + } + } + + fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( + &self, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + target: mir::BasicBlock, + ) -> (Bx::BasicBlock, bool) { + let span = self.terminator.source_info.span; + let lltarget = fx.blocks[target]; + let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); + match (self.funclet_bb, target_funclet) { + (None, None) => (lltarget, false), + (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => + (lltarget, false), + // jump *into* cleanup - need a landing pad if GNU + (None, Some(_)) => (fx.landing_pad_to(target), false), + (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), + (Some(_), Some(_)) => (fx.landing_pad_to(target), true), + } + } + + /// Create a basic block. + fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + &self, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + target: mir::BasicBlock, + ) -> Bx::BasicBlock { + let (lltarget, is_cleanupret) = self.lltarget(fx, target); + if is_cleanupret { + // MSVC cross-funclet jump - need a trampoline + + debug!("llblock: creating cleanup trampoline for {:?}", target); + let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); + let mut trampoline = fx.new_block(name); + trampoline.cleanup_ret(self.funclet(fx).unwrap(), + Some(lltarget)); + trampoline.llbb() + } else { + lltarget + } + } + + fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + &self, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + bx: &mut Bx, + target: mir::BasicBlock, + ) { + let (lltarget, is_cleanupret) = self.lltarget(fx, target); + if is_cleanupret { + // micro-optimization: generate a `ret` rather than a jump + // to a trampoline. + bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); + } else { + bx.br(lltarget); + } + } + + /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional + /// return destination `destination` and the cleanup function `cleanup`. + fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + &self, + fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + bx: &mut Bx, + fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_ptr: Bx::Value, + llargs: &[Bx::Value], + destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, + cleanup: Option, + ) { + if let Some(cleanup) = cleanup { + let ret_bx = if let Some((_, target)) = destination { + fx.blocks[target] + } else { + fx.unreachable_block() + }; + let invokeret = bx.invoke(fn_ptr, + &llargs, + ret_bx, + self.llblock(fx, cleanup), + self.funclet(fx)); + bx.apply_attrs_callsite(&fn_abi, invokeret); + + if let Some((ret_dest, target)) = destination { + let mut ret_bx = fx.build_block(target); + fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); + fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); + } + } else { + let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); + bx.apply_attrs_callsite(&fn_abi, llret); + if fx.mir[*self.bb].is_cleanup { + // Cleanup is always the cold path. Don't inline + // drop glue. Also, when there is a deeply-nested + // struct, there are "symmetry" issues that cause + // exponential inlining - see issue #41696. + bx.do_not_inline(llret); + } + + if let Some((ret_dest, target)) = destination { + fx.store_return(bx, ret_dest, &fn_abi.ret, llret); + self.funclet_br(fx, bx, target); + } else { + bx.unreachable(); + } + } + } + + // Generate sideeffect intrinsic if jumping to any of the targets can form + // a loop. + fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( + &self, + mir: mir::ReadOnlyBodyCache<'b, 'tcx>, + bx: &mut Bx, + targets: &[mir::BasicBlock], + ) { + if bx.tcx().sess.opts.debugging_opts.insert_sideeffect { + if targets.iter().any(|target| { + *target <= *self.bb + && target + .start_location() + .is_predecessor_of(self.bb.start_location(), mir) + }) { + bx.sideeffect(); + } + } + } +} + +/// Codegen implementations for some terminator variants. +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + /// Generates code for a `Resume` terminator. + fn codegen_resume_terminator<'b>( + &mut self, + helper: TerminatorCodegenHelper<'b, 'tcx>, + mut bx: Bx, + ) { + if let Some(funclet) = helper.funclet(self) { + bx.cleanup_ret(funclet, None); + } else { + let slot = self.get_personality_slot(&mut bx); + let lp0 = slot.project_field(&mut bx, 0); + let lp0 = bx.load_operand(lp0).immediate(); + let lp1 = slot.project_field(&mut bx, 1); + let lp1 = bx.load_operand(lp1).immediate(); + slot.storage_dead(&mut bx); + + if !bx.sess().target.target.options.custom_unwind_resume { + let mut lp = bx.const_undef(self.landing_pad_type()); + lp = bx.insert_value(lp, lp0, 0); + lp = bx.insert_value(lp, lp1, 1); + bx.resume(lp); + } else { + bx.call(bx.eh_unwind_resume(), &[lp0], + helper.funclet(self)); + bx.unreachable(); + } + } + } + + fn codegen_switchint_terminator<'b>( + &mut self, + helper: TerminatorCodegenHelper<'b, 'tcx>, + mut bx: Bx, + discr: &mir::Operand<'tcx>, + switch_ty: Ty<'tcx>, + values: &Cow<'tcx, [u128]>, + targets: &Vec, + ) { + let discr = self.codegen_operand(&mut bx, &discr); + if targets.len() == 2 { + // If there are two targets, emit br instead of switch + let lltrue = helper.llblock(self, targets[0]); + let llfalse = helper.llblock(self, targets[1]); + if switch_ty == bx.tcx().types.bool { + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + // Don't generate trivial icmps when switching on bool + if let [0] = values[..] { + bx.cond_br(discr.immediate(), llfalse, lltrue); + } else { + assert_eq!(&values[..], &[1]); + bx.cond_br(discr.immediate(), lltrue, llfalse); + } + } else { + let switch_llty = bx.immediate_backend_type( + bx.layout_of(switch_ty) + ); + let llval = bx.const_uint_big(switch_llty, values[0]); + let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + bx.cond_br(cmp, lltrue, llfalse); + } + } else { + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); + let (otherwise, targets) = targets.split_last().unwrap(); + bx.switch( + discr.immediate(), + helper.llblock(self, *otherwise), + values.iter().zip(targets).map(|(&value, target)| { + (value, helper.llblock(self, *target)) + }) + ); + } + } + + fn codegen_return_terminator(&mut self, mut bx: Bx) { + // Call `va_end` if this is the definition of a C-variadic function. + if self.fn_abi.c_variadic { + // The `VaList` "spoofed" argument is just after all the real arguments. + let va_list_arg_idx = self.fn_abi.args.len(); + match self.locals[mir::Local::new(1 + va_list_arg_idx)] { + LocalRef::Place(va_list) => { + bx.va_end(va_list.llval); + } + _ => bug!("C-variadic function must have a `VaList` place"), + } + } + if self.fn_abi.ret.layout.abi.is_uninhabited() { + // Functions with uninhabited return values are marked `noreturn`, + // so we should make sure that we never actually do. + bx.abort(); + bx.unreachable(); + return; + } + let llval = match self.fn_abi.ret.mode { + PassMode::Ignore | PassMode::Indirect(..) => { + bx.ret_void(); + return; + } + + PassMode::Direct(_) | PassMode::Pair(..) => { + let op = + self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); + if let Ref(llval, _, align) = op.val { + bx.load(llval, align) + } else { + op.immediate_or_packed_pair(&mut bx) + } + } + + PassMode::Cast(cast_ty) => { + let op = match self.locals[mir::RETURN_PLACE] { + LocalRef::Operand(Some(op)) => op, + LocalRef::Operand(None) => bug!("use of return before def"), + LocalRef::Place(cg_place) => { + OperandRef { + val: Ref(cg_place.llval, None, cg_place.align), + layout: cg_place.layout + } + } + LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), + }; + let llslot = match op.val { + Immediate(_) | Pair(..) => { + let scratch = + PlaceRef::alloca(&mut bx, self.fn_abi.ret.layout); + op.val.store(&mut bx, scratch); + scratch.llval + } + Ref(llval, _, align) => { + assert_eq!(align, op.layout.align.abi, + "return place is unaligned!"); + llval + } + }; + let addr = bx.pointercast(llslot, bx.type_ptr_to( + bx.cast_backend_type(&cast_ty) + )); + bx.load(addr, self.fn_abi.ret.layout.align.abi) + } + }; + bx.ret(llval); + } + + + fn codegen_drop_terminator<'b>( + &mut self, + helper: TerminatorCodegenHelper<'b, 'tcx>, + mut bx: Bx, + location: &mir::Place<'tcx>, + target: mir::BasicBlock, + unwind: Option, + ) { + let ty = location.ty(self.mir.body(), bx.tcx()).ty; + let ty = self.monomorphize(&ty); + let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); + + if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { + // we don't actually need to drop anything. + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + return + } + + let place = self.codegen_place(&mut bx, &location.as_ref()); + let (args1, args2); + let mut args = if let Some(llextra) = place.llextra { + args2 = [place.llval, llextra]; + &args2[..] + } else { + args1 = [place.llval]; + &args1[..] + }; + let (drop_fn, fn_abi) = match ty.kind { + ty::Dynamic(..) => { + let sig = drop_fn.fn_sig(self.cx.tcx()); + let sig = self.cx.tcx().normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); + let fn_abi = FnAbi::new_vtable(&bx, sig, &[]); + let vtable = args[1]; + args = &args[..1]; + (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi) + } + _ => { + (bx.get_fn_addr(drop_fn), + FnAbi::of_instance(&bx, drop_fn)) + } + }; + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.do_call(self, &mut bx, fn_ty, drop_fn, args, + Some((ReturnDest::Nothing, target)), + unwind); + } + + fn codegen_assert_terminator<'b>( + &mut self, + helper: TerminatorCodegenHelper<'b, 'tcx>, + mut bx: Bx, + terminator: &mir::Terminator<'tcx>, + cond: &mir::Operand<'tcx>, + expected: bool, + msg: &mir::AssertMessage<'tcx>, + target: mir::BasicBlock, + cleanup: Option, + ) { + let span = terminator.source_info.span; + let cond = self.codegen_operand(&mut bx, cond).immediate(); + let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1); + + // This case can currently arise only from functions marked + // with #[rustc_inherit_overflow_checks] and inlined from + // another crate (mostly core::num generic/#[inline] fns), + // while the current crate doesn't use overflow checks. + // NOTE: Unlike binops, negation doesn't have its own + // checked operation, just a comparison with the minimum + // value, so we have to check for the assert message. + if !bx.check_overflow() { + if let PanicInfo::OverflowNeg = *msg { + const_cond = Some(expected); + } + } + + // Don't codegen the panic block if success if known. + if const_cond == Some(expected) { + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + return; + } + + // Pass the condition through llvm.expect for branch hinting. + let cond = bx.expect(cond, expected); + + // Create the failure block and the conditional branch to it. + let lltarget = helper.llblock(self, target); + let panic_block = self.new_block("panic"); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + if expected { + bx.cond_br(cond, lltarget, panic_block.llbb()); + } else { + bx.cond_br(cond, panic_block.llbb(), lltarget); + } + + // After this point, bx is the block for the call to panic. + bx = panic_block; + self.set_debug_loc(&mut bx, terminator.source_info); + + // Get the location information. + let location = self.get_caller_location(&mut bx, span).immediate(); + + // Put together the arguments to the panic entry point. + let (lang_item, args) = match msg { + PanicInfo::BoundsCheck { ref len, ref index } => { + let len = self.codegen_operand(&mut bx, len).immediate(); + let index = self.codegen_operand(&mut bx, index).immediate(); + (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) + } + _ => { + let msg_str = Symbol::intern(msg.description()); + let msg = bx.const_str(msg_str); + (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location]) + } + }; + + // Obtain the panic entry point. + let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); + let instance = ty::Instance::mono(bx.tcx(), def_id); + let fn_abi = FnAbi::of_instance(&bx, instance); + let llfn = bx.get_fn_addr(instance); + + // Codegen the actual panic invoke/call. + helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); + } + + fn codegen_call_terminator<'b>( + &mut self, + helper: TerminatorCodegenHelper<'b, 'tcx>, + mut bx: Bx, + terminator: &mir::Terminator<'tcx>, + func: &mir::Operand<'tcx>, + args: &Vec>, + destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, + cleanup: Option, + ) { + let span = terminator.source_info.span; + // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. + let callee = self.codegen_operand(&mut bx, func); + + let (instance, mut llfn) = match callee.layout.ty.kind { + ty::FnDef(def_id, substs) => { + (Some(ty::Instance::resolve(bx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs).unwrap()), + None) + } + ty::FnPtr(_) => { + (None, Some(callee.immediate())) + } + _ => bug!("{} is not callable", callee.layout.ty), + }; + let def = instance.map(|i| i.def); + let sig = callee.layout.ty.fn_sig(bx.tcx()); + let sig = bx.tcx().normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &sig, + ); + let abi = sig.abi; + + // Handle intrinsics old codegen wants Expr's for, ourselves. + let intrinsic = match def { + Some(ty::InstanceDef::Intrinsic(def_id)) => + Some(bx.tcx().item_name(def_id).as_str()), + _ => None + }; + let intrinsic = intrinsic.as_ref().map(|s| &s[..]); + + if intrinsic == Some("transmute") { + if let Some(destination_ref) = destination.as_ref() { + let &(ref dest, target) = destination_ref; + self.codegen_transmute(&mut bx, &args[0], dest); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + } else { + // If we are trying to transmute to an uninhabited type, + // it is likely there is no allotted destination. In fact, + // transmuting to an uninhabited type is UB, which means + // we can do what we like. Here, we declare that transmuting + // into an uninhabited type is impossible, so anything following + // it must be unreachable. + assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited); + bx.unreachable(); + } + return; + } + + let extra_args = &args[sig.inputs().len()..]; + let extra_args = extra_args.iter().map(|op_arg| { + let op_ty = op_arg.ty(self.mir.body(), bx.tcx()); + self.monomorphize(&op_ty) + }).collect::>(); + + let fn_abi = match def { + Some(ty::InstanceDef::Virtual(..)) => { + FnAbi::new_vtable(&bx, sig, &extra_args) + } + Some(ty::InstanceDef::DropGlue(_, None)) => { + // Empty drop glue; a no-op. + let &(_, target) = destination.as_ref().unwrap(); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + return; + } + _ => FnAbi::new(&bx, sig, &extra_args) + }; + + // Emit a panic or a no-op for `panic_if_uninhabited`. + if intrinsic == Some("panic_if_uninhabited") { + let ty = instance.unwrap().substs.type_at(0); + let layout = bx.layout_of(ty); + if layout.abi.is_uninhabited() { + let msg_str = format!("Attempted to instantiate uninhabited type {}", ty); + let msg = bx.const_str(Symbol::intern(&msg_str)); + let location = self.get_caller_location(&mut bx, span).immediate(); + + // Obtain the panic entry point. + let def_id = + common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); + let instance = ty::Instance::mono(bx.tcx(), def_id); + let fn_abi = FnAbi::of_instance(&bx, instance); + let llfn = bx.get_fn_addr(instance); + + if let Some((_, target)) = destination.as_ref() { + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + } + // Codegen the actual panic invoke/call. + helper.do_call( + self, + &mut bx, + fn_abi, + llfn, + &[msg.0, msg.1, location], + destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), + cleanup, + ); + } else { + // a NOP + let target = destination.as_ref().unwrap().1; + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) + } + return; + } + + // The arguments we'll be passing. Plus one to account for outptr, if used. + let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; + let mut llargs = Vec::with_capacity(arg_count); + + // Prepare the return value destination + let ret_dest = if let Some((ref dest, _)) = *destination { + let is_intrinsic = intrinsic.is_some(); +<<<<<<< HEAD + self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, is_intrinsic) +======= + self.make_return_dest(&mut bx, dest, &fn_ty.ret, &mut llargs, + is_intrinsic) +>>>>>>> Undo minor changes that weren't needed, fix one lifetime typo + } else { + ReturnDest::Nothing + }; + + if intrinsic == Some("caller_location") { + if let Some((_, target)) = destination.as_ref() { + let location = self.get_caller_location(&mut bx, span); + + if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { + location.val.store(&mut bx, tmp); + } + self.store_return(&mut bx, ret_dest, &fn_abi.ret, location.immediate()); + + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + helper.funclet_br(self, &mut bx, *target); + } + return; + } + + if intrinsic.is_some() && intrinsic != Some("drop_in_place") { + let dest = match ret_dest { + _ if fn_abi.ret.is_indirect() => llargs[0], + ReturnDest::Nothing => + bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret))), + ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => + dst.llval, + ReturnDest::DirectOperand(_) => + bug!("Cannot use direct operand with an intrinsic call"), + }; + + let args: Vec<_> = args.iter().enumerate().map(|(i, arg)| { + // The indices passed to simd_shuffle* in the + // third argument must be constant. This is + // checked by const-qualification, which also + // promotes any complex rvalues to constants. + if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") { + match arg { + // The shuffle array argument is usually not an explicit constant, + // but specified directly in the code. This means it gets promoted + // and we can then extract the value by evaluating the promoted. + mir::Operand::Copy(place) | mir::Operand::Move(place) => { + if let mir::PlaceRef { + base: + &PlaceBase::Static(box Static { + kind: StaticKind::Promoted(promoted, _), + ty, + def_id: _, + }), + projection: &[], + } = place.as_ref() + { + let param_env = ty::ParamEnv::reveal_all(); + let cid = mir::interpret::GlobalId { + instance: self.instance, + promoted: Some(promoted), + }; + let c = bx.tcx().const_eval(param_env.and(cid)); + let (llval, ty) = self.simd_shuffle_indices( + &bx, + terminator.source_info.span, + ty, + c, + ); + return OperandRef { + val: Immediate(llval), + layout: bx.layout_of(ty), + }; + } else { + span_bug!(span, "shuffle indices must be constant"); + } + } + + mir::Operand::Constant(constant) => { + let c = self.eval_mir_constant(constant); + let (llval, ty) = self.simd_shuffle_indices( + &bx, + constant.span, + constant.literal.ty, + c, + ); + return OperandRef { + val: Immediate(llval), + layout: bx.layout_of(ty) + }; + } + } + } + + self.codegen_operand(&mut bx, arg) + }).collect(); + + + bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_abi, &args, dest, + terminator.source_info.span); + + if let ReturnDest::IndirectOperand(dst, _) = ret_dest { + self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval); + } + + if let Some((_, target)) = *destination { + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + } else { + bx.unreachable(); + } + + return; + } + + // Split the rust-call tupled arguments off. + let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() { + let (tup, args) = args.split_last().unwrap(); + (args, Some(tup)) + } else { + (&args[..], None) + }; + + 'make_args: for (i, arg) in first_args.iter().enumerate() { + let mut op = self.codegen_operand(&mut bx, arg); + + if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { + if let Pair(..) = op.val { + // In the case of Rc, we need to explicitly pass a + // *mut RcBox with a Scalar (not ScalarPair) ABI. This is a hack + // that is understood elsewhere in the compiler as a method on + // `dyn Trait`. + // To get a `*mut RcBox`, we just keep unwrapping newtypes until + // we get a value of a built-in pointer type + 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr() + && !op.layout.ty.is_region_ptr() + { + 'iter_fields: for i in 0..op.layout.fields.count() { + let field = op.extract_field(&mut bx, i); + if !field.layout.is_zst() { + // we found the one non-zero-sized field that is allowed + // now find *its* non-zero-sized field, or stop if it's a + // pointer + op = field; + continue 'descend_newtypes + } + } + + span_bug!(span, "receiver has no non-zero-sized fields {:?}", op); + } + + // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its + // data pointer and vtable. Look up the method in the vtable, and pass + // the data pointer as the first argument + match op.val { + Pair(data_ptr, meta) => { + llfn = Some(meth::VirtualIndex::from_index(idx) + .get_fn(&mut bx, meta, &fn_abi)); + llargs.push(data_ptr); + continue 'make_args + } + other => bug!("expected a Pair, got {:?}", other), + } + } else if let Ref(data_ptr, Some(meta), _) = op.val { + // by-value dynamic dispatch + llfn = Some(meth::VirtualIndex::from_index(idx) + .get_fn(&mut bx, meta, &fn_abi)); + llargs.push(data_ptr); + continue; + } else { + span_bug!(span, "can't codegen a virtual call on {:?}", op); + } + } + + // The callee needs to own the argument memory if we pass it + // by-ref, so make a local copy of non-immediate constants. + match (arg, op.val) { + (&mir::Operand::Copy(_), Ref(_, None, _)) | + (&mir::Operand::Constant(_), Ref(_, None, _)) => { + let tmp = PlaceRef::alloca(&mut bx, op.layout); + op.val.store(&mut bx, tmp); + op.val = Ref(tmp.llval, None, tmp.align); + } + _ => {} + } + + self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]); + } + if let Some(tup) = untuple { + self.codegen_arguments_untupled(&mut bx, tup, &mut llargs, + &fn_abi.args[first_args.len()..]) + } + + let fn_ptr = match (llfn, instance) { + (Some(llfn), _) => llfn, + (None, Some(instance)) => bx.get_fn_addr(instance), + _ => span_bug!(span, "no llfn for call"), + }; + + if let Some((_, target)) = destination.as_ref() { + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + } + helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, + destination.as_ref().map(|&(_, target)| (ret_dest, target)), + cleanup); + } +} + +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + pub fn codegen_block( + &mut self, + bb: mir::BasicBlock, + ) { + let mut bx = self.build_block(bb); + let data = &self.mir.body()[bb]; + + debug!("codegen_block({:?}={:?})", bb, data); + + for statement in &data.statements { + bx = self.codegen_statement(bx, statement); + } + + self.codegen_terminator(bx, bb, data.terminator()); + } + + fn codegen_terminator( + &mut self, + mut bx: Bx, + bb: mir::BasicBlock, + terminator: &mir::Terminator<'tcx> + ) { + debug!("codegen_terminator: {:?}", terminator); + + // Create the cleanup bundle, if needed. + let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb); + let helper = TerminatorCodegenHelper { + bb: &bb, terminator, funclet_bb + }; + + self.set_debug_loc(&mut bx, terminator.source_info); + match terminator.kind { + mir::TerminatorKind::Resume => { + self.codegen_resume_terminator(helper, bx) + } + + mir::TerminatorKind::Abort => { + bx.abort(); + bx.unreachable(); + } + + mir::TerminatorKind::Goto { target } => { + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + } + + mir::TerminatorKind::SwitchInt { + ref discr, switch_ty, ref values, ref targets + } => { + self.codegen_switchint_terminator(helper, bx, discr, switch_ty, + values, targets); + } + + mir::TerminatorKind::Return => { + self.codegen_return_terminator(bx); + } + + mir::TerminatorKind::Unreachable => { + bx.unreachable(); + } + + mir::TerminatorKind::Drop { ref location, target, unwind } => { + self.codegen_drop_terminator(helper, bx, location, target, unwind); + } + + mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => { + self.codegen_assert_terminator(helper, bx, terminator, cond, + expected, msg, target, cleanup); + } + + mir::TerminatorKind::DropAndReplace { .. } => { + bug!("undesugared DropAndReplace in codegen: {:?}", terminator); + } + + mir::TerminatorKind::Call { + ref func, + ref args, + ref destination, + cleanup, + from_hir_call: _ + } => { + self.codegen_call_terminator(helper, bx, terminator, func, + args, destination, cleanup); + } + mir::TerminatorKind::GeneratorDrop | + mir::TerminatorKind::Yield { .. } => bug!("generator ops in codegen"), + mir::TerminatorKind::FalseEdges { .. } | + mir::TerminatorKind::FalseUnwind { .. } => bug!("borrowck false edges in codegen"), + } + } + + fn codegen_argument( + &mut self, + bx: &mut Bx, + op: OperandRef<'tcx, Bx::Value>, + llargs: &mut Vec, + arg: &ArgAbi<'tcx, Ty<'tcx>> + ) { + // Fill padding with undef value, where applicable. + if let Some(ty) = arg.pad { + llargs.push(bx.const_undef(bx.reg_backend_type(&ty))) + } + + if arg.is_ignore() { + return; + } + + if let PassMode::Pair(..) = arg.mode { + match op.val { + Pair(a, b) => { + llargs.push(a); + llargs.push(b); + return; + } + _ => bug!("codegen_argument: {:?} invalid for pair argument", op) + } + } else if arg.is_unsized_indirect() { + match op.val { + Ref(a, Some(b), _) => { + llargs.push(a); + llargs.push(b); + return; + } + _ => bug!("codegen_argument: {:?} invalid for unsized indirect argument", op) + } + } + + // Force by-ref if we have to load through a cast pointer. + let (mut llval, align, by_ref) = match op.val { + Immediate(_) | Pair(..) => { + match arg.mode { + PassMode::Indirect(..) | PassMode::Cast(_) => { + let scratch = PlaceRef::alloca(bx, arg.layout); + op.val.store(bx, scratch); + (scratch.llval, scratch.align, true) + } + _ => { + (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false) + } + } + } + Ref(llval, _, align) => { + if arg.is_indirect() && align < arg.layout.align.abi { + // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I + // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't + // have scary latent bugs around. + + let scratch = PlaceRef::alloca(bx, arg.layout); + base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align, + op.layout, MemFlags::empty()); + (scratch.llval, scratch.align, true) + } else { + (llval, align, true) + } + } + }; + + if by_ref && !arg.is_indirect() { + // Have to load the argument, maybe while casting it. + if let PassMode::Cast(ty) = arg.mode { + let addr = bx.pointercast(llval, bx.type_ptr_to( + bx.cast_backend_type(&ty)) + ); + llval = bx.load(addr, align.min(arg.layout.align.abi)); + } else { + // We can't use `PlaceRef::load` here because the argument + // may have a type we don't treat as immediate, but the ABI + // used for this call is passing it by-value. In that case, + // the load would just produce `OperandValue::Ref` instead + // of the `OperandValue::Immediate` we need for the call. + llval = bx.load(llval, align); + if let layout::Abi::Scalar(ref scalar) = arg.layout.abi { + if scalar.is_bool() { + bx.range_metadata(llval, 0..2); + } + } + // We store bools as `i8` so we need to truncate to `i1`. + llval = base::to_immediate(bx, llval, arg.layout); + } + } + + llargs.push(llval); + } + + fn codegen_arguments_untupled( + &mut self, + bx: &mut Bx, + operand: &mir::Operand<'tcx>, + llargs: &mut Vec, + args: &[ArgAbi<'tcx, Ty<'tcx>>] + ) { + let tuple = self.codegen_operand(bx, operand); + + // Handle both by-ref and immediate tuples. + if let Ref(llval, None, align) = tuple.val { + let tuple_ptr = PlaceRef::new_sized_aligned(llval, tuple.layout, align); + for i in 0..tuple.layout.fields.count() { + let field_ptr = tuple_ptr.project_field(bx, i); + let field = bx.load_operand(field_ptr); + self.codegen_argument(bx, field, llargs, &args[i]); + } + } else if let Ref(_, Some(_), _) = tuple.val { + bug!("closure arguments must be sized") + } else { + // If the tuple is immediate, the elements are as well. + for i in 0..tuple.layout.fields.count() { + let op = tuple.extract_field(bx, i); + self.codegen_argument(bx, op, llargs, &args[i]); + } + } + } + + fn get_caller_location( + &mut self, + bx: &mut Bx, + span: Span, + ) -> OperandRef<'tcx, Bx::Value> { + let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); + let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); + let const_loc = bx.tcx().const_caller_location(( + Symbol::intern(&caller.file.name.to_string()), + caller.line as u32, + caller.col_display as u32 + 1, + )); + OperandRef::from_const(bx, const_loc) + } + + fn get_personality_slot( + &mut self, + bx: &mut Bx + ) -> PlaceRef<'tcx, Bx::Value> { + let cx = bx.cx(); + if let Some(slot) = self.personality_slot { + slot + } else { + let layout = cx.layout_of(cx.tcx().intern_tup(&[ + cx.tcx().mk_mut_ptr(cx.tcx().types.u8), + cx.tcx().types.i32 + ])); + let slot = PlaceRef::alloca(bx, layout); + self.personality_slot = Some(slot); + slot + } + } + + /// Returns the landing-pad wrapper around the given basic block. + /// + /// No-op in MSVC SEH scheme. + fn landing_pad_to( + &mut self, + target_bb: mir::BasicBlock + ) -> Bx::BasicBlock { + if let Some(block) = self.landing_pads[target_bb] { + return block; + } + + let block = self.blocks[target_bb]; + let landing_pad = self.landing_pad_uncached(block); + self.landing_pads[target_bb] = Some(landing_pad); + landing_pad + } + + fn landing_pad_uncached( + &mut self, + target_bb: Bx::BasicBlock, + ) -> Bx::BasicBlock { + if base::wants_msvc_seh(self.cx.sess()) { + span_bug!(self.mir.span, "landing pad was not inserted?") + } + + let mut bx = self.new_block("cleanup"); + + let llpersonality = self.cx.eh_personality(); + let llretty = self.landing_pad_type(); + let lp = bx.landing_pad(llretty, llpersonality, 1); + bx.set_cleanup(lp); + + let slot = self.get_personality_slot(&mut bx); + slot.storage_live(&mut bx); + Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot); + + bx.br(target_bb); + bx.llbb() + } + + fn landing_pad_type(&self) -> Bx::Type { + let cx = self.cx; + cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false) + } + + fn unreachable_block( + &mut self + ) -> Bx::BasicBlock { + self.unreachable_block.unwrap_or_else(|| { + let mut bx = self.new_block("unreachable"); + bx.unreachable(); + self.unreachable_block = Some(bx.llbb()); + bx.llbb() + }) + } + + pub fn new_block(&self, name: &str) -> Bx { + Bx::new_block(self.cx, self.llfn, name) + } + + pub fn build_block( + &self, + bb: mir::BasicBlock + ) -> Bx { + let mut bx = Bx::with_cx(self.cx); + bx.position_at_end(self.blocks[bb]); + bx + } + + fn make_return_dest( + &mut self, + bx: &mut Bx, + dest: &mir::Place<'tcx>, +<<<<<<< HEAD + fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, + llargs: &mut Vec, is_intrinsic: bool, +======= + fn_ret: &ArgType<'tcx, Ty<'tcx>>, + llargs: &mut Vec, is_intrinsic: bool +>>>>>>> Undo minor changes that weren't needed, fix one lifetime typo + ) -> ReturnDest<'tcx, Bx::Value> { + // If the return is ignored, we can just return a do-nothing `ReturnDest`. + if fn_ret.is_ignore() { + return ReturnDest::Nothing; + } + let dest = if let Some(index) = dest.as_local() { + match self.locals[index] { + LocalRef::Place(dest) => dest, + LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), + LocalRef::Operand(None) => { + // Handle temporary places, specifically `Operand` ones, as + // they don't have `alloca`s. + return if fn_ret.is_indirect() { + // Odd, but possible, case, we have an operand temporary, + // but the calling convention has an indirect return. + let tmp = PlaceRef::alloca(bx, fn_ret.layout); + tmp.storage_live(bx); + llargs.push(tmp.llval); + ReturnDest::IndirectOperand(tmp, index) + } else if is_intrinsic { + // Currently, intrinsics always need a location to store + // the result, so we create a temporary `alloca` for the + // result. + let tmp = PlaceRef::alloca(bx, fn_ret.layout); + tmp.storage_live(bx); + ReturnDest::IndirectOperand(tmp, index) + } else { + ReturnDest::DirectOperand(index) + }; + } + LocalRef::Operand(Some(_)) => { + bug!("place local already assigned to"); + } + } + } else { + self.codegen_place(bx, &mir::PlaceRef { + base: &dest.base, + projection: &dest.projection, + }) + }; + if fn_ret.is_indirect() { + if dest.align < dest.layout.align.abi { + // Currently, MIR code generation does not create calls + // that store directly to fields of packed structs (in + // fact, the calls it creates write only to temps). + // + // If someone changes that, please update this code path + // to create a temporary. + span_bug!(self.mir.span, "can't directly store to unaligned value"); + } + llargs.push(dest.llval); + ReturnDest::Nothing + } else { + ReturnDest::Store(dest) + } + } + + fn codegen_transmute( + &mut self, + bx: &mut Bx, + src: &mir::Operand<'tcx>, + dst: &mir::Place<'tcx> + ) { + if let Some(index) = dst.as_local() { + match self.locals[index] { + LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), + LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), + LocalRef::Operand(None) => { + let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); + assert!(!dst_layout.ty.has_erasable_regions()); + let place = PlaceRef::alloca(bx, dst_layout); + place.storage_live(bx); + self.codegen_transmute_into(bx, src, place); + let op = bx.load_operand(place); + place.storage_dead(bx); + self.locals[index] = LocalRef::Operand(Some(op)); + } + LocalRef::Operand(Some(op)) => { + assert!(op.layout.is_zst(), + "assigning to initialized SSAtemp"); + } + } + } else { + let dst = self.codegen_place(bx, &dst.as_ref()); + self.codegen_transmute_into(bx, src, dst); + } + } + + fn codegen_transmute_into( + &mut self, + bx: &mut Bx, + src: &mir::Operand<'tcx>, + dst: PlaceRef<'tcx, Bx::Value> + ) { + let src = self.codegen_operand(bx, src); + let llty = bx.backend_type(src.layout); + let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); + let align = src.layout.align.abi.min(dst.align); + src.val.store(bx, PlaceRef::new_sized_aligned(cast_ptr, src.layout, align)); + } + + + // Stores the return value of a function call into it's final location. + fn store_return( + &mut self, + bx: &mut Bx, + dest: ReturnDest<'tcx, Bx::Value>, + ret_abi: &ArgAbi<'tcx, Ty<'tcx>>, + llval: Bx::Value + ) { + use self::ReturnDest::*; + + match dest { + Nothing => (), + Store(dst) => bx.store_arg(&ret_abi, llval, dst), + IndirectOperand(tmp, index) => { + let op = bx.load_operand(tmp); + tmp.storage_dead(bx); + self.locals[index] = LocalRef::Operand(Some(op)); + } + DirectOperand(index) => { + // If there is a cast, we have to store and reload. + let op = if let PassMode::Cast(_) = ret_abi.mode { + let tmp = PlaceRef::alloca(bx, ret_abi.layout); + tmp.storage_live(bx); + bx.store_arg(&ret_abi, llval, tmp); + let op = bx.load_operand(tmp); + tmp.storage_dead(bx); + op + } else { + OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout) + }; + self.locals[index] = LocalRef::Operand(Some(op)); + } + } + } +} + +enum ReturnDest<'tcx, V> { + // Do nothing; the return value is indirect or ignored. + Nothing, + // Store the return value to the pointer. + Store(PlaceRef<'tcx, V>), + // Store an indirect return value to an operand local place. + IndirectOperand(PlaceRef<'tcx, V>, mir::Local), + // Store a direct return value to an operand local place. + DirectOperand(mir::Local) +} diff --git a/src/librustc_codegen_ssa/mir/mod.rs.orig b/src/librustc_codegen_ssa/mir/mod.rs.orig new file mode 100644 index 0000000000000..83365f2ab222c --- /dev/null +++ b/src/librustc_codegen_ssa/mir/mod.rs.orig @@ -0,0 +1,439 @@ +use rustc::ty::{self, Ty, TypeFoldable, Instance}; +<<<<<<< HEAD +use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt}; +use rustc::mir::{self, Body, BodyCache}; +use rustc_target::abi::call::{FnAbi, PassMode}; +======= +use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt}; +use rustc::mir::{self, Body, ReadOnlyBodyCache}; +use rustc_target::abi::call::{FnType, PassMode}; +>>>>>>> Simplify BodyCache impl and fix all remaining type errors in librustc_mir (lifetime errors still exist) +use crate::base; +use crate::traits::*; + +use std::iter; + +use rustc_index::bit_set::BitSet; +use rustc_index::vec::IndexVec; + +use self::analyze::CleanupKind; +use self::debuginfo::FunctionDebugContext; +use self::place::PlaceRef; +use rustc::mir::traversal; + +use self::operand::{OperandRef, OperandValue}; + +/// Master context for codegenning from MIR. +pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { + instance: Instance<'tcx>, + + mir: mir::ReadOnlyBodyCache<'a, 'tcx>, + + debug_context: Option>, + + llfn: Bx::Function, + + cx: &'a Bx::CodegenCx, + + fn_abi: FnAbi<'tcx, Ty<'tcx>>, + + /// When unwinding is initiated, we have to store this personality + /// value somewhere so that we can load it and re-use it in the + /// resume instruction. The personality is (afaik) some kind of + /// value used for C++ unwinding, which must filter by type: we + /// don't really care about it very much. Anyway, this value + /// contains an alloca into which the personality is stored and + /// then later loaded when generating the DIVERGE_BLOCK. + personality_slot: Option>, + + /// A `Block` for each MIR `BasicBlock` + blocks: IndexVec, + + /// The funclet status of each basic block + cleanup_kinds: IndexVec, + + /// When targeting MSVC, this stores the cleanup info for each funclet + /// BB. This is initialized as we compute the funclets' head block in RPO. + funclets: IndexVec>, + + /// This stores the landing-pad block for a given BB, computed lazily on GNU + /// and eagerly on MSVC. + landing_pads: IndexVec>, + + /// Cached unreachable block + unreachable_block: Option, + + /// The location where each MIR arg/var/tmp/ret is stored. This is + /// usually an `PlaceRef` representing an alloca, but not always: + /// sometimes we can skip the alloca and just store the value + /// directly using an `OperandRef`, which makes for tighter LLVM + /// IR. The conditions for using an `OperandRef` are as follows: + /// + /// - the type of the local must be judged "immediate" by `is_llvm_immediate` + /// - the operand must never be referenced indirectly + /// - we should not take its address using the `&` operator + /// - nor should it appear in a place path like `tmp.a` + /// - the operand must be defined by an rvalue that can generate immediate + /// values + /// + /// Avoiding allocs can also be important for certain intrinsics, + /// notably `expect`. + locals: IndexVec>, + + per_local_var_debug_info: Option>>>, +} + +impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + pub fn monomorphize(&self, value: &T) -> T + where T: TypeFoldable<'tcx> + { + self.cx.tcx().subst_and_normalize_erasing_regions( + self.instance.substs, + ty::ParamEnv::reveal_all(), + value, + ) + } +} + +enum LocalRef<'tcx, V> { + Place(PlaceRef<'tcx, V>), + /// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place). + /// `*p` is the fat pointer that references the actual unsized place. + /// Every time it is initialized, we have to reallocate the place + /// and update the fat pointer. That's the reason why it is indirect. + UnsizedPlace(PlaceRef<'tcx, V>), + Operand(Option>), +} + +impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { + fn new_operand>( + bx: &mut Bx, + layout: TyLayout<'tcx>, + ) -> LocalRef<'tcx, V> { + if layout.is_zst() { + // Zero-size temporaries aren't always initialized, which + // doesn't matter because they don't contain data, but + // we need something in the operand. + LocalRef::Operand(Some(OperandRef::new_zst(bx, layout))) + } else { + LocalRef::Operand(None) + } + } +} + +/////////////////////////////////////////////////////////////////////////// + +pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + cx: &'a Bx::CodegenCx, + llfn: Bx::Function, + mir: ReadOnlyBodyCache<'a, 'tcx>, + instance: Instance<'tcx>, + sig: ty::FnSig<'tcx>, +) { + assert!(!instance.substs.needs_infer()); + + let fn_abi = FnAbi::new(cx, sig, &[]); + debug!("fn_abi: {:?}", fn_abi); + + let debug_context = + cx.create_function_debug_context(instance, sig, llfn, &mir); + + let mut bx = Bx::new_block(cx, llfn, "start"); + + if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) { + bx.set_personality_fn(cx.eh_personality()); + } + + bx.sideeffect(); + + let cleanup_kinds = analyze::cleanup_kinds(&mir); + // Allocate a `Block` for every basic block, except + // the start block, if nothing loops back to it. + let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty(); + let block_bxs: IndexVec = + mir.basic_blocks().indices().map(|bb| { + if bb == mir::START_BLOCK && !reentrant_start_block { + bx.llbb() + } else { + bx.build_sibling_block(&format!("{:?}", bb)).llbb() + } + }).collect(); + + let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); + let mir_body = mir.body(); + let mut fx = FunctionCx { + instance, + mir, + llfn, + fn_abi, + cx, + personality_slot: None, + blocks: block_bxs, + unreachable_block: None, + cleanup_kinds, + landing_pads, + funclets, + locals: IndexVec::new(), + debug_context, + per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), + }; + + let memory_locals = analyze::non_ssa_locals(&fx); + + // Allocate variable and temp allocas + fx.locals = { + let args = arg_local_refs(&mut bx, &fx, &memory_locals); + + let mut allocate_local = |local| { + let decl = &mir_body.local_decls[local]; + let layout = bx.layout_of(fx.monomorphize(&decl.ty)); + assert!(!layout.ty.has_erasable_regions()); + + if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() { + debug!("alloc: {:?} (return place) -> place", local); + let llretptr = bx.get_param(0); + return LocalRef::Place(PlaceRef::new_sized(llretptr, layout)); + } + + if memory_locals.contains(local) { + debug!("alloc: {:?} -> place", local); + if layout.is_unsized() { + LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout)) + } else { + LocalRef::Place(PlaceRef::alloca(&mut bx, layout)) + } + } else { + debug!("alloc: {:?} -> operand", local); + LocalRef::new_operand(&mut bx, layout) + } + }; + + let retptr = allocate_local(mir::RETURN_PLACE); + iter::once(retptr) + .chain(args.into_iter()) + .chain(mir_body.vars_and_temps_iter().map(allocate_local)) + .collect() + }; + + // Apply debuginfo to the newly allocated locals. + fx.debug_introduce_locals(&mut bx); + + // Branch to the START block, if it's not the entry block. + if reentrant_start_block { + bx.br(fx.blocks[mir::START_BLOCK]); + } + + // Up until here, IR instructions for this function have explicitly not been annotated with + // source code location, so we don't step into call setup code. From here on, source location + // emitting should be enabled. + if let Some(debug_context) = &mut fx.debug_context { + debug_context.source_locations_enabled = true; + } + + let rpo = traversal::reverse_postorder(&mir_body); + let mut visited = BitSet::new_empty(mir_body.basic_blocks().len()); + + // Codegen the body of each block using reverse postorder + for (bb, _) in rpo { + visited.insert(bb.index()); + fx.codegen_block(bb); + } + + // Remove blocks that haven't been visited, or have no + // predecessors. + for bb in mir_body.basic_blocks().indices() { + // Unreachable block + if !visited.contains(bb.index()) { + debug!("codegen_mir: block {:?} was not visited", bb); + unsafe { + bx.delete_basic_block(fx.blocks[bb]); + } + } + } +} + +fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + mir: &'b Body<'tcx>, + bx: &mut Bx, + cleanup_kinds: &IndexVec, + block_bxs: &IndexVec, +) -> ( + IndexVec>, + IndexVec>, +) { + block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| { + match *cleanup_kind { + CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {} + _ => return (None, None) + } + + let funclet; + let ret_llbb; + match mir[bb].terminator.as_ref().map(|t| &t.kind) { + // This is a basic block that we're aborting the program for, + // notably in an `extern` function. These basic blocks are inserted + // so that we assert that `extern` functions do indeed not panic, + // and if they do we abort the process. + // + // On MSVC these are tricky though (where we're doing funclets). If + // we were to do a cleanuppad (like below) the normal functions like + // `longjmp` would trigger the abort logic, terminating the + // program. Instead we insert the equivalent of `catch(...)` for C++ + // which magically doesn't trigger when `longjmp` files over this + // frame. + // + // Lots more discussion can be found on #48251 but this codegen is + // modeled after clang's for: + // + // try { + // foo(); + // } catch (...) { + // bar(); + // } + Some(&mir::TerminatorKind::Abort) => { + let mut cs_bx = bx.build_sibling_block(&format!("cs_funclet{:?}", bb)); + let mut cp_bx = bx.build_sibling_block(&format!("cp_funclet{:?}", bb)); + ret_llbb = cs_bx.llbb(); + + let cs = cs_bx.catch_switch(None, None, 1); + cs_bx.add_handler(cs, cp_bx.llbb()); + + // The "null" here is actually a RTTI type descriptor for the + // C++ personality function, but `catch (...)` has no type so + // it's null. The 64 here is actually a bitfield which + // represents that this is a catch-all block. + let null = bx.const_null(bx.type_i8p()); + let sixty_four = bx.const_i32(64); + funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]); + cp_bx.br(llbb); + } + _ => { + let mut cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb)); + ret_llbb = cleanup_bx.llbb(); + funclet = cleanup_bx.cleanup_pad(None, &[]); + cleanup_bx.br(llbb); + } + }; + + (Some(ret_llbb), Some(funclet)) + }).unzip() +} + +/// Produces, for each argument, a `Value` pointing at the +/// argument's value. As arguments are places, these are always +/// indirect. +fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &mut Bx, + fx: &FunctionCx<'a, 'tcx, Bx>, + memory_locals: &BitSet, +) -> Vec> { + let mut idx = 0; + let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; + + fx.mir.args_iter().enumerate().map(|(arg_index, local)| { + let arg_decl = &fx.mir.local_decls[local]; + + if Some(local) == fx.mir.spread_arg { + // This argument (e.g., the last argument in the "rust-call" ABI) + // is a tuple that was spread at the ABI level and now we have + // to reconstruct it into a tuple local variable, from multiple + // individual LLVM function arguments. + + let arg_ty = fx.monomorphize(&arg_decl.ty); + let tupled_arg_tys = match arg_ty.kind { + ty::Tuple(ref tys) => tys, + _ => bug!("spread argument isn't a tuple?!") + }; + + let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + for i in 0..tupled_arg_tys.len() { + let arg = &fx.fn_abi.args[idx]; + idx += 1; + if arg.pad.is_some() { + llarg_idx += 1; + } + let pr_field = place.project_field(bx, i); + bx.store_fn_arg(arg, &mut llarg_idx, pr_field); + } + + return LocalRef::Place(place); + } + + if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() { + let arg_ty = fx.monomorphize(&arg_decl.ty); + + let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + bx.va_start(va_list.llval); + + return LocalRef::Place(va_list); + } + + let arg = &fx.fn_abi.args[idx]; + idx += 1; + if arg.pad.is_some() { + llarg_idx += 1; + } + + if !memory_locals.contains(local) { + // We don't have to cast or keep the argument in the alloca. + // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead + // of putting everything in allocas just so we can use llvm.dbg.declare. + let local = |op| LocalRef::Operand(Some(op)); + match arg.mode { + PassMode::Ignore => { + return local(OperandRef::new_zst(bx, arg.layout)); + } + PassMode::Direct(_) => { + let llarg = bx.get_param(llarg_idx); + llarg_idx += 1; + return local( + OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout)); + } + PassMode::Pair(..) => { + let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1)); + llarg_idx += 2; + + return local(OperandRef { + val: OperandValue::Pair(a, b), + layout: arg.layout + }); + } + _ => {} + } + } + + if arg.is_sized_indirect() { + // Don't copy an indirect argument to an alloca, the caller + // already put it in a temporary alloca and gave it up. + // FIXME: lifetimes + let llarg = bx.get_param(llarg_idx); + llarg_idx += 1; + LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout)) + } else if arg.is_unsized_indirect() { + // As the storage for the indirect argument lives during + // the whole function call, we just copy the fat pointer. + let llarg = bx.get_param(llarg_idx); + llarg_idx += 1; + let llextra = bx.get_param(llarg_idx); + llarg_idx += 1; + let indirect_operand = OperandValue::Pair(llarg, llextra); + + let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout); + indirect_operand.store(bx, tmp); + LocalRef::UnsizedPlace(tmp) + } else { + let tmp = PlaceRef::alloca(bx, arg.layout); + bx.store_fn_arg(arg, &mut llarg_idx, tmp); + LocalRef::Place(tmp) + } + }).collect() +} + +mod analyze; +mod block; +pub mod constant; +pub mod debuginfo; +pub mod place; +pub mod operand; +mod rvalue; +mod statement; From ed90818ac8b826249f786aae701bf1602a830a8f Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 6 Nov 2019 12:34:16 -0500 Subject: [PATCH 37/47] Remove files created during conflict resolution --- src/librustc_codegen_ssa/mir/block.rs.orig | 1257 -------------------- src/librustc_codegen_ssa/mir/mod.rs.orig | 439 ------- 2 files changed, 1696 deletions(-) delete mode 100644 src/librustc_codegen_ssa/mir/block.rs.orig delete mode 100644 src/librustc_codegen_ssa/mir/mod.rs.orig diff --git a/src/librustc_codegen_ssa/mir/block.rs.orig b/src/librustc_codegen_ssa/mir/block.rs.orig deleted file mode 100644 index d715a4e0e09c5..0000000000000 --- a/src/librustc_codegen_ssa/mir/block.rs.orig +++ /dev/null @@ -1,1257 +0,0 @@ -use rustc_index::vec::Idx; -use rustc::middle::lang_items; -use rustc::ty::{self, Ty, TypeFoldable, Instance}; -use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, PlaceBase, Static, StaticKind}; -use rustc::mir::interpret::PanicInfo; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; -use rustc_target::spec::abi::Abi; -use crate::base; -use crate::MemFlags; -use crate::common::{self, IntPredicate}; -use crate::meth; - -use crate::traits::*; - -use std::borrow::Cow; - -use syntax::{source_map::Span, symbol::Symbol}; - -use super::{FunctionCx, LocalRef}; -use super::place::PlaceRef; -use super::operand::OperandRef; -use super::operand::OperandValue::{Pair, Ref, Immediate}; - -/// Used by `FunctionCx::codegen_terminator` for emitting common patterns -/// e.g., creating a basic block, calling a function, etc. -struct TerminatorCodegenHelper<'a, 'tcx> { - bb: &'a mir::BasicBlock, - terminator: &'a mir::Terminator<'tcx>, - funclet_bb: Option, -} - -impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { - /// Returns the associated funclet from `FunctionCx::funclets` for the - /// `funclet_bb` member if it is not `None`. - fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( - &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - ) -> Option<&'c Bx::Funclet> { - match self.funclet_bb { - Some(funcl) => fx.funclets[funcl].as_ref(), - None => None, - } - } - - fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( - &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - target: mir::BasicBlock, - ) -> (Bx::BasicBlock, bool) { - let span = self.terminator.source_info.span; - let lltarget = fx.blocks[target]; - let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); - match (self.funclet_bb, target_funclet) { - (None, None) => (lltarget, false), - (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => - (lltarget, false), - // jump *into* cleanup - need a landing pad if GNU - (None, Some(_)) => (fx.landing_pad_to(target), false), - (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), - (Some(_), Some(_)) => (fx.landing_pad_to(target), true), - } - } - - /// Create a basic block. - fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( - &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - target: mir::BasicBlock, - ) -> Bx::BasicBlock { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); - if is_cleanupret { - // MSVC cross-funclet jump - need a trampoline - - debug!("llblock: creating cleanup trampoline for {:?}", target); - let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); - let mut trampoline = fx.new_block(name); - trampoline.cleanup_ret(self.funclet(fx).unwrap(), - Some(lltarget)); - trampoline.llbb() - } else { - lltarget - } - } - - fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( - &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - bx: &mut Bx, - target: mir::BasicBlock, - ) { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); - if is_cleanupret { - // micro-optimization: generate a `ret` rather than a jump - // to a trampoline. - bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); - } else { - bx.br(lltarget); - } - } - - /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional - /// return destination `destination` and the cleanup function `cleanup`. - fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( - &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - bx: &mut Bx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, - fn_ptr: Bx::Value, - llargs: &[Bx::Value], - destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, - cleanup: Option, - ) { - if let Some(cleanup) = cleanup { - let ret_bx = if let Some((_, target)) = destination { - fx.blocks[target] - } else { - fx.unreachable_block() - }; - let invokeret = bx.invoke(fn_ptr, - &llargs, - ret_bx, - self.llblock(fx, cleanup), - self.funclet(fx)); - bx.apply_attrs_callsite(&fn_abi, invokeret); - - if let Some((ret_dest, target)) = destination { - let mut ret_bx = fx.build_block(target); - fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); - fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); - } - } else { - let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); - bx.apply_attrs_callsite(&fn_abi, llret); - if fx.mir[*self.bb].is_cleanup { - // Cleanup is always the cold path. Don't inline - // drop glue. Also, when there is a deeply-nested - // struct, there are "symmetry" issues that cause - // exponential inlining - see issue #41696. - bx.do_not_inline(llret); - } - - if let Some((ret_dest, target)) = destination { - fx.store_return(bx, ret_dest, &fn_abi.ret, llret); - self.funclet_br(fx, bx, target); - } else { - bx.unreachable(); - } - } - } - - // Generate sideeffect intrinsic if jumping to any of the targets can form - // a loop. - fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( - &self, - mir: mir::ReadOnlyBodyCache<'b, 'tcx>, - bx: &mut Bx, - targets: &[mir::BasicBlock], - ) { - if bx.tcx().sess.opts.debugging_opts.insert_sideeffect { - if targets.iter().any(|target| { - *target <= *self.bb - && target - .start_location() - .is_predecessor_of(self.bb.start_location(), mir) - }) { - bx.sideeffect(); - } - } - } -} - -/// Codegen implementations for some terminator variants. -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - /// Generates code for a `Resume` terminator. - fn codegen_resume_terminator<'b>( - &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, - mut bx: Bx, - ) { - if let Some(funclet) = helper.funclet(self) { - bx.cleanup_ret(funclet, None); - } else { - let slot = self.get_personality_slot(&mut bx); - let lp0 = slot.project_field(&mut bx, 0); - let lp0 = bx.load_operand(lp0).immediate(); - let lp1 = slot.project_field(&mut bx, 1); - let lp1 = bx.load_operand(lp1).immediate(); - slot.storage_dead(&mut bx); - - if !bx.sess().target.target.options.custom_unwind_resume { - let mut lp = bx.const_undef(self.landing_pad_type()); - lp = bx.insert_value(lp, lp0, 0); - lp = bx.insert_value(lp, lp1, 1); - bx.resume(lp); - } else { - bx.call(bx.eh_unwind_resume(), &[lp0], - helper.funclet(self)); - bx.unreachable(); - } - } - } - - fn codegen_switchint_terminator<'b>( - &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, - mut bx: Bx, - discr: &mir::Operand<'tcx>, - switch_ty: Ty<'tcx>, - values: &Cow<'tcx, [u128]>, - targets: &Vec, - ) { - let discr = self.codegen_operand(&mut bx, &discr); - if targets.len() == 2 { - // If there are two targets, emit br instead of switch - let lltrue = helper.llblock(self, targets[0]); - let llfalse = helper.llblock(self, targets[1]); - if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); - // Don't generate trivial icmps when switching on bool - if let [0] = values[..] { - bx.cond_br(discr.immediate(), llfalse, lltrue); - } else { - assert_eq!(&values[..], &[1]); - bx.cond_br(discr.immediate(), lltrue, llfalse); - } - } else { - let switch_llty = bx.immediate_backend_type( - bx.layout_of(switch_ty) - ); - let llval = bx.const_uint_big(switch_llty, values[0]); - let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); - bx.cond_br(cmp, lltrue, llfalse); - } - } else { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); - let (otherwise, targets) = targets.split_last().unwrap(); - bx.switch( - discr.immediate(), - helper.llblock(self, *otherwise), - values.iter().zip(targets).map(|(&value, target)| { - (value, helper.llblock(self, *target)) - }) - ); - } - } - - fn codegen_return_terminator(&mut self, mut bx: Bx) { - // Call `va_end` if this is the definition of a C-variadic function. - if self.fn_abi.c_variadic { - // The `VaList` "spoofed" argument is just after all the real arguments. - let va_list_arg_idx = self.fn_abi.args.len(); - match self.locals[mir::Local::new(1 + va_list_arg_idx)] { - LocalRef::Place(va_list) => { - bx.va_end(va_list.llval); - } - _ => bug!("C-variadic function must have a `VaList` place"), - } - } - if self.fn_abi.ret.layout.abi.is_uninhabited() { - // Functions with uninhabited return values are marked `noreturn`, - // so we should make sure that we never actually do. - bx.abort(); - bx.unreachable(); - return; - } - let llval = match self.fn_abi.ret.mode { - PassMode::Ignore | PassMode::Indirect(..) => { - bx.ret_void(); - return; - } - - PassMode::Direct(_) | PassMode::Pair(..) => { - let op = - self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); - if let Ref(llval, _, align) = op.val { - bx.load(llval, align) - } else { - op.immediate_or_packed_pair(&mut bx) - } - } - - PassMode::Cast(cast_ty) => { - let op = match self.locals[mir::RETURN_PLACE] { - LocalRef::Operand(Some(op)) => op, - LocalRef::Operand(None) => bug!("use of return before def"), - LocalRef::Place(cg_place) => { - OperandRef { - val: Ref(cg_place.llval, None, cg_place.align), - layout: cg_place.layout - } - } - LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), - }; - let llslot = match op.val { - Immediate(_) | Pair(..) => { - let scratch = - PlaceRef::alloca(&mut bx, self.fn_abi.ret.layout); - op.val.store(&mut bx, scratch); - scratch.llval - } - Ref(llval, _, align) => { - assert_eq!(align, op.layout.align.abi, - "return place is unaligned!"); - llval - } - }; - let addr = bx.pointercast(llslot, bx.type_ptr_to( - bx.cast_backend_type(&cast_ty) - )); - bx.load(addr, self.fn_abi.ret.layout.align.abi) - } - }; - bx.ret(llval); - } - - - fn codegen_drop_terminator<'b>( - &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, - mut bx: Bx, - location: &mir::Place<'tcx>, - target: mir::BasicBlock, - unwind: Option, - ) { - let ty = location.ty(self.mir.body(), bx.tcx()).ty; - let ty = self.monomorphize(&ty); - let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); - - if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { - // we don't actually need to drop anything. - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - return - } - - let place = self.codegen_place(&mut bx, &location.as_ref()); - let (args1, args2); - let mut args = if let Some(llextra) = place.llextra { - args2 = [place.llval, llextra]; - &args2[..] - } else { - args1 = [place.llval]; - &args1[..] - }; - let (drop_fn, fn_abi) = match ty.kind { - ty::Dynamic(..) => { - let sig = drop_fn.fn_sig(self.cx.tcx()); - let sig = self.cx.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let fn_abi = FnAbi::new_vtable(&bx, sig, &[]); - let vtable = args[1]; - args = &args[..1]; - (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi) - } - _ => { - (bx.get_fn_addr(drop_fn), - FnAbi::of_instance(&bx, drop_fn)) - } - }; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.do_call(self, &mut bx, fn_ty, drop_fn, args, - Some((ReturnDest::Nothing, target)), - unwind); - } - - fn codegen_assert_terminator<'b>( - &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, - mut bx: Bx, - terminator: &mir::Terminator<'tcx>, - cond: &mir::Operand<'tcx>, - expected: bool, - msg: &mir::AssertMessage<'tcx>, - target: mir::BasicBlock, - cleanup: Option, - ) { - let span = terminator.source_info.span; - let cond = self.codegen_operand(&mut bx, cond).immediate(); - let mut const_cond = bx.const_to_opt_u128(cond, false).map(|c| c == 1); - - // This case can currently arise only from functions marked - // with #[rustc_inherit_overflow_checks] and inlined from - // another crate (mostly core::num generic/#[inline] fns), - // while the current crate doesn't use overflow checks. - // NOTE: Unlike binops, negation doesn't have its own - // checked operation, just a comparison with the minimum - // value, so we have to check for the assert message. - if !bx.check_overflow() { - if let PanicInfo::OverflowNeg = *msg { - const_cond = Some(expected); - } - } - - // Don't codegen the panic block if success if known. - if const_cond == Some(expected) { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - return; - } - - // Pass the condition through llvm.expect for branch hinting. - let cond = bx.expect(cond, expected); - - // Create the failure block and the conditional branch to it. - let lltarget = helper.llblock(self, target); - let panic_block = self.new_block("panic"); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - if expected { - bx.cond_br(cond, lltarget, panic_block.llbb()); - } else { - bx.cond_br(cond, panic_block.llbb(), lltarget); - } - - // After this point, bx is the block for the call to panic. - bx = panic_block; - self.set_debug_loc(&mut bx, terminator.source_info); - - // Get the location information. - let location = self.get_caller_location(&mut bx, span).immediate(); - - // Put together the arguments to the panic entry point. - let (lang_item, args) = match msg { - PanicInfo::BoundsCheck { ref len, ref index } => { - let len = self.codegen_operand(&mut bx, len).immediate(); - let index = self.codegen_operand(&mut bx, index).immediate(); - (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) - } - _ => { - let msg_str = Symbol::intern(msg.description()); - let msg = bx.const_str(msg_str); - (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location]) - } - }; - - // Obtain the panic entry point. - let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance); - let llfn = bx.get_fn_addr(instance); - - // Codegen the actual panic invoke/call. - helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); - } - - fn codegen_call_terminator<'b>( - &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, - mut bx: Bx, - terminator: &mir::Terminator<'tcx>, - func: &mir::Operand<'tcx>, - args: &Vec>, - destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, - cleanup: Option, - ) { - let span = terminator.source_info.span; - // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. - let callee = self.codegen_operand(&mut bx, func); - - let (instance, mut llfn) = match callee.layout.ty.kind { - ty::FnDef(def_id, substs) => { - (Some(ty::Instance::resolve(bx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs).unwrap()), - None) - } - ty::FnPtr(_) => { - (None, Some(callee.immediate())) - } - _ => bug!("{} is not callable", callee.layout.ty), - }; - let def = instance.map(|i| i.def); - let sig = callee.layout.ty.fn_sig(bx.tcx()); - let sig = bx.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let abi = sig.abi; - - // Handle intrinsics old codegen wants Expr's for, ourselves. - let intrinsic = match def { - Some(ty::InstanceDef::Intrinsic(def_id)) => - Some(bx.tcx().item_name(def_id).as_str()), - _ => None - }; - let intrinsic = intrinsic.as_ref().map(|s| &s[..]); - - if intrinsic == Some("transmute") { - if let Some(destination_ref) = destination.as_ref() { - let &(ref dest, target) = destination_ref; - self.codegen_transmute(&mut bx, &args[0], dest); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - } else { - // If we are trying to transmute to an uninhabited type, - // it is likely there is no allotted destination. In fact, - // transmuting to an uninhabited type is UB, which means - // we can do what we like. Here, we declare that transmuting - // into an uninhabited type is impossible, so anything following - // it must be unreachable. - assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited); - bx.unreachable(); - } - return; - } - - let extra_args = &args[sig.inputs().len()..]; - let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir.body(), bx.tcx()); - self.monomorphize(&op_ty) - }).collect::>(); - - let fn_abi = match def { - Some(ty::InstanceDef::Virtual(..)) => { - FnAbi::new_vtable(&bx, sig, &extra_args) - } - Some(ty::InstanceDef::DropGlue(_, None)) => { - // Empty drop glue; a no-op. - let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - return; - } - _ => FnAbi::new(&bx, sig, &extra_args) - }; - - // Emit a panic or a no-op for `panic_if_uninhabited`. - if intrinsic == Some("panic_if_uninhabited") { - let ty = instance.unwrap().substs.type_at(0); - let layout = bx.layout_of(ty); - if layout.abi.is_uninhabited() { - let msg_str = format!("Attempted to instantiate uninhabited type {}", ty); - let msg = bx.const_str(Symbol::intern(&msg_str)); - let location = self.get_caller_location(&mut bx, span).immediate(); - - // Obtain the panic entry point. - let def_id = - common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance); - let llfn = bx.get_fn_addr(instance); - - if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); - } - // Codegen the actual panic invoke/call. - helper.do_call( - self, - &mut bx, - fn_abi, - llfn, - &[msg.0, msg.1, location], - destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), - cleanup, - ); - } else { - // a NOP - let target = destination.as_ref().unwrap().1; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) - } - return; - } - - // The arguments we'll be passing. Plus one to account for outptr, if used. - let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; - let mut llargs = Vec::with_capacity(arg_count); - - // Prepare the return value destination - let ret_dest = if let Some((ref dest, _)) = *destination { - let is_intrinsic = intrinsic.is_some(); -<<<<<<< HEAD - self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, is_intrinsic) -======= - self.make_return_dest(&mut bx, dest, &fn_ty.ret, &mut llargs, - is_intrinsic) ->>>>>>> Undo minor changes that weren't needed, fix one lifetime typo - } else { - ReturnDest::Nothing - }; - - if intrinsic == Some("caller_location") { - if let Some((_, target)) = destination.as_ref() { - let location = self.get_caller_location(&mut bx, span); - - if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { - location.val.store(&mut bx, tmp); - } - self.store_return(&mut bx, ret_dest, &fn_abi.ret, location.immediate()); - - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); - helper.funclet_br(self, &mut bx, *target); - } - return; - } - - if intrinsic.is_some() && intrinsic != Some("drop_in_place") { - let dest = match ret_dest { - _ if fn_abi.ret.is_indirect() => llargs[0], - ReturnDest::Nothing => - bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret))), - ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => - dst.llval, - ReturnDest::DirectOperand(_) => - bug!("Cannot use direct operand with an intrinsic call"), - }; - - let args: Vec<_> = args.iter().enumerate().map(|(i, arg)| { - // The indices passed to simd_shuffle* in the - // third argument must be constant. This is - // checked by const-qualification, which also - // promotes any complex rvalues to constants. - if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") { - match arg { - // The shuffle array argument is usually not an explicit constant, - // but specified directly in the code. This means it gets promoted - // and we can then extract the value by evaluating the promoted. - mir::Operand::Copy(place) | mir::Operand::Move(place) => { - if let mir::PlaceRef { - base: - &PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted, _), - ty, - def_id: _, - }), - projection: &[], - } = place.as_ref() - { - let param_env = ty::ParamEnv::reveal_all(); - let cid = mir::interpret::GlobalId { - instance: self.instance, - promoted: Some(promoted), - }; - let c = bx.tcx().const_eval(param_env.and(cid)); - let (llval, ty) = self.simd_shuffle_indices( - &bx, - terminator.source_info.span, - ty, - c, - ); - return OperandRef { - val: Immediate(llval), - layout: bx.layout_of(ty), - }; - } else { - span_bug!(span, "shuffle indices must be constant"); - } - } - - mir::Operand::Constant(constant) => { - let c = self.eval_mir_constant(constant); - let (llval, ty) = self.simd_shuffle_indices( - &bx, - constant.span, - constant.literal.ty, - c, - ); - return OperandRef { - val: Immediate(llval), - layout: bx.layout_of(ty) - }; - } - } - } - - self.codegen_operand(&mut bx, arg) - }).collect(); - - - bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_abi, &args, dest, - terminator.source_info.span); - - if let ReturnDest::IndirectOperand(dst, _) = ret_dest { - self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval); - } - - if let Some((_, target)) = *destination { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - } else { - bx.unreachable(); - } - - return; - } - - // Split the rust-call tupled arguments off. - let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() { - let (tup, args) = args.split_last().unwrap(); - (args, Some(tup)) - } else { - (&args[..], None) - }; - - 'make_args: for (i, arg) in first_args.iter().enumerate() { - let mut op = self.codegen_operand(&mut bx, arg); - - if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { - if let Pair(..) = op.val { - // In the case of Rc, we need to explicitly pass a - // *mut RcBox with a Scalar (not ScalarPair) ABI. This is a hack - // that is understood elsewhere in the compiler as a method on - // `dyn Trait`. - // To get a `*mut RcBox`, we just keep unwrapping newtypes until - // we get a value of a built-in pointer type - 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr() - && !op.layout.ty.is_region_ptr() - { - 'iter_fields: for i in 0..op.layout.fields.count() { - let field = op.extract_field(&mut bx, i); - if !field.layout.is_zst() { - // we found the one non-zero-sized field that is allowed - // now find *its* non-zero-sized field, or stop if it's a - // pointer - op = field; - continue 'descend_newtypes - } - } - - span_bug!(span, "receiver has no non-zero-sized fields {:?}", op); - } - - // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its - // data pointer and vtable. Look up the method in the vtable, and pass - // the data pointer as the first argument - match op.val { - Pair(data_ptr, meta) => { - llfn = Some(meth::VirtualIndex::from_index(idx) - .get_fn(&mut bx, meta, &fn_abi)); - llargs.push(data_ptr); - continue 'make_args - } - other => bug!("expected a Pair, got {:?}", other), - } - } else if let Ref(data_ptr, Some(meta), _) = op.val { - // by-value dynamic dispatch - llfn = Some(meth::VirtualIndex::from_index(idx) - .get_fn(&mut bx, meta, &fn_abi)); - llargs.push(data_ptr); - continue; - } else { - span_bug!(span, "can't codegen a virtual call on {:?}", op); - } - } - - // The callee needs to own the argument memory if we pass it - // by-ref, so make a local copy of non-immediate constants. - match (arg, op.val) { - (&mir::Operand::Copy(_), Ref(_, None, _)) | - (&mir::Operand::Constant(_), Ref(_, None, _)) => { - let tmp = PlaceRef::alloca(&mut bx, op.layout); - op.val.store(&mut bx, tmp); - op.val = Ref(tmp.llval, None, tmp.align); - } - _ => {} - } - - self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]); - } - if let Some(tup) = untuple { - self.codegen_arguments_untupled(&mut bx, tup, &mut llargs, - &fn_abi.args[first_args.len()..]) - } - - let fn_ptr = match (llfn, instance) { - (Some(llfn), _) => llfn, - (None, Some(instance)) => bx.get_fn_addr(instance), - _ => span_bug!(span, "no llfn for call"), - }; - - if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); - } - helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, - destination.as_ref().map(|&(_, target)| (ret_dest, target)), - cleanup); - } -} - -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_block( - &mut self, - bb: mir::BasicBlock, - ) { - let mut bx = self.build_block(bb); - let data = &self.mir.body()[bb]; - - debug!("codegen_block({:?}={:?})", bb, data); - - for statement in &data.statements { - bx = self.codegen_statement(bx, statement); - } - - self.codegen_terminator(bx, bb, data.terminator()); - } - - fn codegen_terminator( - &mut self, - mut bx: Bx, - bb: mir::BasicBlock, - terminator: &mir::Terminator<'tcx> - ) { - debug!("codegen_terminator: {:?}", terminator); - - // Create the cleanup bundle, if needed. - let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb); - let helper = TerminatorCodegenHelper { - bb: &bb, terminator, funclet_bb - }; - - self.set_debug_loc(&mut bx, terminator.source_info); - match terminator.kind { - mir::TerminatorKind::Resume => { - self.codegen_resume_terminator(helper, bx) - } - - mir::TerminatorKind::Abort => { - bx.abort(); - bx.unreachable(); - } - - mir::TerminatorKind::Goto { target } => { - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - } - - mir::TerminatorKind::SwitchInt { - ref discr, switch_ty, ref values, ref targets - } => { - self.codegen_switchint_terminator(helper, bx, discr, switch_ty, - values, targets); - } - - mir::TerminatorKind::Return => { - self.codegen_return_terminator(bx); - } - - mir::TerminatorKind::Unreachable => { - bx.unreachable(); - } - - mir::TerminatorKind::Drop { ref location, target, unwind } => { - self.codegen_drop_terminator(helper, bx, location, target, unwind); - } - - mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => { - self.codegen_assert_terminator(helper, bx, terminator, cond, - expected, msg, target, cleanup); - } - - mir::TerminatorKind::DropAndReplace { .. } => { - bug!("undesugared DropAndReplace in codegen: {:?}", terminator); - } - - mir::TerminatorKind::Call { - ref func, - ref args, - ref destination, - cleanup, - from_hir_call: _ - } => { - self.codegen_call_terminator(helper, bx, terminator, func, - args, destination, cleanup); - } - mir::TerminatorKind::GeneratorDrop | - mir::TerminatorKind::Yield { .. } => bug!("generator ops in codegen"), - mir::TerminatorKind::FalseEdges { .. } | - mir::TerminatorKind::FalseUnwind { .. } => bug!("borrowck false edges in codegen"), - } - } - - fn codegen_argument( - &mut self, - bx: &mut Bx, - op: OperandRef<'tcx, Bx::Value>, - llargs: &mut Vec, - arg: &ArgAbi<'tcx, Ty<'tcx>> - ) { - // Fill padding with undef value, where applicable. - if let Some(ty) = arg.pad { - llargs.push(bx.const_undef(bx.reg_backend_type(&ty))) - } - - if arg.is_ignore() { - return; - } - - if let PassMode::Pair(..) = arg.mode { - match op.val { - Pair(a, b) => { - llargs.push(a); - llargs.push(b); - return; - } - _ => bug!("codegen_argument: {:?} invalid for pair argument", op) - } - } else if arg.is_unsized_indirect() { - match op.val { - Ref(a, Some(b), _) => { - llargs.push(a); - llargs.push(b); - return; - } - _ => bug!("codegen_argument: {:?} invalid for unsized indirect argument", op) - } - } - - // Force by-ref if we have to load through a cast pointer. - let (mut llval, align, by_ref) = match op.val { - Immediate(_) | Pair(..) => { - match arg.mode { - PassMode::Indirect(..) | PassMode::Cast(_) => { - let scratch = PlaceRef::alloca(bx, arg.layout); - op.val.store(bx, scratch); - (scratch.llval, scratch.align, true) - } - _ => { - (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false) - } - } - } - Ref(llval, _, align) => { - if arg.is_indirect() && align < arg.layout.align.abi { - // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I - // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't - // have scary latent bugs around. - - let scratch = PlaceRef::alloca(bx, arg.layout); - base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align, - op.layout, MemFlags::empty()); - (scratch.llval, scratch.align, true) - } else { - (llval, align, true) - } - } - }; - - if by_ref && !arg.is_indirect() { - // Have to load the argument, maybe while casting it. - if let PassMode::Cast(ty) = arg.mode { - let addr = bx.pointercast(llval, bx.type_ptr_to( - bx.cast_backend_type(&ty)) - ); - llval = bx.load(addr, align.min(arg.layout.align.abi)); - } else { - // We can't use `PlaceRef::load` here because the argument - // may have a type we don't treat as immediate, but the ABI - // used for this call is passing it by-value. In that case, - // the load would just produce `OperandValue::Ref` instead - // of the `OperandValue::Immediate` we need for the call. - llval = bx.load(llval, align); - if let layout::Abi::Scalar(ref scalar) = arg.layout.abi { - if scalar.is_bool() { - bx.range_metadata(llval, 0..2); - } - } - // We store bools as `i8` so we need to truncate to `i1`. - llval = base::to_immediate(bx, llval, arg.layout); - } - } - - llargs.push(llval); - } - - fn codegen_arguments_untupled( - &mut self, - bx: &mut Bx, - operand: &mir::Operand<'tcx>, - llargs: &mut Vec, - args: &[ArgAbi<'tcx, Ty<'tcx>>] - ) { - let tuple = self.codegen_operand(bx, operand); - - // Handle both by-ref and immediate tuples. - if let Ref(llval, None, align) = tuple.val { - let tuple_ptr = PlaceRef::new_sized_aligned(llval, tuple.layout, align); - for i in 0..tuple.layout.fields.count() { - let field_ptr = tuple_ptr.project_field(bx, i); - let field = bx.load_operand(field_ptr); - self.codegen_argument(bx, field, llargs, &args[i]); - } - } else if let Ref(_, Some(_), _) = tuple.val { - bug!("closure arguments must be sized") - } else { - // If the tuple is immediate, the elements are as well. - for i in 0..tuple.layout.fields.count() { - let op = tuple.extract_field(bx, i); - self.codegen_argument(bx, op, llargs, &args[i]); - } - } - } - - fn get_caller_location( - &mut self, - bx: &mut Bx, - span: Span, - ) -> OperandRef<'tcx, Bx::Value> { - let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); - let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); - let const_loc = bx.tcx().const_caller_location(( - Symbol::intern(&caller.file.name.to_string()), - caller.line as u32, - caller.col_display as u32 + 1, - )); - OperandRef::from_const(bx, const_loc) - } - - fn get_personality_slot( - &mut self, - bx: &mut Bx - ) -> PlaceRef<'tcx, Bx::Value> { - let cx = bx.cx(); - if let Some(slot) = self.personality_slot { - slot - } else { - let layout = cx.layout_of(cx.tcx().intern_tup(&[ - cx.tcx().mk_mut_ptr(cx.tcx().types.u8), - cx.tcx().types.i32 - ])); - let slot = PlaceRef::alloca(bx, layout); - self.personality_slot = Some(slot); - slot - } - } - - /// Returns the landing-pad wrapper around the given basic block. - /// - /// No-op in MSVC SEH scheme. - fn landing_pad_to( - &mut self, - target_bb: mir::BasicBlock - ) -> Bx::BasicBlock { - if let Some(block) = self.landing_pads[target_bb] { - return block; - } - - let block = self.blocks[target_bb]; - let landing_pad = self.landing_pad_uncached(block); - self.landing_pads[target_bb] = Some(landing_pad); - landing_pad - } - - fn landing_pad_uncached( - &mut self, - target_bb: Bx::BasicBlock, - ) -> Bx::BasicBlock { - if base::wants_msvc_seh(self.cx.sess()) { - span_bug!(self.mir.span, "landing pad was not inserted?") - } - - let mut bx = self.new_block("cleanup"); - - let llpersonality = self.cx.eh_personality(); - let llretty = self.landing_pad_type(); - let lp = bx.landing_pad(llretty, llpersonality, 1); - bx.set_cleanup(lp); - - let slot = self.get_personality_slot(&mut bx); - slot.storage_live(&mut bx); - Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot); - - bx.br(target_bb); - bx.llbb() - } - - fn landing_pad_type(&self) -> Bx::Type { - let cx = self.cx; - cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false) - } - - fn unreachable_block( - &mut self - ) -> Bx::BasicBlock { - self.unreachable_block.unwrap_or_else(|| { - let mut bx = self.new_block("unreachable"); - bx.unreachable(); - self.unreachable_block = Some(bx.llbb()); - bx.llbb() - }) - } - - pub fn new_block(&self, name: &str) -> Bx { - Bx::new_block(self.cx, self.llfn, name) - } - - pub fn build_block( - &self, - bb: mir::BasicBlock - ) -> Bx { - let mut bx = Bx::with_cx(self.cx); - bx.position_at_end(self.blocks[bb]); - bx - } - - fn make_return_dest( - &mut self, - bx: &mut Bx, - dest: &mir::Place<'tcx>, -<<<<<<< HEAD - fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, - llargs: &mut Vec, is_intrinsic: bool, -======= - fn_ret: &ArgType<'tcx, Ty<'tcx>>, - llargs: &mut Vec, is_intrinsic: bool ->>>>>>> Undo minor changes that weren't needed, fix one lifetime typo - ) -> ReturnDest<'tcx, Bx::Value> { - // If the return is ignored, we can just return a do-nothing `ReturnDest`. - if fn_ret.is_ignore() { - return ReturnDest::Nothing; - } - let dest = if let Some(index) = dest.as_local() { - match self.locals[index] { - LocalRef::Place(dest) => dest, - LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), - LocalRef::Operand(None) => { - // Handle temporary places, specifically `Operand` ones, as - // they don't have `alloca`s. - return if fn_ret.is_indirect() { - // Odd, but possible, case, we have an operand temporary, - // but the calling convention has an indirect return. - let tmp = PlaceRef::alloca(bx, fn_ret.layout); - tmp.storage_live(bx); - llargs.push(tmp.llval); - ReturnDest::IndirectOperand(tmp, index) - } else if is_intrinsic { - // Currently, intrinsics always need a location to store - // the result, so we create a temporary `alloca` for the - // result. - let tmp = PlaceRef::alloca(bx, fn_ret.layout); - tmp.storage_live(bx); - ReturnDest::IndirectOperand(tmp, index) - } else { - ReturnDest::DirectOperand(index) - }; - } - LocalRef::Operand(Some(_)) => { - bug!("place local already assigned to"); - } - } - } else { - self.codegen_place(bx, &mir::PlaceRef { - base: &dest.base, - projection: &dest.projection, - }) - }; - if fn_ret.is_indirect() { - if dest.align < dest.layout.align.abi { - // Currently, MIR code generation does not create calls - // that store directly to fields of packed structs (in - // fact, the calls it creates write only to temps). - // - // If someone changes that, please update this code path - // to create a temporary. - span_bug!(self.mir.span, "can't directly store to unaligned value"); - } - llargs.push(dest.llval); - ReturnDest::Nothing - } else { - ReturnDest::Store(dest) - } - } - - fn codegen_transmute( - &mut self, - bx: &mut Bx, - src: &mir::Operand<'tcx>, - dst: &mir::Place<'tcx> - ) { - if let Some(index) = dst.as_local() { - match self.locals[index] { - LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place), - LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"), - LocalRef::Operand(None) => { - let dst_layout = bx.layout_of(self.monomorphized_place_ty(&dst.as_ref())); - assert!(!dst_layout.ty.has_erasable_regions()); - let place = PlaceRef::alloca(bx, dst_layout); - place.storage_live(bx); - self.codegen_transmute_into(bx, src, place); - let op = bx.load_operand(place); - place.storage_dead(bx); - self.locals[index] = LocalRef::Operand(Some(op)); - } - LocalRef::Operand(Some(op)) => { - assert!(op.layout.is_zst(), - "assigning to initialized SSAtemp"); - } - } - } else { - let dst = self.codegen_place(bx, &dst.as_ref()); - self.codegen_transmute_into(bx, src, dst); - } - } - - fn codegen_transmute_into( - &mut self, - bx: &mut Bx, - src: &mir::Operand<'tcx>, - dst: PlaceRef<'tcx, Bx::Value> - ) { - let src = self.codegen_operand(bx, src); - let llty = bx.backend_type(src.layout); - let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty)); - let align = src.layout.align.abi.min(dst.align); - src.val.store(bx, PlaceRef::new_sized_aligned(cast_ptr, src.layout, align)); - } - - - // Stores the return value of a function call into it's final location. - fn store_return( - &mut self, - bx: &mut Bx, - dest: ReturnDest<'tcx, Bx::Value>, - ret_abi: &ArgAbi<'tcx, Ty<'tcx>>, - llval: Bx::Value - ) { - use self::ReturnDest::*; - - match dest { - Nothing => (), - Store(dst) => bx.store_arg(&ret_abi, llval, dst), - IndirectOperand(tmp, index) => { - let op = bx.load_operand(tmp); - tmp.storage_dead(bx); - self.locals[index] = LocalRef::Operand(Some(op)); - } - DirectOperand(index) => { - // If there is a cast, we have to store and reload. - let op = if let PassMode::Cast(_) = ret_abi.mode { - let tmp = PlaceRef::alloca(bx, ret_abi.layout); - tmp.storage_live(bx); - bx.store_arg(&ret_abi, llval, tmp); - let op = bx.load_operand(tmp); - tmp.storage_dead(bx); - op - } else { - OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout) - }; - self.locals[index] = LocalRef::Operand(Some(op)); - } - } - } -} - -enum ReturnDest<'tcx, V> { - // Do nothing; the return value is indirect or ignored. - Nothing, - // Store the return value to the pointer. - Store(PlaceRef<'tcx, V>), - // Store an indirect return value to an operand local place. - IndirectOperand(PlaceRef<'tcx, V>, mir::Local), - // Store a direct return value to an operand local place. - DirectOperand(mir::Local) -} diff --git a/src/librustc_codegen_ssa/mir/mod.rs.orig b/src/librustc_codegen_ssa/mir/mod.rs.orig deleted file mode 100644 index 83365f2ab222c..0000000000000 --- a/src/librustc_codegen_ssa/mir/mod.rs.orig +++ /dev/null @@ -1,439 +0,0 @@ -use rustc::ty::{self, Ty, TypeFoldable, Instance}; -<<<<<<< HEAD -use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, Body, BodyCache}; -use rustc_target::abi::call::{FnAbi, PassMode}; -======= -use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt}; -use rustc::mir::{self, Body, ReadOnlyBodyCache}; -use rustc_target::abi::call::{FnType, PassMode}; ->>>>>>> Simplify BodyCache impl and fix all remaining type errors in librustc_mir (lifetime errors still exist) -use crate::base; -use crate::traits::*; - -use std::iter; - -use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; - -use self::analyze::CleanupKind; -use self::debuginfo::FunctionDebugContext; -use self::place::PlaceRef; -use rustc::mir::traversal; - -use self::operand::{OperandRef, OperandValue}; - -/// Master context for codegenning from MIR. -pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { - instance: Instance<'tcx>, - - mir: mir::ReadOnlyBodyCache<'a, 'tcx>, - - debug_context: Option>, - - llfn: Bx::Function, - - cx: &'a Bx::CodegenCx, - - fn_abi: FnAbi<'tcx, Ty<'tcx>>, - - /// When unwinding is initiated, we have to store this personality - /// value somewhere so that we can load it and re-use it in the - /// resume instruction. The personality is (afaik) some kind of - /// value used for C++ unwinding, which must filter by type: we - /// don't really care about it very much. Anyway, this value - /// contains an alloca into which the personality is stored and - /// then later loaded when generating the DIVERGE_BLOCK. - personality_slot: Option>, - - /// A `Block` for each MIR `BasicBlock` - blocks: IndexVec, - - /// The funclet status of each basic block - cleanup_kinds: IndexVec, - - /// When targeting MSVC, this stores the cleanup info for each funclet - /// BB. This is initialized as we compute the funclets' head block in RPO. - funclets: IndexVec>, - - /// This stores the landing-pad block for a given BB, computed lazily on GNU - /// and eagerly on MSVC. - landing_pads: IndexVec>, - - /// Cached unreachable block - unreachable_block: Option, - - /// The location where each MIR arg/var/tmp/ret is stored. This is - /// usually an `PlaceRef` representing an alloca, but not always: - /// sometimes we can skip the alloca and just store the value - /// directly using an `OperandRef`, which makes for tighter LLVM - /// IR. The conditions for using an `OperandRef` are as follows: - /// - /// - the type of the local must be judged "immediate" by `is_llvm_immediate` - /// - the operand must never be referenced indirectly - /// - we should not take its address using the `&` operator - /// - nor should it appear in a place path like `tmp.a` - /// - the operand must be defined by an rvalue that can generate immediate - /// values - /// - /// Avoiding allocs can also be important for certain intrinsics, - /// notably `expect`. - locals: IndexVec>, - - per_local_var_debug_info: Option>>>, -} - -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn monomorphize(&self, value: &T) -> T - where T: TypeFoldable<'tcx> - { - self.cx.tcx().subst_and_normalize_erasing_regions( - self.instance.substs, - ty::ParamEnv::reveal_all(), - value, - ) - } -} - -enum LocalRef<'tcx, V> { - Place(PlaceRef<'tcx, V>), - /// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place). - /// `*p` is the fat pointer that references the actual unsized place. - /// Every time it is initialized, we have to reallocate the place - /// and update the fat pointer. That's the reason why it is indirect. - UnsizedPlace(PlaceRef<'tcx, V>), - Operand(Option>), -} - -impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { - fn new_operand>( - bx: &mut Bx, - layout: TyLayout<'tcx>, - ) -> LocalRef<'tcx, V> { - if layout.is_zst() { - // Zero-size temporaries aren't always initialized, which - // doesn't matter because they don't contain data, but - // we need something in the operand. - LocalRef::Operand(Some(OperandRef::new_zst(bx, layout))) - } else { - LocalRef::Operand(None) - } - } -} - -/////////////////////////////////////////////////////////////////////////// - -pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - cx: &'a Bx::CodegenCx, - llfn: Bx::Function, - mir: ReadOnlyBodyCache<'a, 'tcx>, - instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, -) { - assert!(!instance.substs.needs_infer()); - - let fn_abi = FnAbi::new(cx, sig, &[]); - debug!("fn_abi: {:?}", fn_abi); - - let debug_context = - cx.create_function_debug_context(instance, sig, llfn, &mir); - - let mut bx = Bx::new_block(cx, llfn, "start"); - - if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) { - bx.set_personality_fn(cx.eh_personality()); - } - - bx.sideeffect(); - - let cleanup_kinds = analyze::cleanup_kinds(&mir); - // Allocate a `Block` for every basic block, except - // the start block, if nothing loops back to it. - let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty(); - let block_bxs: IndexVec = - mir.basic_blocks().indices().map(|bb| { - if bb == mir::START_BLOCK && !reentrant_start_block { - bx.llbb() - } else { - bx.build_sibling_block(&format!("{:?}", bb)).llbb() - } - }).collect(); - - let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); - let mir_body = mir.body(); - let mut fx = FunctionCx { - instance, - mir, - llfn, - fn_abi, - cx, - personality_slot: None, - blocks: block_bxs, - unreachable_block: None, - cleanup_kinds, - landing_pads, - funclets, - locals: IndexVec::new(), - debug_context, - per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), - }; - - let memory_locals = analyze::non_ssa_locals(&fx); - - // Allocate variable and temp allocas - fx.locals = { - let args = arg_local_refs(&mut bx, &fx, &memory_locals); - - let mut allocate_local = |local| { - let decl = &mir_body.local_decls[local]; - let layout = bx.layout_of(fx.monomorphize(&decl.ty)); - assert!(!layout.ty.has_erasable_regions()); - - if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() { - debug!("alloc: {:?} (return place) -> place", local); - let llretptr = bx.get_param(0); - return LocalRef::Place(PlaceRef::new_sized(llretptr, layout)); - } - - if memory_locals.contains(local) { - debug!("alloc: {:?} -> place", local); - if layout.is_unsized() { - LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout)) - } else { - LocalRef::Place(PlaceRef::alloca(&mut bx, layout)) - } - } else { - debug!("alloc: {:?} -> operand", local); - LocalRef::new_operand(&mut bx, layout) - } - }; - - let retptr = allocate_local(mir::RETURN_PLACE); - iter::once(retptr) - .chain(args.into_iter()) - .chain(mir_body.vars_and_temps_iter().map(allocate_local)) - .collect() - }; - - // Apply debuginfo to the newly allocated locals. - fx.debug_introduce_locals(&mut bx); - - // Branch to the START block, if it's not the entry block. - if reentrant_start_block { - bx.br(fx.blocks[mir::START_BLOCK]); - } - - // Up until here, IR instructions for this function have explicitly not been annotated with - // source code location, so we don't step into call setup code. From here on, source location - // emitting should be enabled. - if let Some(debug_context) = &mut fx.debug_context { - debug_context.source_locations_enabled = true; - } - - let rpo = traversal::reverse_postorder(&mir_body); - let mut visited = BitSet::new_empty(mir_body.basic_blocks().len()); - - // Codegen the body of each block using reverse postorder - for (bb, _) in rpo { - visited.insert(bb.index()); - fx.codegen_block(bb); - } - - // Remove blocks that haven't been visited, or have no - // predecessors. - for bb in mir_body.basic_blocks().indices() { - // Unreachable block - if !visited.contains(bb.index()) { - debug!("codegen_mir: block {:?} was not visited", bb); - unsafe { - bx.delete_basic_block(fx.blocks[bb]); - } - } - } -} - -fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - mir: &'b Body<'tcx>, - bx: &mut Bx, - cleanup_kinds: &IndexVec, - block_bxs: &IndexVec, -) -> ( - IndexVec>, - IndexVec>, -) { - block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| { - match *cleanup_kind { - CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {} - _ => return (None, None) - } - - let funclet; - let ret_llbb; - match mir[bb].terminator.as_ref().map(|t| &t.kind) { - // This is a basic block that we're aborting the program for, - // notably in an `extern` function. These basic blocks are inserted - // so that we assert that `extern` functions do indeed not panic, - // and if they do we abort the process. - // - // On MSVC these are tricky though (where we're doing funclets). If - // we were to do a cleanuppad (like below) the normal functions like - // `longjmp` would trigger the abort logic, terminating the - // program. Instead we insert the equivalent of `catch(...)` for C++ - // which magically doesn't trigger when `longjmp` files over this - // frame. - // - // Lots more discussion can be found on #48251 but this codegen is - // modeled after clang's for: - // - // try { - // foo(); - // } catch (...) { - // bar(); - // } - Some(&mir::TerminatorKind::Abort) => { - let mut cs_bx = bx.build_sibling_block(&format!("cs_funclet{:?}", bb)); - let mut cp_bx = bx.build_sibling_block(&format!("cp_funclet{:?}", bb)); - ret_llbb = cs_bx.llbb(); - - let cs = cs_bx.catch_switch(None, None, 1); - cs_bx.add_handler(cs, cp_bx.llbb()); - - // The "null" here is actually a RTTI type descriptor for the - // C++ personality function, but `catch (...)` has no type so - // it's null. The 64 here is actually a bitfield which - // represents that this is a catch-all block. - let null = bx.const_null(bx.type_i8p()); - let sixty_four = bx.const_i32(64); - funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]); - cp_bx.br(llbb); - } - _ => { - let mut cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb)); - ret_llbb = cleanup_bx.llbb(); - funclet = cleanup_bx.cleanup_pad(None, &[]); - cleanup_bx.br(llbb); - } - }; - - (Some(ret_llbb), Some(funclet)) - }).unzip() -} - -/// Produces, for each argument, a `Value` pointing at the -/// argument's value. As arguments are places, these are always -/// indirect. -fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - bx: &mut Bx, - fx: &FunctionCx<'a, 'tcx, Bx>, - memory_locals: &BitSet, -) -> Vec> { - let mut idx = 0; - let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - - fx.mir.args_iter().enumerate().map(|(arg_index, local)| { - let arg_decl = &fx.mir.local_decls[local]; - - if Some(local) == fx.mir.spread_arg { - // This argument (e.g., the last argument in the "rust-call" ABI) - // is a tuple that was spread at the ABI level and now we have - // to reconstruct it into a tuple local variable, from multiple - // individual LLVM function arguments. - - let arg_ty = fx.monomorphize(&arg_decl.ty); - let tupled_arg_tys = match arg_ty.kind { - ty::Tuple(ref tys) => tys, - _ => bug!("spread argument isn't a tuple?!") - }; - - let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); - for i in 0..tupled_arg_tys.len() { - let arg = &fx.fn_abi.args[idx]; - idx += 1; - if arg.pad.is_some() { - llarg_idx += 1; - } - let pr_field = place.project_field(bx, i); - bx.store_fn_arg(arg, &mut llarg_idx, pr_field); - } - - return LocalRef::Place(place); - } - - if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() { - let arg_ty = fx.monomorphize(&arg_decl.ty); - - let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); - bx.va_start(va_list.llval); - - return LocalRef::Place(va_list); - } - - let arg = &fx.fn_abi.args[idx]; - idx += 1; - if arg.pad.is_some() { - llarg_idx += 1; - } - - if !memory_locals.contains(local) { - // We don't have to cast or keep the argument in the alloca. - // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead - // of putting everything in allocas just so we can use llvm.dbg.declare. - let local = |op| LocalRef::Operand(Some(op)); - match arg.mode { - PassMode::Ignore => { - return local(OperandRef::new_zst(bx, arg.layout)); - } - PassMode::Direct(_) => { - let llarg = bx.get_param(llarg_idx); - llarg_idx += 1; - return local( - OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout)); - } - PassMode::Pair(..) => { - let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1)); - llarg_idx += 2; - - return local(OperandRef { - val: OperandValue::Pair(a, b), - layout: arg.layout - }); - } - _ => {} - } - } - - if arg.is_sized_indirect() { - // Don't copy an indirect argument to an alloca, the caller - // already put it in a temporary alloca and gave it up. - // FIXME: lifetimes - let llarg = bx.get_param(llarg_idx); - llarg_idx += 1; - LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout)) - } else if arg.is_unsized_indirect() { - // As the storage for the indirect argument lives during - // the whole function call, we just copy the fat pointer. - let llarg = bx.get_param(llarg_idx); - llarg_idx += 1; - let llextra = bx.get_param(llarg_idx); - llarg_idx += 1; - let indirect_operand = OperandValue::Pair(llarg, llextra); - - let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout); - indirect_operand.store(bx, tmp); - LocalRef::UnsizedPlace(tmp) - } else { - let tmp = PlaceRef::alloca(bx, arg.layout); - bx.store_fn_arg(arg, &mut llarg_idx, tmp); - LocalRef::Place(tmp) - } - }).collect() -} - -mod analyze; -mod block; -pub mod constant; -pub mod debuginfo; -pub mod place; -pub mod operand; -mod rvalue; -mod statement; From 05dc5e9f47729b8bba89f7b0e2b54ea7dd1e1777 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 12 Nov 2019 23:41:43 -0500 Subject: [PATCH 38/47] Compute predecessors in mir_build query and use existing cache for generating ReadOnlyBodyCache, remove unneeded fns --- src/librustc/mir/cache.rs | 10 ---------- src/librustc_mir/build/mod.rs | 4 +++- src/librustc_mir/transform/check_unsafety.rs | 7 ++++--- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 09c18d714f2c7..44d534caa7590 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -181,8 +181,6 @@ impl BodyCache<'tcx> { ReadOnlyBodyCache::new(&self.cache, &self.body) } - pub fn cache(&self) -> &Cache { &self.cache } - pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { self.cache.basic_blocks_mut(&mut self.body) } @@ -240,14 +238,6 @@ impl ReadOnlyBodyCache<'a, 'tcx> { } } - pub fn from_external_cache(cache: &'a mut Cache, body: &'a Body<'tcx>) -> Self { - cache.ensure_predecessors(body); - Self { - cache, - body, - } - } - #[inline] pub fn predecessors(&self) -> &IndexVec> { self.cache.predecessors.as_ref().unwrap() diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 28b4c9fd09b37..b84461d6b9275 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -196,7 +196,9 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyCache<'_> { lints::check(tcx, &body, def_id); - BodyCache::new(body) + let mut body = BodyCache::new(body); + body.ensure_predecessors(); + body }) } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 85932bc5e5bc1..2c45dcfbe2665 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -528,9 +528,10 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult hir::BodyOwnerKind::Static(_) => (true, false), }; let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env); - let mut cache = body.cache().clone(); - let read_only_cache = ReadOnlyBodyCache::from_external_cache(&mut cache, body); - checker.visit_body(read_only_cache); + // mir_built ensures that body has a computed cache, so we don't (and can't) attempt to + // recompute it here. + let body = body.unwrap_read_only(); + checker.visit_body(body); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); UnsafetyCheckResult { From 245abc49be638e79781e6c3d633aba7a171d80d4 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 13 Nov 2019 00:35:45 -0500 Subject: [PATCH 39/47] Fix type errors cause during rebasing --- src/librustc_mir/borrow_check/conflict_errors.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 4 ++-- src/librustc_mir/transform/uninhabited_enum_branching.rs | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 2170bd7e7a44c..73a9fd81c9b4f 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -1695,7 +1695,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } let mut visitor = FakeReadCauseFinder { place, cause: None }; - visitor.visit_body(&self.body); + visitor.visit_body(self.body); match visitor.cause { Some(FakeReadCause::ForMatchGuard) => Some("match guard"), Some(FakeReadCause::ForIndex) => Some("indexing expression"), diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 3a24f4a9fb1a4..49ae759fd5531 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -41,11 +41,11 @@ use crate::transform::check_consts::{qualifs, Item, ConstKind, is_lang_panic_fn} /// newly created `StaticKind::Promoted`. #[derive(Default)] pub struct PromoteTemps<'tcx> { - pub promoted_fragments: Cell>>, + pub promoted_fragments: Cell>>, } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { // There's not really any point in promoting errorful MIR. // // This does not include MIR that failed const-checking, which we still try to promote. diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs index a6c18aee6a889..de070d75ad8e2 100644 --- a/src/librustc_mir/transform/uninhabited_enum_branching.rs +++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs @@ -2,7 +2,8 @@ use crate::transform::{MirPass, MirSource}; use rustc::mir::{ - BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind, + BasicBlock, BasicBlockData, Body, BodyCache, Local, Operand, Rvalue, StatementKind, + TerminatorKind, }; use rustc::ty::layout::{Abi, TyLayout, Variants}; use rustc::ty::{Ty, TyCtxt}; @@ -65,7 +66,7 @@ fn variant_discriminants<'tcx>( } impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { if source.promoted.is_some() { return; } From c6354e9839cefbaf80d3a26304bc3e4adacfabb0 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 20 Nov 2019 09:58:31 -0500 Subject: [PATCH 40/47] Remove inline attributes that hadn't been profiled, unexport Cache since it no longer needs to be public --- src/librustc/mir/cache.rs | 15 --------------- src/librustc/mir/mod.rs | 3 +-- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 44d534caa7590..fcab65cdfdd9f 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -78,13 +78,11 @@ impl Cache { } } - #[inline] pub fn invalidate_predecessors(&mut self) { // FIXME: consider being more fine-grained self.predecessors = None; } - #[inline] pub fn ensure_predecessors(&mut self, body: &Body<'_>) { if self.predecessors.is_none() { let mut result = IndexVec::from_elem(vec![], body.basic_blocks()); @@ -100,29 +98,24 @@ impl Cache { } } - #[inline] /// This will recompute the predecessors cache if it is not available fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec> { self.ensure_predecessors(body); self.predecessors.as_ref().unwrap() } - #[inline] fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] { &self.predecessors(body)[bb] } - #[inline] fn unwrap_predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { &self.predecessors.as_ref().unwrap()[bb] } - #[inline] impl_predecessor_locations!((pub) predecessor_locations mut); impl_predecessor_locations!(() unwrap_predecessor_locations); - #[inline] pub fn basic_blocks_mut<'a, 'tcx>( &mut self, body: &'a mut Body<'tcx> @@ -195,7 +188,6 @@ impl BodyCache<'tcx> { impl<'tcx> Index for BodyCache<'tcx> { type Output = BasicBlockData<'tcx>; - #[inline] fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { &self.body[index] } @@ -238,32 +230,26 @@ impl ReadOnlyBodyCache<'a, 'tcx> { } } - #[inline] pub fn predecessors(&self) -> &IndexVec> { self.cache.predecessors.as_ref().unwrap() } - #[inline] pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { self.cache.unwrap_predecessors_for(bb) } - #[inline] pub fn predecessor_locations(&self, loc: Location) -> impl Iterator + '_ { self.cache.unwrap_predecessor_locations(loc, self.body) } - #[inline] pub fn body(&self) -> &'a Body<'tcx> { self.body } - #[inline] pub fn basic_blocks(&self) -> &IndexVec> { &self.body.basic_blocks } - #[inline] pub fn dominators(&self) -> Dominators { dominators(self) } @@ -325,7 +311,6 @@ impl Deref for ReadOnlyBodyCache<'a, 'tcx> { impl Index for ReadOnlyBodyCache<'a, 'tcx> { type Output = BasicBlockData<'tcx>; - #[inline] fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { &self.body[index] } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ea858c80db79b..cc25ad0e22529 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -38,8 +38,7 @@ use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; -// FIXME(nashenas88) Cache only exported for use in librustc_mir/transform/check_unsafety.rs -pub use crate::mir::cache::{BodyCache, Cache, ReadOnlyBodyCache}; +pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache}; pub use crate::read_only; pub mod cache; From 598797c6e76c041b449a838d09f1c829b0adc437 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 20 Nov 2019 11:53:34 -0500 Subject: [PATCH 41/47] Remove unchecked inline attribute, remove unused functions, make chache mod private again --- src/librustc/mir/cache.rs | 72 ++++++++++++++------------------------- src/librustc/mir/mod.rs | 2 +- 2 files changed, 26 insertions(+), 48 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index fcab65cdfdd9f..30f383ff33116 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -32,45 +32,6 @@ impl<'a> HashStable> for Cache { } } -macro_rules! get_predecessors { - (mut $self:ident, $block:expr, $body:expr) => { - $self.predecessors_for($block, $body) - }; - ($self:ident, $block:expr, $body:expr) => { - $self.unwrap_predecessors_for($block) - }; -} - -macro_rules! impl_predecessor_locations { - ( ( $($pub:ident)? ) $name:ident $($mutability:ident)?) => { - $($pub)? fn $name<'a>( - &'a $($mutability)? self, - loc: Location, - body: &'a Body<'a> - ) -> impl Iterator + 'a { - let if_zero_locations = if loc.statement_index == 0 { - let predecessor_blocks = get_predecessors!($($mutability)? self, loc.block, body); - let num_predecessor_blocks = predecessor_blocks.len(); - Some( - (0..num_predecessor_blocks) - .map(move |i| predecessor_blocks[i]) - .map(move |bb| body.terminator_loc(bb)), - ) - } else { - None - }; - - let if_not_zero_locations = if loc.statement_index == 0 { - None - } else { - Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) - }; - - if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) - } - }; -} - impl Cache { pub fn new() -> Self { Self { @@ -104,17 +65,35 @@ impl Cache { self.predecessors.as_ref().unwrap() } - fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] { - &self.predecessors(body)[bb] - } - fn unwrap_predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] { &self.predecessors.as_ref().unwrap()[bb] } - impl_predecessor_locations!((pub) predecessor_locations mut); - - impl_predecessor_locations!(() unwrap_predecessor_locations); + fn unwrap_predecessor_locations<'a>( + &'a self, + loc: Location, + body: &'a Body<'a> + ) -> impl Iterator + 'a { + let if_zero_locations = if loc.statement_index == 0 { + let predecessor_blocks = self.unwrap_predecessors_for(loc.block); + let num_predecessor_blocks = predecessor_blocks.len(); + Some( + (0..num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| body.terminator_loc(bb)), + ) + } else { + None + }; + + let if_not_zero_locations = if loc.statement_index == 0 { + None + } else { + Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) + }; + + if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) + } pub fn basic_blocks_mut<'a, 'tcx>( &mut self, @@ -125,7 +104,6 @@ impl Cache { &mut body.basic_blocks } - #[inline] pub fn basic_blocks_and_local_decls_mut<'a, 'tcx>( &mut self, body: &'a mut Body<'tcx> diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index cc25ad0e22529..df5d4997e089a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -41,7 +41,7 @@ pub use crate::mir::interpret::AssertMessage; pub use crate::mir::cache::{BodyCache, ReadOnlyBodyCache}; pub use crate::read_only; -pub mod cache; +mod cache; pub mod interpret; pub mod mono; pub mod tcx; From 64654ce1f171faad7461db90435bffefe0390151 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 21 Nov 2019 10:50:52 -0500 Subject: [PATCH 42/47] Fix type errors created during rebasing --- src/librustc/mir/cache.rs | 9 +--- .../borrow_check/nll/type_check/mod.rs | 48 +++++++++---------- .../transform/check_consts/mod.rs | 4 +- .../transform/check_consts/qualifs.rs | 6 +-- .../transform/check_consts/resolver.rs | 2 +- .../transform/check_consts/validation.rs | 28 +++++------ src/librustc_mir/transform/mod.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 38 ++++++++------- 8 files changed, 67 insertions(+), 70 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 30f383ff33116..f61b7e74d340b 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -114,7 +114,7 @@ impl Cache { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, TypeFoldable)] pub struct BodyCache<'tcx> { cache: Cache, body: Body<'tcx>, @@ -302,10 +302,3 @@ impl_stable_hash_for!(struct BodyCache<'tcx> { cache, body, }); - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for BodyCache<'tcx> { - cache, - body - } -} diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 5a8fd3f707d6d..3fcc6e9e176b9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -220,7 +220,7 @@ fn type_check_internal<'a, 'tcx, R>( if !errors_reported { // if verifier failed, don't do further checks to avoid ICEs - checker.typeck_mir(&body); + checker.typeck_mir(body); } extra(&mut checker) @@ -588,7 +588,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { if !self.errors_reported { // if verifier failed, don't do further checks to avoid ICEs - self.cx.typeck_mir(&promoted_body); + self.cx.typeck_mir(promoted_body); } self.body = parent_body; @@ -1374,7 +1374,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx.tcx } - fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) { + fn check_stmt(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>, stmt: &Statement<'tcx>, location: Location) { debug!("check_stmt: {:?}", stmt); let tcx = self.tcx(); match stmt.kind { @@ -1406,9 +1406,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { _ => ConstraintCategory::Assignment, }; - let place_ty = place.ty(body, tcx).ty; + let place_ty = place.ty(body.body(), tcx).ty; let place_ty = self.normalize(place_ty, location); - let rv_ty = rv.ty(body, tcx); + let rv_ty = rv.ty(body.body(), tcx); let rv_ty = self.normalize(rv_ty, location); if let Err(terr) = self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category) @@ -1460,7 +1460,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ref place, variant_index, } => { - let place_type = place.ty(body, tcx).ty; + let place_type = place.ty(body.body(), tcx).ty; let adt = match place_type.kind { ty::Adt(adt, _) if adt.is_enum() => adt, _ => { @@ -1482,7 +1482,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; } StatementKind::AscribeUserType(box(ref place, ref projection), variance) => { - let place_ty = place.ty(body, tcx).ty; + let place_ty = place.ty(body.body(), tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, variance, @@ -1985,12 +1985,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { + fn check_rvalue(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { let tcx = self.tcx(); match rvalue { Rvalue::Aggregate(ak, ops) => { - self.check_aggregate_rvalue(body, rvalue, ak, ops, location) + self.check_aggregate_rvalue(&body, rvalue, ak, ops, location) } Rvalue::Repeat(operand, len) => if *len > 1 { @@ -1998,7 +1998,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // While this is located in `nll::typeck` this error is not an NLL error, it's // a required check to make sure that repeated elements implement `Copy`. let span = body.source_info(location).span; - let ty = operand.ty(body, tcx); + let ty = operand.ty(body.body(), tcx); if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { // To determine if `const_in_array_repeat_expressions` feature gate should // be mentioned, need to check if the rvalue is promotable. @@ -2052,7 +2052,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Cast(cast_kind, op, ty) => { match cast_kind { CastKind::Pointer(PointerCast::ReifyFnPointer) => { - let fn_sig = op.ty(body, tcx).fn_sig(tcx); + let fn_sig = op.ty(body.body(), tcx).fn_sig(tcx); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a @@ -2081,7 +2081,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { - let sig = match op.ty(body, tcx).kind { + let sig = match op.ty(body.body(), tcx).kind { ty::Closure(def_id, substs) => { substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx) } @@ -2107,7 +2107,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::UnsafeFnPointer) => { - let fn_sig = op.ty(body, tcx).fn_sig(tcx); + let fn_sig = op.ty(body.body(), tcx).fn_sig(tcx); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a @@ -2139,7 +2139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let &ty = ty; let trait_ref = ty::TraitRef { def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), - substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), + substs: tcx.mk_substs_trait(op.ty(body.body(), tcx), &[ty.into()]), }; self.prove_trait_ref( @@ -2150,7 +2150,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::MutToConstPointer) => { - let ty_from = match op.ty(body, tcx).kind { + let ty_from = match op.ty(body.body(), tcx).kind { ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mutable, @@ -2198,7 +2198,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ArrayToPointer) => { - let ty_from = op.ty(body, tcx); + let ty_from = op.ty(body.body(), tcx); let opt_ty_elem = match ty_from.kind { ty::RawPtr( @@ -2260,7 +2260,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Misc => { - let ty_from = op.ty(body, tcx); + let ty_from = op.ty(body.body(), tcx); let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(ty); match (cast_ty_from, cast_ty_to) { @@ -2318,7 +2318,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } Rvalue::Ref(region, _borrow_kind, borrowed_place) => { - self.add_reborrow_constraint(body, location, region, borrowed_place); + self.add_reborrow_constraint(&body, location, region, borrowed_place); } Rvalue::BinaryOp(BinOp::Eq, left, right) @@ -2327,9 +2327,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::BinaryOp(BinOp::Le, left, right) | Rvalue::BinaryOp(BinOp::Gt, left, right) | Rvalue::BinaryOp(BinOp::Ge, left, right) => { - let ty_left = left.ty(body, tcx); + let ty_left = left.ty(body.body(), tcx); if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.kind { - let ty_right = right.ty(body, tcx); + let ty_right = right.ty(body.body(), tcx); let common_ty = self.infcx.next_ty_var( TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, @@ -2754,12 +2754,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }) } - fn typeck_mir(&mut self, body: &Body<'tcx>) { + fn typeck_mir(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>) { self.last_span = body.span; debug!("run_on_mir: {:?}", body.span); for (local, local_decl) in body.local_decls.iter_enumerated() { - self.check_local(body, local, local_decl); + self.check_local(&body, local, local_decl); } for (block, block_data) in body.basic_blocks().iter_enumerated() { @@ -2775,8 +2775,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location.statement_index += 1; } - self.check_terminator(body, block_data.terminator(), location); - self.check_iscleanup(body, block_data); + self.check_terminator(&body, block_data.terminator(), location); + self.check_iscleanup(&body, block_data); } } diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs index 4d00aaf7abc21..7095b3fa0aa83 100644 --- a/src/librustc_mir/transform/check_consts/mod.rs +++ b/src/librustc_mir/transform/check_consts/mod.rs @@ -20,7 +20,7 @@ pub mod validation; /// Information about the item currently being const-checked, as well as a reference to the global /// context. pub struct Item<'mir, 'tcx> { - pub body: &'mir mir::Body<'tcx>, + pub body: mir::ReadOnlyBodyCache<'mir, 'tcx>, pub tcx: TyCtxt<'tcx>, pub def_id: DefId, pub param_env: ty::ParamEnv<'tcx>, @@ -31,7 +31,7 @@ impl Item<'mir, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, def_id: DefId, - body: &'mir mir::Body<'tcx>, + body: mir::ReadOnlyBodyCache<'mir, 'tcx>, ) -> Self { let param_env = tcx.param_env(def_id); let const_kind = ConstKind::for_item(tcx, def_id); diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 2d5a0a2afcd01..718988b26d8a5 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -51,7 +51,7 @@ pub trait Qualif { }); let qualif = base_qualif && Self::in_any_value_of_ty( cx, - Place::ty_from(place.base, proj_base, cx.body, cx.tcx) + Place::ty_from(place.base, proj_base, cx.body.body(), cx.tcx) .projection_ty(cx.tcx, elem) .ty, ); @@ -155,7 +155,7 @@ pub trait Qualif { // Special-case reborrows to be more like a copy of the reference. if let &[ref proj_base @ .., elem] = place.projection.as_ref() { if ProjectionElem::Deref == elem { - let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, cx.body.body(), cx.tcx).ty; if let ty::Ref(..) = base_ty.kind { return Self::in_place(cx, per_local, PlaceRef { base: &place.base, @@ -221,7 +221,7 @@ impl Qualif for HasMutInterior { Rvalue::Aggregate(ref kind, _) => { if let AggregateKind::Adt(def, ..) = **kind { if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() { - let ty = rvalue.ty(cx.body, cx.tcx); + let ty = rvalue.ty(cx.body.body(), cx.tcx); assert_eq!(Self::in_any_value_of_ty(cx, ty), true); return true; } diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index 8909ef7db683d..7db649e6ba0ac 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -77,7 +77,7 @@ where args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ) { - let return_ty = return_place.ty(self.item.body, self.item.tcx).ty; + let return_ty = return_place.ty(self.item.body.body(), self.item.tcx).ty; let qualif = Q::in_call( self.item, &|l| self.qualifs_per_local.contains(l), diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 783c64ece7371..63b100dc86dc1 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -39,9 +39,9 @@ impl QualifCursor<'a, 'mir, 'tcx, Q> { ) -> Self { let analysis = FlowSensitiveAnalysis::new(q, item); let results = - dataflow::Engine::new(item.tcx, item.body, item.def_id, dead_unwinds, analysis) + dataflow::Engine::new(item.tcx, &item.body, item.def_id, dead_unwinds, analysis) .iterate_to_fixpoint(); - let cursor = dataflow::ResultsCursor::new(item.body, results); + let cursor = dataflow::ResultsCursor::new(item.body.body(), results); let mut in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len()); for (local, decl) in item.body.local_decls.iter_enumerated() { @@ -172,17 +172,17 @@ impl Validator<'a, 'mir, 'tcx> { let indirectly_mutable = old_dataflow::do_dataflow( item.tcx, - item.body, + item.body.body(), item.def_id, &item.tcx.get_attrs(item.def_id), &dead_unwinds, - old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body, item.param_env), + old_dataflow::IndirectlyMutableLocals::new(item.tcx, item.body.body(), item.param_env), |_, local| old_dataflow::DebugFormatted::new(&local), ); let indirectly_mutable = old_dataflow::DataflowResultsCursor::new( indirectly_mutable, - item.body, + item.body.body(), ); let qualifs = Qualifs { @@ -208,7 +208,7 @@ impl Validator<'a, 'mir, 'tcx> { if use_min_const_fn_checks { // Enforce `min_const_fn` for stable `const fn`s. use crate::transform::qualify_min_const_fn::is_min_const_fn; - if let Err((span, err)) = is_min_const_fn(tcx, def_id, body) { + if let Err((span, err)) = is_min_const_fn(tcx, def_id, &body) { error_min_const_fn_violation(tcx, span, err); return; } @@ -230,7 +230,7 @@ impl Validator<'a, 'mir, 'tcx> { if should_check_for_sync { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - check_return_ty_is_sync(tcx, body, hir_id); + check_return_ty_is_sync(tcx, &body, hir_id); } } @@ -304,7 +304,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // Special-case reborrows to be more like a copy of a reference. if let Rvalue::Ref(_, kind, ref place) = *rvalue { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body, place) { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body.body(), place) { let ctx = match kind { BorrowKind::Shared => PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow, @@ -390,7 +390,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { - let operand_ty = operand.ty(self.body, self.tcx); + let operand_ty = operand.ty(self.body.body(), self.tcx); let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); @@ -401,7 +401,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body.body(), self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -475,7 +475,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty; + let base_ty = Place::ty_from(place_base, proj_base, self.body.body(), self.tcx).ty; if let ty::RawPtr(_) = base_ty.kind { if proj_base.is_empty() { if let (PlaceBase::Local(local), []) = (place_base, proj_base) { @@ -499,7 +499,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { ProjectionElem::Subslice {..} | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty; + let base_ty = Place::ty_from(place_base, proj_base, self.body.body(), self.tcx).ty; match base_ty.ty_adt_def() { Some(def) if def.is_union() => { self.check_op(ops::UnionAccess); @@ -548,7 +548,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match kind { TerminatorKind::Call { func, .. } => { - let fn_ty = func.ty(self.body, self.tcx); + let fn_ty = func.ty(self.body.body(), self.tcx); let def_id = match fn_ty.kind { ty::FnDef(def_id, _) => def_id, @@ -609,7 +609,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // Check to see if the type of this place can ever have a drop impl. If not, this // `Drop` terminator is frivolous. let ty_needs_drop = dropped_place - .ty(self.body, self.tcx) + .ty(self.body.body(), self.tcx) .ty .needs_drop(self.tcx, self.param_env); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 05d9787531b2a..3273588ec1a5f 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -205,7 +205,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs { } let item = check_consts::Item { - body, + body: body.unwrap_read_only(), tcx, def_id, const_kind, diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 49ae759fd5531..1a2eeb9025b94 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -63,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { let mut rpo = traversal::reverse_postorder(body); let (temps, all_candidates) = collect_temps_and_candidates(tcx, body, &mut rpo); - let promotable_candidates = validate_candidates(tcx, body, def_id, &temps, &all_candidates); + let promotable_candidates = validate_candidates(tcx, read_only, def_id, &temps, &all_candidates); let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); @@ -346,10 +346,14 @@ impl<'tcx> Validator<'_, 'tcx> { while let [proj_base @ .., elem] = place_projection { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. - let ty = - Place::ty_from(&place.base, proj_base, self.body, self.tcx) - .projection_ty(self.tcx, elem) - .ty; + let ty = Place::ty_from( + &place.base, + proj_base, + self.body.body(), + self.tcx + ) + .projection_ty(self.tcx, elem) + .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { has_mut_interior = false; break; @@ -368,7 +372,7 @@ impl<'tcx> Validator<'_, 'tcx> { } if let BorrowKind::Mut { .. } = kind { - let ty = place.ty(self.body, self.tcx).ty; + let ty = place.ty(self.body.body(), self.tcx).ty; // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] @@ -517,7 +521,7 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::Field(..) => { if self.const_kind.is_none() { let base_ty = - Place::ty_from(place.base, proj_base, self.body, self.tcx).ty; + Place::ty_from(place.base, proj_base, self.body.body(), self.tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No promotion of union field accesses. if def.is_union() { @@ -566,7 +570,7 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { match *rvalue { Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.const_kind.is_none() => { - let operand_ty = operand.ty(self.body, self.tcx); + let operand_ty = operand.ty(self.body.body(), self.tcx); let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); match (cast_in, cast_out) { @@ -580,7 +584,7 @@ impl<'tcx> Validator<'_, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) if self.const_kind.is_none() => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body.body(), self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -615,7 +619,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::Ref(_, kind, place) => { if let BorrowKind::Mut { .. } = kind { - let ty = place.ty(self.body, self.tcx).ty; + let ty = place.ty(self.body.body(), self.tcx).ty; // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] @@ -642,7 +646,7 @@ impl<'tcx> Validator<'_, 'tcx> { let mut place = place.as_ref(); if let [proj_base @ .., ProjectionElem::Deref] = &place.projection { let base_ty = - Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty; + Place::ty_from(&place.base, proj_base, self.body.body(), self.tcx).ty; if let ty::Ref(..) = base_ty.kind { place = PlaceRef { base: &place.base, @@ -668,7 +672,7 @@ impl<'tcx> Validator<'_, 'tcx> { while let [proj_base @ .., elem] = place_projection { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. - let ty = Place::ty_from(place.base, proj_base, self.body, self.tcx) + let ty = Place::ty_from(place.base, proj_base, self.body.body(), self.tcx) .projection_ty(self.tcx, elem) .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { @@ -701,7 +705,7 @@ impl<'tcx> Validator<'_, 'tcx> { callee: &Operand<'tcx>, args: &[Operand<'tcx>], ) -> Result<(), Unpromotable> { - let fn_ty = callee.ty(self.body, self.tcx); + let fn_ty = callee.ty(self.body.body(), self.tcx); if !self.explicit && self.const_kind.is_none() { if let ty::FnDef(def_id, _) = fn_ty.kind { @@ -737,7 +741,7 @@ impl<'tcx> Validator<'_, 'tcx> { // FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`. pub fn validate_candidates( tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, def_id: DefId, temps: &IndexVec, candidates: &[Candidate], @@ -1146,11 +1150,11 @@ pub fn promote_candidates<'tcx>( crate fn should_suggest_const_in_array_repeat_expressions_attribute<'tcx>( tcx: TyCtxt<'tcx>, mir_def_id: DefId, - body: &Body<'tcx>, + body: ReadOnlyBodyCache<'_, 'tcx>, operand: &Operand<'tcx>, ) -> bool { - let mut rpo = traversal::reverse_postorder(body); - let (temps, _) = collect_temps_and_candidates(tcx, body, &mut rpo); + let mut rpo = traversal::reverse_postorder(&body); + let (temps, _) = collect_temps_and_candidates(tcx, &body, &mut rpo); let validator = Validator { item: Item::new(tcx, mir_def_id, body), temps: &temps, From 9978574c9e18ac2feb2daf0758ec00e407be75ca Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sun, 24 Nov 2019 23:39:22 -0500 Subject: [PATCH 43/47] Fix rebasing errors, convert some BodyCache::body() calls to reborrows --- .../borrow_check/mutability_errors.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 28 +++++++++---------- .../transform/check_consts/qualifs.rs | 6 ++-- .../transform/check_consts/resolver.rs | 2 +- .../transform/check_consts/validation.rs | 16 +++++------ src/librustc_mir/transform/mod.rs | 1 + src/librustc_mir/transform/promote_consts.rs | 18 ++++++------ src/librustc_mir/transform/simplify_try.rs | 4 +-- 8 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 348c788eb33ae..e135f8d1be98d 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -365,7 +365,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Local(local), projection: [ProjectionElem::Deref], - } if self.body_cache.local_decls[*local].is_user_variable.is_some() => + } if self.body.local_decls[*local].is_user_variable() => { let local_decl = &self.body.local_decls[*local]; let suggestion = match local_decl.local_info { diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 3fcc6e9e176b9..b8a275e5b34b4 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1406,9 +1406,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { _ => ConstraintCategory::Assignment, }; - let place_ty = place.ty(body.body(), tcx).ty; + let place_ty = place.ty(&*body, tcx).ty; let place_ty = self.normalize(place_ty, location); - let rv_ty = rv.ty(body.body(), tcx); + let rv_ty = rv.ty(&*body, tcx); let rv_ty = self.normalize(rv_ty, location); if let Err(terr) = self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category) @@ -1460,7 +1460,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ref place, variant_index, } => { - let place_type = place.ty(body.body(), tcx).ty; + let place_type = place.ty(&*body, tcx).ty; let adt = match place_type.kind { ty::Adt(adt, _) if adt.is_enum() => adt, _ => { @@ -1482,7 +1482,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; } StatementKind::AscribeUserType(box(ref place, ref projection), variance) => { - let place_ty = place.ty(body.body(), tcx).ty; + let place_ty = place.ty(&*body, tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, variance, @@ -1998,7 +1998,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // While this is located in `nll::typeck` this error is not an NLL error, it's // a required check to make sure that repeated elements implement `Copy`. let span = body.source_info(location).span; - let ty = operand.ty(body.body(), tcx); + let ty = operand.ty(&*body, tcx); if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { // To determine if `const_in_array_repeat_expressions` feature gate should // be mentioned, need to check if the rvalue is promotable. @@ -2052,7 +2052,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Cast(cast_kind, op, ty) => { match cast_kind { CastKind::Pointer(PointerCast::ReifyFnPointer) => { - let fn_sig = op.ty(body.body(), tcx).fn_sig(tcx); + let fn_sig = op.ty(&*body, tcx).fn_sig(tcx); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a @@ -2081,7 +2081,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { - let sig = match op.ty(body.body(), tcx).kind { + let sig = match op.ty(&*body, tcx).kind { ty::Closure(def_id, substs) => { substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx) } @@ -2107,7 +2107,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::UnsafeFnPointer) => { - let fn_sig = op.ty(body.body(), tcx).fn_sig(tcx); + let fn_sig = op.ty(&*body, tcx).fn_sig(tcx); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a @@ -2139,7 +2139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let &ty = ty; let trait_ref = ty::TraitRef { def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), - substs: tcx.mk_substs_trait(op.ty(body.body(), tcx), &[ty.into()]), + substs: tcx.mk_substs_trait(op.ty(&*body, tcx), &[ty.into()]), }; self.prove_trait_ref( @@ -2150,7 +2150,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::MutToConstPointer) => { - let ty_from = match op.ty(body.body(), tcx).kind { + let ty_from = match op.ty(&*body, tcx).kind { ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mutable, @@ -2198,7 +2198,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ArrayToPointer) => { - let ty_from = op.ty(body.body(), tcx); + let ty_from = op.ty(&*body, tcx); let opt_ty_elem = match ty_from.kind { ty::RawPtr( @@ -2260,7 +2260,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Misc => { - let ty_from = op.ty(body.body(), tcx); + let ty_from = op.ty(&*body, tcx); let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(ty); match (cast_ty_from, cast_ty_to) { @@ -2327,9 +2327,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::BinaryOp(BinOp::Le, left, right) | Rvalue::BinaryOp(BinOp::Gt, left, right) | Rvalue::BinaryOp(BinOp::Ge, left, right) => { - let ty_left = left.ty(body.body(), tcx); + let ty_left = left.ty(&*body, tcx); if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.kind { - let ty_right = right.ty(body.body(), tcx); + let ty_right = right.ty(&*body, tcx); let common_ty = self.infcx.next_ty_var( TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 718988b26d8a5..62b4a4ccc9894 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -51,7 +51,7 @@ pub trait Qualif { }); let qualif = base_qualif && Self::in_any_value_of_ty( cx, - Place::ty_from(place.base, proj_base, cx.body.body(), cx.tcx) + Place::ty_from(place.base, proj_base, &*cx.body, cx.tcx) .projection_ty(cx.tcx, elem) .ty, ); @@ -155,7 +155,7 @@ pub trait Qualif { // Special-case reborrows to be more like a copy of the reference. if let &[ref proj_base @ .., elem] = place.projection.as_ref() { if ProjectionElem::Deref == elem { - let base_ty = Place::ty_from(&place.base, proj_base, cx.body.body(), cx.tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, &*cx.body, cx.tcx).ty; if let ty::Ref(..) = base_ty.kind { return Self::in_place(cx, per_local, PlaceRef { base: &place.base, @@ -221,7 +221,7 @@ impl Qualif for HasMutInterior { Rvalue::Aggregate(ref kind, _) => { if let AggregateKind::Adt(def, ..) = **kind { if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() { - let ty = rvalue.ty(cx.body.body(), cx.tcx); + let ty = rvalue.ty(&*cx.body, cx.tcx); assert_eq!(Self::in_any_value_of_ty(cx, ty), true); return true; } diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index 7db649e6ba0ac..9004c5be987fd 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -77,7 +77,7 @@ where args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ) { - let return_ty = return_place.ty(self.item.body.body(), self.item.tcx).ty; + let return_ty = return_place.ty(&*self.item.body, self.item.tcx).ty; let qualif = Q::in_call( self.item, &|l| self.qualifs_per_local.contains(l), diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 63b100dc86dc1..86e1d6584fc2e 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -172,7 +172,7 @@ impl Validator<'a, 'mir, 'tcx> { let indirectly_mutable = old_dataflow::do_dataflow( item.tcx, - item.body.body(), + &*item.body, item.def_id, &item.tcx.get_attrs(item.def_id), &dead_unwinds, @@ -304,7 +304,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // Special-case reborrows to be more like a copy of a reference. if let Rvalue::Ref(_, kind, ref place) = *rvalue { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body.body(), place) { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, &*self.body, place) { let ctx = match kind { BorrowKind::Shared => PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow, @@ -390,7 +390,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { - let operand_ty = operand.ty(self.body.body(), self.tcx); + let operand_ty = operand.ty(&*self.body, self.tcx); let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); @@ -401,7 +401,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body.body(), self.tcx).kind { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(&*self.body, self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -475,7 +475,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(place_base, proj_base, self.body.body(), self.tcx).ty; + let base_ty = Place::ty_from(place_base, proj_base, &*self.body, self.tcx).ty; if let ty::RawPtr(_) = base_ty.kind { if proj_base.is_empty() { if let (PlaceBase::Local(local), []) = (place_base, proj_base) { @@ -499,7 +499,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { ProjectionElem::Subslice {..} | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - let base_ty = Place::ty_from(place_base, proj_base, self.body.body(), self.tcx).ty; + let base_ty = Place::ty_from(place_base, proj_base, &*self.body, self.tcx).ty; match base_ty.ty_adt_def() { Some(def) if def.is_union() => { self.check_op(ops::UnionAccess); @@ -548,7 +548,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match kind { TerminatorKind::Call { func, .. } => { - let fn_ty = func.ty(self.body.body(), self.tcx); + let fn_ty = func.ty(&*self.body, self.tcx); let def_id = match fn_ty.kind { ty::FnDef(def_id, _) => def_id, @@ -609,7 +609,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // Check to see if the type of this place can ever have a drop impl. If not, this // `Drop` terminator is frivolous. let ty_needs_drop = dropped_place - .ty(self.body.body(), self.tcx) + .ty(&*self.body, self.tcx) .ty .needs_drop(self.tcx, self.param_env); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 3273588ec1a5f..df4cb7615336a 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -231,6 +231,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { &rustc_peek::SanityCheck, &uniform_array_move_out::UniformArrayMoveOut, ]); + body.ensure_predecessors(); tcx.alloc_steal_mir(body) } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 1a2eeb9025b94..4af9ccb83aced 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -349,7 +349,7 @@ impl<'tcx> Validator<'_, 'tcx> { let ty = Place::ty_from( &place.base, proj_base, - self.body.body(), + &*self.body, self.tcx ) .projection_ty(self.tcx, elem) @@ -372,7 +372,7 @@ impl<'tcx> Validator<'_, 'tcx> { } if let BorrowKind::Mut { .. } = kind { - let ty = place.ty(self.body.body(), self.tcx).ty; + let ty = place.ty(&*self.body, self.tcx).ty; // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] @@ -521,7 +521,7 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::Field(..) => { if self.const_kind.is_none() { let base_ty = - Place::ty_from(place.base, proj_base, self.body.body(), self.tcx).ty; + Place::ty_from(place.base, proj_base, &*self.body, self.tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No promotion of union field accesses. if def.is_union() { @@ -570,7 +570,7 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { match *rvalue { Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.const_kind.is_none() => { - let operand_ty = operand.ty(self.body.body(), self.tcx); + let operand_ty = operand.ty(&*self.body, self.tcx); let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); match (cast_in, cast_out) { @@ -584,7 +584,7 @@ impl<'tcx> Validator<'_, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) if self.const_kind.is_none() => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body.body(), self.tcx).kind { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(&*self.body, self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -619,7 +619,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::Ref(_, kind, place) => { if let BorrowKind::Mut { .. } = kind { - let ty = place.ty(self.body.body(), self.tcx).ty; + let ty = place.ty(&*self.body, self.tcx).ty; // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] @@ -646,7 +646,7 @@ impl<'tcx> Validator<'_, 'tcx> { let mut place = place.as_ref(); if let [proj_base @ .., ProjectionElem::Deref] = &place.projection { let base_ty = - Place::ty_from(&place.base, proj_base, self.body.body(), self.tcx).ty; + Place::ty_from(&place.base, proj_base, &*self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.kind { place = PlaceRef { base: &place.base, @@ -672,7 +672,7 @@ impl<'tcx> Validator<'_, 'tcx> { while let [proj_base @ .., elem] = place_projection { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. - let ty = Place::ty_from(place.base, proj_base, self.body.body(), self.tcx) + let ty = Place::ty_from(place.base, proj_base, &*self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { @@ -705,7 +705,7 @@ impl<'tcx> Validator<'_, 'tcx> { callee: &Operand<'tcx>, args: &[Operand<'tcx>], ) -> Result<(), Unpromotable> { - let fn_ty = callee.ty(self.body.body(), self.tcx); + let fn_ty = callee.ty(&*self.body, self.tcx); if !self.explicit && self.const_kind.is_none() { if let ty::FnDef(def_id, _) = fn_ty.kind { diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs index 9dc5daa9b0709..2235de9a1533a 100644 --- a/src/librustc_mir/transform/simplify_try.rs +++ b/src/librustc_mir/transform/simplify_try.rs @@ -33,7 +33,7 @@ use itertools::Itertools as _; pub struct SimplifyArmIdentity; impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { - fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); for bb in basic_blocks { // Need 3 statements: @@ -151,7 +151,7 @@ fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarFie pub struct SimplifyBranchSame; impl<'tcx> MirPass<'tcx> for SimplifyBranchSame { - fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyCache<'tcx>) { let mut did_remove_blocks = false; let bbs = body.basic_blocks_mut(); for bb_idx in bbs.indices() { From acb90eb014eff6f4e4de2c3a651c68086ad4c466 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 25 Nov 2019 00:28:24 -0500 Subject: [PATCH 44/47] Fix tidy issues --- .../borrow_check/nll/type_check/mod.rs | 90 +++++++++++-------- src/librustc_mir/transform/promote_consts.rs | 3 +- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index b8a275e5b34b4..a554867389e12 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1,57 +1,59 @@ //! This pass type-checks the MIR to ensure it is not broken. -use crate::borrow_check::borrow_set::BorrowSet; -use crate::borrow_check::location::LocationTable; -use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint}; -use crate::borrow_check::nll::member_constraints::MemberConstraintSet; -use crate::borrow_check::nll::facts::AllFacts; -use crate::borrow_check::nll::region_infer::values::LivenessValues; -use crate::borrow_check::nll::region_infer::values::PlaceholderIndex; -use crate::borrow_check::nll::region_infer::values::PlaceholderIndices; -use crate::borrow_check::nll::region_infer::values::RegionValueElements; -use crate::borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; -use crate::borrow_check::nll::renumber; -use crate::borrow_check::nll::type_check::free_region_relations::{ - CreateResult, UniversalRegionRelations, -}; -use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions}; -use crate::borrow_check::nll::ToRegionVid; -use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute; -use crate::dataflow::move_paths::MoveData; -use crate::dataflow::FlowAtLocation; -use crate::dataflow::MaybeInitializedPlaces; +use std::{fmt, iter, mem}; +use std::rc::Rc; + use either::Either; + use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; use rustc::infer::canonical::QueryRegionConstraints; use rustc::infer::outlives::env::RegionBoundPairs; -use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc::mir::*; use rustc::mir::interpret::PanicInfo; use rustc::mir::tcx::PlaceTy; -use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext}; -use rustc::mir::*; +use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; +use rustc::traits::{self, ObligationCause, PredicateObligations}; +use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; -use rustc::traits::query::{Fallible, NoSolution}; -use rustc::traits::{self, ObligationCause, PredicateObligations}; -use rustc::ty::adjustment::{PointerCast}; -use rustc::ty::cast::CastTy; -use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{Subst, SubstsRef, GenericArgKind, UserSubsts}; use rustc::ty::{ - self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, UserType, - CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, + self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPolyTraitRef, Ty, + TyCtxt, UserType, UserTypeAnnotationIndex, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_index::vec::{IndexVec, Idx}; +use rustc::ty::adjustment::PointerCast; +use rustc::ty::cast::CastTy; +use rustc::ty::fold::TypeFoldable; use rustc::ty::layout::VariantIdx; -use std::rc::Rc; -use std::{fmt, iter, mem}; -use syntax_pos::{Span, DUMMY_SP}; - +use rustc::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_error_codes::*; +use rustc_index::vec::{Idx, IndexVec}; +use syntax_pos::{DUMMY_SP, Span}; + +use crate::borrow_check::borrow_set::BorrowSet; +use crate::borrow_check::location::LocationTable; +use crate::borrow_check::nll::constraints::{OutlivesConstraint, OutlivesConstraintSet}; +use crate::borrow_check::nll::facts::AllFacts; +use crate::borrow_check::nll::member_constraints::MemberConstraintSet; +use crate::borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; +use crate::borrow_check::nll::region_infer::values::LivenessValues; +use crate::borrow_check::nll::region_infer::values::PlaceholderIndex; +use crate::borrow_check::nll::region_infer::values::PlaceholderIndices; +use crate::borrow_check::nll::region_infer::values::RegionValueElements; +use crate::borrow_check::nll::renumber; +use crate::borrow_check::nll::ToRegionVid; +use crate::borrow_check::nll::type_check::free_region_relations::{ + CreateResult, UniversalRegionRelations, +}; +use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions}; +use crate::dataflow::FlowAtLocation; +use crate::dataflow::MaybeInitializedPlaces; +use crate::dataflow::move_paths::MoveData; +use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -1374,7 +1376,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx.tcx } - fn check_stmt(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>, stmt: &Statement<'tcx>, location: Location) { + fn check_stmt( + &mut self, + body: ReadOnlyBodyCache<'_, 'tcx>, + stmt: &Statement<'tcx>, + location: Location) + { debug!("check_stmt: {:?}", stmt); let tcx = self.tcx(); match stmt.kind { @@ -1985,7 +1992,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - fn check_rvalue(&mut self, body: ReadOnlyBodyCache<'_, 'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { + fn check_rvalue( + &mut self, + body: ReadOnlyBodyCache<'_, 'tcx>, + rvalue: &Rvalue<'tcx>, + location: Location) + { let tcx = self.tcx(); match rvalue { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4af9ccb83aced..4c5b374059de0 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -63,7 +63,8 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { let mut rpo = traversal::reverse_postorder(body); let (temps, all_candidates) = collect_temps_and_candidates(tcx, body, &mut rpo); - let promotable_candidates = validate_candidates(tcx, read_only, def_id, &temps, &all_candidates); + let promotable_candidates + = validate_candidates(tcx, read_only, def_id, &temps, &all_candidates); let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); From 38bd3a23421e3f772004e0886ad80848d8bd03b6 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 27 Nov 2019 10:54:49 -0500 Subject: [PATCH 45/47] Use new HashStable proc macro --- src/librustc/mir/cache.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index f61b7e74d340b..b8ef4f753f368 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -114,7 +114,7 @@ impl Cache { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, TypeFoldable)] +#[derive(Clone, Debug, HashStable, RustcEncodable, RustcDecodable, TypeFoldable)] pub struct BodyCache<'tcx> { cache: Cache, body: Body<'tcx>, @@ -297,8 +297,3 @@ impl Index for ReadOnlyBodyCache<'a, 'tcx> { CloneTypeFoldableAndLiftImpls! { Cache, } - -impl_stable_hash_for!(struct BodyCache<'tcx> { - cache, - body, -}); From 6123478f2a7f51b5fc7eecbd6d6498ae3ddbadfb Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 29 Nov 2019 18:36:16 -0500 Subject: [PATCH 46/47] Fix issues caused during rebasing --- src/librustc_codegen_ssa/mir/mod.rs | 2 +- src/librustc_mir/shim.rs | 4 ++-- src/librustc_mir/transform/promote_consts.rs | 2 +- src/librustc_mir/util/def_use.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 9374c829e4f96..8b60904081e66 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -156,7 +156,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }).collect(); let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); - let mir_body: &Body<'_> = &mir; + let mir_body: &Body<'_> = mir.body(); let mut fx = FunctionCx { instance, mir, diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 0636d254c2f39..680f75eb84e2c 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -199,7 +199,7 @@ fn build_drop_shim<'tcx>( block(&mut blocks, TerminatorKind::Goto { target: return_block }); block(&mut blocks, TerminatorKind::Return); - let mut body = new_body( + let body = new_body( blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), @@ -914,7 +914,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &BodyCache<'_> { is_cleanup: false }; - let mut body = new_body( + let body = new_body( IndexVec::from_elem_n(start_block, 1), local_decls, sig.inputs().len(), diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4c5b374059de0..73d224a944c2f 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -64,7 +64,7 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { let (temps, all_candidates) = collect_temps_and_candidates(tcx, body, &mut rpo); let promotable_candidates - = validate_candidates(tcx, read_only, def_id, &temps, &all_candidates); + = validate_candidates(tcx, read_only!(body), def_id, &temps, &all_candidates); let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 632e92d67200a..1907e9bdc9746 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -62,7 +62,7 @@ impl DefUseAnalysis { let mut visitor = MutateUseVisitor::new(local, new_local, tcx); let info = &self.info[local]; for place_use in &info.defs_and_uses { - visitor.visit_location(body_cache, place_use.location) + visitor.visit_location(body, place_use.location) } // Update debuginfo as well, alongside defs/uses. for &i in &info.var_debug_info_indices { From 3eaad564d25402013bdf5591c453c916b49cdf93 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 2 Dec 2019 09:40:03 -0500 Subject: [PATCH 47/47] Fix issues caused during rebasing --- src/librustc_mir/transform/check_consts/validation.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 86e1d6584fc2e..9d477bfbae81f 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -342,7 +342,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { | Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place) | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => { - let ty = place.ty(self.body, self.tcx).ty; + let ty = place.ty(&*self.body, self.tcx).ty; let is_allowed = match ty.kind { // Inside a `static mut`, `&mut [...]` is allowed. ty::Array(..) | ty::Slice(_) if self.const_kind() == ConstKind::StaticMut diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 73d224a944c2f..c99824bd35647 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -1086,7 +1086,6 @@ pub fn promote_candidates<'tcx>( // FIXME: maybe try to filter this to avoid blowing up // memory usage? body.source_scopes.clone(), - body.source_scope_local_data.clone(), initial_locals, IndexVec::new(), 0,