diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index f25075f7912..7394d0081ed 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -55,7 +55,7 @@ macro_rules! newtype_index { pub struct Mir<'tcx> { /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock` /// that indexes into this vector. - pub basic_blocks: IndexVec>, + basic_blocks: IndexVec>, /// List of visibility (lexical) scopes; these are referenced by statements /// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`. @@ -94,18 +94,37 @@ pub struct Mir<'tcx> { pub const START_BLOCK: BasicBlock = BasicBlock(0); impl<'tcx> Mir<'tcx> { - pub fn all_basic_blocks(&self) -> Vec { - (0..self.basic_blocks.len()) - .map(|i| BasicBlock::new(i)) - .collect() + pub fn new(basic_blocks: IndexVec>, + visibility_scopes: IndexVec, + promoted: IndexVec>, + return_ty: FnOutput<'tcx>, + var_decls: IndexVec>, + arg_decls: IndexVec>, + temp_decls: IndexVec>, + upvar_decls: Vec, + span: Span) -> Self + { + Mir { + basic_blocks: basic_blocks, + visibility_scopes: visibility_scopes, + promoted: promoted, + return_ty: return_ty, + var_decls: var_decls, + arg_decls: arg_decls, + temp_decls: temp_decls, + upvar_decls: upvar_decls, + span: span + } } - pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<'tcx> { - &self.basic_blocks[bb] + #[inline] + pub fn basic_blocks(&self) -> &IndexVec> { + &self.basic_blocks } - pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<'tcx> { - &mut self.basic_blocks[bb] + #[inline] + pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { + &mut self.basic_blocks } } @@ -114,14 +133,14 @@ impl<'tcx> Index for Mir<'tcx> { #[inline] fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { - self.basic_block_data(index) + &self.basic_blocks()[index] } } impl<'tcx> IndexMut for Mir<'tcx> { #[inline] fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> { - self.basic_block_data_mut(index) + &mut self.basic_blocks_mut()[index] } } diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 73481b6643d..1af5123b4df 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { Preorder { mir: mir, - visited: BitVector::new(mir.basic_blocks.len()), + visited: BitVector::new(mir.basic_blocks().len()), worklist: worklist } } @@ -64,7 +64,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { continue; } - let data = self.mir.basic_block_data(idx); + let data = &self.mir[idx]; if let Some(ref term) = data.terminator { for &succ in term.successors().iter() { @@ -107,12 +107,12 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> { let mut po = Postorder { mir: mir, - visited: BitVector::new(mir.basic_blocks.len()), + visited: BitVector::new(mir.basic_blocks().len()), visit_stack: Vec::new() }; - let data = po.mir.basic_block_data(root); + let data = &po.mir[root]; if let Some(ref term) = data.terminator { po.visited.insert(root.index()); @@ -186,9 +186,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { }; if self.visited.insert(bb.index()) { - let data = self.mir.basic_block_data(bb); - - if let Some(ref term) = data.terminator { + if let Some(ref term) = self.mir[bb].terminator { let succs = term.successors().into_owned().into_iter(); self.visit_stack.push((bb, succs)); } @@ -210,10 +208,7 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { self.traverse_successor(); } - next.map(|(bb, _)| { - let data = self.mir.basic_block_data(bb); - (bb, data) - }) + next.map(|(bb, _)| (bb, &self.mir[bb])) } } @@ -279,9 +274,6 @@ impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> { if self.idx == 0 { return None; } self.idx -= 1; - self.blocks.get(self.idx).map(|&bb| { - let data = self.mir.basic_block_data(bb); - (bb, data) - }) + self.blocks.get(self.idx).map(|&bb| (bb, &self.mir[bb])) } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index f37f6386bd8..fcc7715a8af 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -252,42 +252,30 @@ macro_rules! make_mir_visitor { fn super_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) { - let Mir { - ref $($mutability)* basic_blocks, - ref $($mutability)* visibility_scopes, - promoted: _, // Visited by passes separately. - ref $($mutability)* return_ty, - ref $($mutability)* var_decls, - ref $($mutability)* arg_decls, - ref $($mutability)* temp_decls, - upvar_decls: _, - ref $($mutability)* span, - } = *mir; - - for (index, data) in basic_blocks.into_iter().enumerate() { + for index in 0..mir.basic_blocks().len() { let block = BasicBlock::new(index); - self.visit_basic_block_data(block, data); + self.visit_basic_block_data(block, &$($mutability)* mir[block]); } - for scope in visibility_scopes { + for scope in &$($mutability)* mir.visibility_scopes { self.visit_visibility_scope_data(scope); } - self.visit_fn_output(return_ty); + self.visit_fn_output(&$($mutability)* mir.return_ty); - for var_decl in var_decls { + for var_decl in &$($mutability)* mir.var_decls { self.visit_var_decl(var_decl); } - for arg_decl in arg_decls { + for arg_decl in &$($mutability)* mir.arg_decls { self.visit_arg_decl(arg_decl); } - for temp_decl in temp_decls { + for temp_decl in &$($mutability)* mir.temp_decls { self.visit_temp_decl(temp_decl); } - self.visit_span(span); + self.visit_span(&$($mutability)* mir.span); } fn super_basic_block_data(&mut self, diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs index 3b04f34af2b..91be50d11f9 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs @@ -127,7 +127,7 @@ pub type Node = BasicBlock; pub struct Edge { source: BasicBlock, index: usize } fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec { - let succ_len = mir.basic_block_data(bb).terminator().successors().len(); + let succ_len = mir[bb].terminator().successors().len(); (0..succ_len).map(|index| Edge { source: bb, index: index}).collect() } @@ -313,17 +313,20 @@ impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P> type Node = Node; type Edge = Edge; fn nodes(&self) -> dot::Nodes { - self.mbcx.mir().all_basic_blocks().into_cow() + self.mbcx.mir() + .basic_blocks() + .indices() + .collect::>() + .into_cow() } fn edges(&self) -> dot::Edges { let mir = self.mbcx.mir(); - let blocks = mir.all_basic_blocks(); // base initial capacity on assumption every block has at // least one outgoing edge (Which should be true for all // blocks but one, the exit-block). - let mut edges = Vec::with_capacity(blocks.len()); - for bb in blocks { + let mut edges = Vec::with_capacity(mir.basic_blocks().len()); + for bb in mir.basic_blocks().indices() { let outgoing = outgoing(mir, bb); edges.extend(outgoing.into_iter()); } @@ -336,6 +339,6 @@ impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P> fn target(&self, edge: &Edge) -> Node { let mir = self.mbcx.mir(); - mir.basic_block_data(edge.source).terminator().successors()[edge.index] + mir[edge.source].terminator().successors()[edge.index] } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index fe399b97908..932b7485201 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -426,7 +426,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { bb: repr::BasicBlock, idx: usize) { let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data); - let stmt = &mir.basic_block_data(bb).statements[idx]; + let stmt = &mir[bb].statements[idx]; let loc_map = &move_data.loc_map; let path_map = &move_data.path_map; let rev_lookup = &move_data.rev_lookup; @@ -466,7 +466,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { statements_len: usize) { let (mir, move_data) = (self.mir, &ctxt.move_data); - let term = mir.basic_block_data(bb).terminator.as_ref().unwrap(); + let term = mir[bb].terminator(); let loc_map = &move_data.loc_map; let loc = Location { block: bb, index: statements_len }; debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs index 3b6121449b4..d42103d5d25 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs @@ -83,11 +83,10 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> self.flow_state.operator.start_block_effect(&self.ctxt, sets); } - for bb in self.mir.all_basic_blocks() { + for (bb, data) in self.mir.basic_blocks().iter_enumerated() { let &repr::BasicBlockData { ref statements, ref terminator, - is_cleanup: _ } = - self.mir.basic_block_data(bb); + is_cleanup: _ } = data; let sets = &mut self.flow_state.sets.for_block(bb.index()); for j_stmt in 0..statements.len() { @@ -114,7 +113,7 @@ impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> fn walk_cfg(&mut self, in_out: &mut IdxSet) { let mir = self.builder.mir; - for (bb_idx, bb_data) in mir.basic_blocks.iter().enumerate() { + for (bb_idx, bb_data) in mir.basic_blocks().iter().enumerate() { let builder = &mut self.builder; { let sets = builder.flow_state.sets.for_block(bb_idx); @@ -398,7 +397,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> // (now rounded up to multiple of word size) let bits_per_block = words_per_block * usize_bits; - let num_blocks = mir.basic_blocks.len(); + let num_blocks = mir.basic_blocks().len(); let num_overall = num_blocks * bits_per_block; let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall)); diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index 735fffb8ef8..c8d3ff01b6c 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -50,8 +50,7 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `dataflow::build_sets`. (But note it is doing non-standard // stuff, so such generalization may not be realistic.) - let blocks = mir.all_basic_blocks(); - 'next_block: for bb in blocks { + for bb in mir.basic_blocks().indices() { each_block(tcx, mir, flow_ctxt, results, bb); } } @@ -64,10 +63,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, O: BitDenotation, Idx=MovePathIndex> { let move_data = &ctxt.move_data; - let bb_data = mir.basic_block_data(bb); - let &repr::BasicBlockData { ref statements, - ref terminator, - is_cleanup: _ } = bb_data; + let repr::BasicBlockData { ref statements, + ref terminator, + is_cleanup: _ } = mir[bb]; let (args, span) = match is_rustc_peek(tcx, terminator) { Some(args_and_span) => args_and_span, diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index d4cdb695ffb..6ecf4a66d62 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -225,8 +225,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn collect_drop_flags(&mut self) { - for bb in self.mir.all_basic_blocks() { - let data = self.mir.basic_block_data(bb); + for (bb, data) in self.mir.basic_blocks().iter_enumerated() { let terminator = data.terminator(); let location = match terminator.kind { TerminatorKind::Drop { ref location, .. } | @@ -262,8 +261,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn elaborate_drops(&mut self) { - for bb in self.mir.all_basic_blocks() { - let data = self.mir.basic_block_data(bb); + for (bb, data) in self.mir.basic_blocks().iter_enumerated() { let loc = Location { block: bb, index: data.statements.len() }; let terminator = data.terminator(); @@ -323,7 +321,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { unwind: Option) { let bb = loc.block; - let data = self.mir.basic_block_data(bb); + let data = &self.mir[bb]; let terminator = data.terminator(); let assign = Statement { @@ -942,8 +940,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn drop_flags_for_fn_rets(&mut self) { - for bb in self.mir.all_basic_blocks() { - let data = self.mir.basic_block_data(bb); + for (bb, data) in self.mir.basic_blocks().iter_enumerated() { if let TerminatorKind::Call { destination: Some((ref lv, tgt)), cleanup: Some(_), .. } = data.terminator().kind { @@ -975,8 +972,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // drop flags by themselves, to avoid the drop flags being // clobbered before they are read. - for bb in self.mir.all_basic_blocks() { - let data = self.mir.basic_block_data(bb); + for (bb, data) in self.mir.basic_blocks().iter_enumerated() { debug!("drop_flags_for_locs({:?})", data); for i in 0..(data.statements.len()+1) { debug!("drop_flag_for_locs: stmt {}", i); diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 110633b1388..7a3f467a627 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -519,9 +519,9 @@ enum StmtKind { fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveData<'tcx> { use self::StmtKind as SK; - let bbs = mir.all_basic_blocks(); - let mut moves = Vec::with_capacity(bbs.len()); - let mut loc_map: Vec<_> = iter::repeat(Vec::new()).take(bbs.len()).collect(); + let bb_count = mir.basic_blocks().len(); + let mut moves = vec![]; + let mut loc_map: Vec<_> = iter::repeat(Vec::new()).take(bb_count).collect(); let mut path_map = Vec::new(); // this is mutable only because we will move it to and fro' the @@ -541,22 +541,21 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD assert!(mir.var_decls.len() <= ::std::u32::MAX as usize); assert!(mir.arg_decls.len() <= ::std::u32::MAX as usize); assert!(mir.temp_decls.len() <= ::std::u32::MAX as usize); - for (var, _) in mir.var_decls.iter_enumerated() { + for var in mir.var_decls.indices() { let path_idx = builder.move_path_for(&Lvalue::Var(var)); path_map.fill_to(path_idx.index()); } - for (arg, _) in mir.arg_decls.iter_enumerated() { + for arg in mir.arg_decls.indices() { let path_idx = builder.move_path_for(&Lvalue::Arg(arg)); path_map.fill_to(path_idx.index()); } - for (temp, _) in mir.temp_decls.iter_enumerated() { + for temp in mir.temp_decls.indices() { let path_idx = builder.move_path_for(&Lvalue::Temp(temp)); path_map.fill_to(path_idx.index()); } - for bb in bbs { + for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { let loc_map_bb = &mut loc_map[bb.index()]; - let bb_data = mir.basic_block_data(bb); debug_assert!(loc_map_bb.len() == 0); let len = bb_data.statements.len(); diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 53dc62d5f71..270b16fcf49 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -111,7 +111,7 @@ pub fn borrowck_mir<'a, 'tcx: 'a>( flow_uninits: flow_uninits, }; - for bb in mir.all_basic_blocks() { + for bb in mir.basic_blocks().indices() { mbcx.process_basic_block(bb); } @@ -180,8 +180,8 @@ pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> { impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> { fn process_basic_block(&mut self, bb: BasicBlock) { - let &BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = - self.mir.basic_block_data(bb); + let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = + self.mir[bb]; for stmt in statements { self.process_statement(bb, stmt); } @@ -337,8 +337,8 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( |moi| callback(moi, DropFlagState::Absent)) } - let bb = mir.basic_block_data(loc.block); - match bb.statements.get(loc.index) { + let block = &mir[loc.block]; + match block.statements.get(loc.index) { Some(stmt) => match stmt.kind { repr::StatementKind::Assign(ref lvalue, _) => { debug!("drop_flag_effects: assignment {:?}", stmt); @@ -348,8 +348,8 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( } }, None => { - debug!("drop_flag_effects: replace {:?}", bb.terminator()); - match bb.terminator().kind { + debug!("drop_flag_effects: replace {:?}", block.terminator()); + match block.terminator().kind { repr::TerminatorKind::DropAndReplace { ref location, .. } => { on_all_children_bits(tcx, mir, move_data, move_data.rev_lookup.find(location), diff --git a/src/librustc_borrowck/borrowck/mir/patch.rs b/src/librustc_borrowck/borrowck/mir/patch.rs index 0e342e0c293..417e719a9dc 100644 --- a/src/librustc_borrowck/borrowck/mir/patch.rs +++ b/src/librustc_borrowck/borrowck/mir/patch.rs @@ -28,7 +28,7 @@ pub struct MirPatch<'tcx> { impl<'tcx> MirPatch<'tcx> { pub fn new(mir: &Mir<'tcx>) -> Self { let mut result = MirPatch { - patch_map: IndexVec::from_elem(None, &mir.basic_blocks), + patch_map: IndexVec::from_elem(None, mir.basic_blocks()), new_blocks: vec![], new_temps: vec![], new_statements: vec![], @@ -43,13 +43,12 @@ impl<'tcx> MirPatch<'tcx> { let mut resume_block = None; let mut resume_stmt_block = None; - for block in mir.all_basic_blocks() { - let data = mir.basic_block_data(block); - if let TerminatorKind::Resume = data.terminator().kind { - if data.statements.len() > 0 { - resume_stmt_block = Some(block); + for (bb, block) in mir.basic_blocks().iter_enumerated() { + if let TerminatorKind::Resume = block.terminator().kind { + if block.statements.len() > 0 { + resume_stmt_block = Some(bb); } else { - resume_block = Some(block); + resume_block = Some(bb); } break } @@ -84,9 +83,9 @@ impl<'tcx> MirPatch<'tcx> { } pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location { - let offset = match bb.index().checked_sub(mir.basic_blocks.len()) { + let offset = match bb.index().checked_sub(mir.basic_blocks().len()) { Some(index) => self.new_blocks[index].statements.len(), - None => mir.basic_block_data(bb).statements.len() + None => mir[bb].statements.len() }; Location { block: bb, @@ -128,13 +127,13 @@ impl<'tcx> MirPatch<'tcx> { debug!("MirPatch: {:?} new temps, starting from index {}: {:?}", self.new_temps.len(), mir.temp_decls.len(), self.new_temps); debug!("MirPatch: {} new blocks, starting from index {}", - self.new_blocks.len(), mir.basic_blocks.len()); - mir.basic_blocks.extend(self.new_blocks); + self.new_blocks.len(), mir.basic_blocks().len()); + mir.basic_blocks_mut().extend(self.new_blocks); mir.temp_decls.extend(self.new_temps); for (src, patch) in self.patch_map.into_iter_enumerated() { if let Some(patch) = patch { debug!("MirPatch: patching block {:?}", src); - mir.basic_blocks[src].terminator_mut().kind = patch; + mir[src].terminator_mut().kind = patch; } } @@ -152,9 +151,9 @@ impl<'tcx> MirPatch<'tcx> { stmt, loc, delta); loc.index += delta; let source_info = Self::source_info_for_index( - mir.basic_block_data(loc.block), loc + &mir[loc.block], loc ); - mir.basic_block_data_mut(loc.block).statements.insert( + mir[loc.block].statements.insert( loc.index, Statement { source_info: source_info, kind: stmt @@ -171,9 +170,9 @@ impl<'tcx> MirPatch<'tcx> { } pub fn source_info_for_location(&self, mir: &Mir, loc: Location) -> SourceInfo { - let data = match loc.block.index().checked_sub(mir.basic_blocks.len()) { + let data = match loc.block.index().checked_sub(mir.basic_blocks().len()) { Some(new) => &self.new_blocks[new], - None => mir.basic_block_data(loc.block) + None => &mir[loc.block] }; Self::source_info_for_index(data, loc) } diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index b7697211241..db054477f75 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -11,7 +11,7 @@ use std::iter::{self, FromIterator}; use std::slice; use std::marker::PhantomData; -use std::ops::{Index, IndexMut}; +use std::ops::{Index, IndexMut, Range}; use std::fmt; use std::vec; @@ -115,6 +115,11 @@ impl IndexVec { self.raw.iter().enumerate().map(IntoIdx { _marker: PhantomData }) } + #[inline] + pub fn indices(&self) -> iter::Map, IntoIdx> { + (0..self.len()).map(IntoIdx { _marker: PhantomData }) + } + #[inline] pub fn iter_mut(&mut self) -> slice::IterMut { self.raw.iter_mut() @@ -207,3 +212,17 @@ impl FnMut<((usize, T),)> for IntoIdx { (I::new(n), t) } } + +impl FnOnce<(usize,)> for IntoIdx { + type Output = I; + + extern "rust-call" fn call_once(self, (n,): (usize,)) -> Self::Output { + I::new(n) + } +} + +impl FnMut<(usize,)> for IntoIdx { + extern "rust-call" fn call_mut(&mut self, (n,): (usize,)) -> Self::Output { + I::new(n) + } +} diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index dce64d2f3b7..2626a02281f 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -295,17 +295,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - (Mir { - basic_blocks: self.cfg.basic_blocks, - visibility_scopes: self.visibility_scopes, - promoted: IndexVec::new(), - var_decls: self.var_decls, - arg_decls: arg_decls, - temp_decls: self.temp_decls, - upvar_decls: upvar_decls, - return_ty: return_ty, - span: self.fn_span - }, self.scope_auxiliary) + (Mir::new(self.cfg.basic_blocks, + self.visibility_scopes, + IndexVec::new(), + return_ty, + self.var_decls, + arg_decls, + self.temp_decls, + upvar_decls, + self.fn_span + ), self.scope_auxiliary) } fn args_and_body(&mut self, diff --git a/src/librustc_mir/graphviz.rs b/src/librustc_mir/graphviz.rs index 17bd41a81d2..fdfa872b0b6 100644 --- a/src/librustc_mir/graphviz.rs +++ b/src/librustc_mir/graphviz.rs @@ -34,12 +34,12 @@ where W: Write, I: Iterator)> { write_graph_label(tcx, nodeid, mir, w)?; // Nodes - for block in mir.all_basic_blocks() { + for (block, _) in mir.basic_blocks().iter_enumerated() { write_node(block, mir, w)?; } // Edges - for source in mir.all_basic_blocks() { + for (source, _) in mir.basic_blocks().iter_enumerated() { write_edges(source, mir, w)?; } writeln!(w, "}}")? @@ -63,7 +63,7 @@ pub fn write_node_label(block: BasicBlock, where INIT: Fn(&mut W) -> io::Result<()>, FINI: Fn(&mut W) -> io::Result<()> { - let data = mir.basic_block_data(block); + let data = &mir[block]; write!(w, r#""#)?; @@ -107,7 +107,7 @@ fn write_node(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<( /// Write graphviz DOT edges with labels between the given basic block and all of its successors. fn write_edges(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> { - let terminator = &mir.basic_block_data(source).terminator(); + let terminator = mir[source].terminator(); let labels = terminator.kind.fmt_successor_labels(); for (&target, label) in terminator.successors().iter().zip(labels) { diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs index b913f2ae6cf..856d6cda5af 100644 --- a/src/librustc_mir/pretty.rs +++ b/src/librustc_mir/pretty.rs @@ -135,9 +135,9 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> io::Result<()> { let annotations = scope_entry_exit_annotations(auxiliary); write_mir_intro(tcx, src, mir, w)?; - for block in mir.all_basic_blocks() { + for block in mir.basic_blocks().indices() { write_basic_block(tcx, block, mir, w, &annotations)?; - if block.index() + 1 != mir.basic_blocks.len() { + if block.index() + 1 != mir.basic_blocks().len() { writeln!(w, "")?; } } @@ -153,7 +153,7 @@ fn write_basic_block(tcx: TyCtxt, w: &mut Write, annotations: &FnvHashMap>) -> io::Result<()> { - let data = mir.basic_block_data(block); + let data = &mir[block]; // Basic block label at the top. writeln!(w, "{}{:?}: {{", INDENT, block)?; diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index f829865255d..dee9227fd9b 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -40,7 +40,7 @@ pub struct AddCallGuards; impl<'tcx> MirPass<'tcx> for AddCallGuards { fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { - let mut pred_count = IndexVec::from_elem(0u32, &mir.basic_blocks); + let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks()); // Build the precedecessor map for the MIR for (_, data) in traversal::preorder(mir) { @@ -54,13 +54,10 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); - let bbs = mir.all_basic_blocks(); - let cur_len = mir.basic_blocks.len(); + let cur_len = mir.basic_blocks().len(); - for &bb in &bbs { - let data = mir.basic_block_data_mut(bb); - - match data.terminator { + for block in mir.basic_blocks_mut() { + match block.terminator { Some(Terminator { kind: TerminatorKind::Call { destination: Some((_, ref mut destination)), @@ -71,7 +68,7 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { // It's a critical edge, break it let call_guard = BasicBlockData { statements: vec![], - is_cleanup: data.is_cleanup, + is_cleanup: block.is_cleanup, terminator: Some(Terminator { source_info: source_info, kind: TerminatorKind::Goto { target: *destination } @@ -90,7 +87,7 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards { pretty::dump_mir(tcx, "break_cleanup_edges", &0, src, mir, None); debug!("Broke {} N edges", new_blocks.len()); - mir.basic_blocks.extend(new_blocks); + mir.basic_blocks_mut().extend(new_blocks); } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4d6838052de..3ebfef10d43 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -163,11 +163,12 @@ struct Promoter<'a, 'tcx: 'a> { impl<'a, 'tcx> Promoter<'a, 'tcx> { fn new_block(&mut self) -> BasicBlock { - self.promoted.basic_blocks.push(BasicBlockData { + let span = self.promoted.span; + self.promoted.basic_blocks_mut().push(BasicBlockData { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo { - span: self.promoted.span, + span: span, scope: ARGUMENT_VISIBILITY_SCOPE }, kind: TerminatorKind::Return @@ -177,8 +178,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn assign(&mut self, dest: Lvalue<'tcx>, rvalue: Rvalue<'tcx>, span: Span) { - let last = self.promoted.basic_blocks.last().unwrap(); - let data = &mut self.promoted.basic_blocks[last]; + let last = self.promoted.basic_blocks().last().unwrap(); + let data = &mut self.promoted[last]; data.statements.push(Statement { source_info: SourceInfo { span: span, @@ -268,7 +269,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { if stmt_idx < no_stmts { self.assign(Lvalue::Temp(new_temp), rvalue.unwrap(), source_info.span); } else { - let last = self.promoted.basic_blocks.last().unwrap(); + let last = self.promoted.basic_blocks().last().unwrap(); let new_target = self.new_block(); let mut call = call.unwrap(); match call { @@ -277,7 +278,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } _ => bug!() } - let terminator = &mut self.promoted.basic_blocks[last].terminator_mut(); + let terminator = self.promoted[last].terminator_mut(); terminator.source_info.span = source_info.span; terminator.kind = call; } @@ -365,20 +366,20 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, let mut promoter = Promoter { source: mir, - promoted: Mir { - basic_blocks: IndexVec::new(), - visibility_scopes: Some(VisibilityScopeData { + promoted: Mir::new( + IndexVec::new(), + Some(VisibilityScopeData { span: span, parent_scope: None }).into_iter().collect(), - promoted: IndexVec::new(), - return_ty: ty::FnConverging(ty), - var_decls: IndexVec::new(), - arg_decls: IndexVec::new(), - temp_decls: IndexVec::new(), - upvar_decls: vec![], - span: span - }, + IndexVec::new(), + ty::FnConverging(ty), + IndexVec::new(), + IndexVec::new(), + IndexVec::new(), + vec![], + span + ), temps: &mut temps, keep_original: false }; @@ -388,7 +389,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, // Eliminate assignments to, and drops of promoted temps. let promoted = |index: Temp| temps[index] == TempState::PromotedOut; - for block in &mut mir.basic_blocks { + for block in mir.basic_blocks_mut() { block.statements.retain(|statement| { match statement.kind { StatementKind::Assign(Lvalue::Temp(index), _) => { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 3272d7276d5..73ecac55389 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -337,7 +337,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { fn qualify_const(&mut self) -> Qualif { let mir = self.mir; - let mut seen_blocks = BitVector::new(mir.basic_blocks.len()); + let mut seen_blocks = BitVector::new(mir.basic_blocks().len()); let mut bb = START_BLOCK; loop { seen_blocks.insert(bb.index()); @@ -367,12 +367,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { TerminatorKind::Return => { // Check for unused values. This usually means // there are extra statements in the AST. - for (i, _) in mir.temp_decls.iter_enumerated() { - if self.temp_qualif[i].is_none() { + for temp in mir.temp_decls.indices() { + if self.temp_qualif[temp].is_none() { continue; } - let state = self.temp_promotion_state[i]; + let state = self.temp_promotion_state[temp]; if let TempState::Defined { location, uses: 0 } = state { let data = &mir[location.block]; let stmt_idx = location.statement_index; diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index a65e9b8c414..fcc82249953 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -60,7 +60,7 @@ impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> { pretty::dump_mir(tcx, "simplify_cfg", &format!("{}-after", self.label), src, mir, None); // FIXME: Should probably be moved into some kind of pass manager - mir.basic_blocks.raw.shrink_to_fit(); + mir.basic_blocks_mut().raw.shrink_to_fit(); } } @@ -68,7 +68,7 @@ impl<'l> Pass for SimplifyCfg<'l> {} fn merge_consecutive_blocks(mir: &mut Mir) { // Build the precedecessor map for the MIR - let mut pred_count = IndexVec::from_elem(0u32, &mir.basic_blocks); + let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks()); for (_, data) in traversal::preorder(mir) { if let Some(ref term) = data.terminator { for &tgt in term.successors().iter() { @@ -79,12 +79,11 @@ fn merge_consecutive_blocks(mir: &mut Mir) { loop { let mut changed = false; - let mut seen = BitVector::new(mir.basic_blocks.len()); + let mut seen = BitVector::new(mir.basic_blocks().len()); let mut worklist = vec![START_BLOCK]; while let Some(bb) = worklist.pop() { // Temporarily take ownership of the terminator we're modifying to keep borrowck happy - let mut terminator = mir.basic_block_data_mut(bb).terminator.take() - .expect("invalid terminator state"); + let mut terminator = mir[bb].terminator.take().expect("invalid terminator state"); // See if we can merge the target block into this one loop { @@ -96,8 +95,8 @@ fn merge_consecutive_blocks(mir: &mut Mir) { break; } - let num_insts = mir.basic_block_data(target).statements.len(); - match mir.basic_block_data(target).terminator().kind { + let num_insts = mir[target].statements.len(); + match mir[target].terminator().kind { TerminatorKind::Goto { target: new_target } if num_insts == 0 => { inner_change = true; terminator.kind = TerminatorKind::Goto { target: new_target }; @@ -108,12 +107,12 @@ fn merge_consecutive_blocks(mir: &mut Mir) { inner_change = true; let mut stmts = Vec::new(); { - let target_data = mir.basic_block_data_mut(target); + let target_data = &mut mir[target]; mem::swap(&mut stmts, &mut target_data.statements); mem::swap(&mut terminator, target_data.terminator_mut()); } - mir.basic_block_data_mut(bb).statements.append(&mut stmts); + mir[bb].statements.append(&mut stmts); } _ => {} }; @@ -122,7 +121,7 @@ fn merge_consecutive_blocks(mir: &mut Mir) { for target in terminator.successors_mut() { let new_target = match final_target(mir, *target) { Some(new_target) => new_target, - None if mir.basic_block_data(bb).statements.is_empty() => bb, + None if mir[bb].statements.is_empty() => bb, None => continue }; if *target != new_target { @@ -139,9 +138,9 @@ fn merge_consecutive_blocks(mir: &mut Mir) { } } - mir.basic_block_data_mut(bb).terminator = Some(terminator); + mir[bb].terminator = Some(terminator); - for succ in mir.basic_block_data(bb).terminator().successors().iter() { + for succ in mir[bb].terminator().successors().iter() { if seen.insert(succ.index()) { worklist.push(*succ); } @@ -159,11 +158,11 @@ fn final_target(mir: &Mir, mut target: BasicBlock) -> Option { // Keep track of already seen blocks to detect loops let mut seen: Vec = Vec::with_capacity(8); - while mir.basic_block_data(target).statements.is_empty() { + while mir[target].statements.is_empty() { // NB -- terminator may have been swapped with `None` in // merge_consecutive_blocks, in which case we have a cycle and just want // to stop - match mir.basic_block_data(target).terminator { + match mir[target].terminator { Some(Terminator { kind: TerminatorKind::Goto { target: next }, .. }) => { if seen.contains(&next) { return None; @@ -182,8 +181,7 @@ fn simplify_branches(mir: &mut Mir) { loop { let mut changed = false; - for bb in mir.all_basic_blocks() { - let basic_block = mir.basic_block_data_mut(bb); + for (_, basic_block) in mir.basic_blocks_mut().iter_enumerated_mut() { let mut terminator = basic_block.terminator_mut(); terminator.kind = match terminator.kind { TerminatorKind::If { ref targets, .. } if targets.0 == targets.1 => { @@ -228,13 +226,14 @@ fn simplify_branches(mir: &mut Mir) { } fn remove_dead_blocks(mir: &mut Mir) { - let mut seen = BitVector::new(mir.basic_blocks.len()); + let mut seen = BitVector::new(mir.basic_blocks().len()); for (bb, _) in traversal::preorder(mir) { seen.insert(bb.index()); } - let num_blocks = mir.basic_blocks.len(); + let basic_blocks = mir.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() { @@ -242,14 +241,14 @@ fn remove_dead_blocks(mir: &mut Mir) { 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. - mir.basic_blocks.raw.swap(alive_index, used_blocks); + basic_blocks.raw.swap(alive_index, used_blocks); } used_blocks += 1; } - mir.basic_blocks.raw.truncate(used_blocks); + basic_blocks.raw.truncate(used_blocks); - for bb in mir.all_basic_blocks() { - for target in mir.basic_block_data_mut(bb).terminator_mut().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/type_check.rs b/src/librustc_mir/transform/type_check.rs index ab402a7f881..16ea4780bb3 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -626,7 +626,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { bb: BasicBlock, iscleanuppad: bool) { - if mir.basic_block_data(bb).is_cleanup != iscleanuppad { + if mir[bb].is_cleanup != iscleanuppad { span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad); } @@ -635,7 +635,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn typeck_mir(&mut self, mir: &Mir<'tcx>) { self.last_span = mir.span; debug!("run_on_mir: {:?}", mir.span); - for block in &mir.basic_blocks { + for block in mir.basic_blocks() { for stmt in &block.statements { if stmt.source_info.span != DUMMY_SP { self.last_span = stmt.source_info.span; diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 0ac9b522748..df00abf7b1c 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -168,8 +168,7 @@ pub fn cleanup_kinds<'bcx,'tcx>(_bcx: Block<'bcx,'tcx>, { fn discover_masters<'tcx>(result: &mut IndexVec, mir: &mir::Mir<'tcx>) { - for bb in mir.all_basic_blocks() { - let data = mir.basic_block_data(bb); + for (bb, data) in mir.basic_blocks().iter_enumerated() { match data.terminator().kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume | @@ -195,7 +194,7 @@ pub fn cleanup_kinds<'bcx,'tcx>(_bcx: Block<'bcx,'tcx>, fn propagate<'tcx>(result: &mut IndexVec, mir: &mir::Mir<'tcx>) { - let mut funclet_succs = IndexVec::from_elem(None, &mir.basic_blocks); + let mut funclet_succs = IndexVec::from_elem(None, mir.basic_blocks()); let mut set_successor = |funclet: mir::BasicBlock, succ| { match funclet_succs[funclet] { @@ -249,7 +248,7 @@ pub fn cleanup_kinds<'bcx,'tcx>(_bcx: Block<'bcx,'tcx>, } } - let mut result = IndexVec::from_elem(CleanupKind::NotCleanup, &mir.basic_blocks); + let mut result = IndexVec::from_elem(CleanupKind::NotCleanup, mir.basic_blocks()); discover_masters(&mut result, mir); propagate(&mut result, mir); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 03a9e977b1a..8dabce2ec4e 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -43,7 +43,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn trans_block(&mut self, bb: mir::BasicBlock) { let mut bcx = self.bcx(bb); let mir = self.mir.clone(); - let data = mir.basic_block_data(bb); + let data = &mir[bb]; debug!("trans_block({:?}={:?})", bb, data); @@ -725,7 +725,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { pub fn init_cpad(&mut self, bb: mir::BasicBlock) { let bcx = self.bcx(bb); - let data = self.mir.basic_block_data(bb); + let data = &self.mir[bb]; debug!("init_cpad({:?})", data); match self.cleanup_kinds[bb] { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 488c913d88d..316c7341ef1 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -280,7 +280,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let mut failure = Ok(()); loop { - let data = self.mir.basic_block_data(bb); + let data = &self.mir[bb]; for statement in &data.statements { let span = statement.source_info.span; match statement.kind { diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index fe9f4419f6c..1932a2023fa 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -155,8 +155,6 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { let bcx = fcx.init(false, None).build(); let mir = bcx.mir(); - let mir_blocks = mir.all_basic_blocks(); - // Analyze the temps to determine which must be lvalues // FIXME let (lvalue_temps, cleanup_kinds) = bcx.with_block(|bcx| { @@ -202,15 +200,13 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { // Allocate a `Block` for every basic block let block_bcxs: IndexVec> = - mir_blocks.iter() - .map(|&bb| { - if bb == mir::START_BLOCK { - fcx.new_block("start", None) - } else { - fcx.new_block(&format!("{:?}", bb), None) - } - }) - .collect(); + mir.basic_blocks().indices().map(|bb| { + if bb == mir::START_BLOCK { + fcx.new_block("start", None) + } else { + fcx.new_block(&format!("{:?}", bb), None) + } + }).collect(); // Branch to the START block let start_bcx = block_bcxs[mir::START_BLOCK]; @@ -228,14 +224,14 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { blocks: block_bcxs, unreachable_block: None, cleanup_kinds: cleanup_kinds, - landing_pads: mir_blocks.iter().map(|_| None).collect(), + landing_pads: IndexVec::from_elem(None, mir.basic_blocks()), vars: vars, temps: temps, args: args, scopes: scopes }; - let mut visited = BitVector::new(mir_blocks.len()); + let mut visited = BitVector::new(mir.basic_blocks().len()); let mut rpo = traversal::reverse_postorder(&mir); @@ -253,7 +249,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) { // Remove blocks that haven't been visited, or have no // predecessors. - for &bb in &mir_blocks { + for bb in mir.basic_blocks().indices() { let block = mircx.blocks[bb]; let block = BasicBlock(block.llbb); // Unreachable block