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<BasicBlock, BasicBlockData<'tcx>>,
+ basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
/// List of visibility (lexical) scopes; these are referenced by statements
/// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
pub const START_BLOCK: BasicBlock = BasicBlock(0);
impl<'tcx> Mir<'tcx> {
- pub fn all_basic_blocks(&self) -> Vec<BasicBlock> {
- (0..self.basic_blocks.len())
- .map(|i| BasicBlock::new(i))
- .collect()
+ pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+ visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
+ promoted: IndexVec<Promoted, Mir<'tcx>>,
+ return_ty: FnOutput<'tcx>,
+ var_decls: IndexVec<Var, VarDecl<'tcx>>,
+ arg_decls: IndexVec<Arg, ArgDecl<'tcx>>,
+ temp_decls: IndexVec<Temp, TempDecl<'tcx>>,
+ upvar_decls: Vec<UpvarDecl>,
+ 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<BasicBlock, BasicBlockData<'tcx>> {
+ &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<BasicBlock, BasicBlockData<'tcx>> {
+ &mut self.basic_blocks
}
}
#[inline]
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
- self.basic_block_data(index)
+ &self.basic_blocks()[index]
}
}
impl<'tcx> IndexMut<BasicBlock> 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]
}
}
Preorder {
mir: mir,
- visited: BitVector::new(mir.basic_blocks.len()),
+ visited: BitVector::new(mir.basic_blocks().len()),
worklist: worklist
}
}
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() {
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());
};
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));
}
self.traverse_successor();
}
- next.map(|(bb, _)| {
- let data = self.mir.basic_block_data(bb);
- (bb, data)
- })
+ next.map(|(bb, _)| (bb, &self.mir[bb]))
}
}
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]))
}
}
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,
pub struct Edge { source: BasicBlock, index: usize }
fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
- 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()
}
type Node = Node;
type Edge = Edge;
fn nodes(&self) -> dot::Nodes<Node> {
- self.mbcx.mir().all_basic_blocks().into_cow()
+ self.mbcx.mir()
+ .basic_blocks()
+ .indices()
+ .collect::<Vec<_>>()
+ .into_cow()
}
fn edges(&self) -> dot::Edges<Edge> {
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());
}
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]
}
}
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;
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 {:?}",
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() {
fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
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);
// (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));
// `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);
}
}
O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, 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,
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, .. } |
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();
unwind: Option<BasicBlock>)
{
let bb = loc.block;
- let data = self.mir.basic_block_data(bb);
+ let data = &self.mir[bb];
let terminator = data.terminator();
let assign = Statement {
}
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 {
// 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);
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
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();
flow_uninits: flow_uninits,
};
- for bb in mir.all_basic_blocks() {
+ for bb in mir.basic_blocks().indices() {
mbcx.process_basic_block(bb);
}
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);
}
|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);
}
},
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),
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![],
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
}
}
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,
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;
}
}
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
}
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)
}
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;
self.raw.iter().enumerate().map(IntoIdx { _marker: PhantomData })
}
+ #[inline]
+ pub fn indices(&self) -> iter::Map<Range<usize>, IntoIdx<I>> {
+ (0..self.len()).map(IntoIdx { _marker: PhantomData })
+ }
+
#[inline]
pub fn iter_mut(&mut self) -> slice::IterMut<T> {
self.raw.iter_mut()
(I::new(n), t)
}
}
+
+impl<I: Idx> FnOnce<(usize,)> for IntoIdx<I> {
+ type Output = I;
+
+ extern "rust-call" fn call_once(self, (n,): (usize,)) -> Self::Output {
+ I::new(n)
+ }
+}
+
+impl<I: Idx> FnMut<(usize,)> for IntoIdx<I> {
+ extern "rust-call" fn call_mut(&mut self, (n,): (usize,)) -> Self::Output {
+ I::new(n)
+ }
+}
}
}
- (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<A>(&mut self,
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, "}}")?
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#"<table border="0" cellborder="1" cellspacing="0">"#)?;
/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
fn write_edges<W: Write>(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) {
-> 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, "")?;
}
}
w: &mut Write,
annotations: &FnvHashMap<Location, Vec<Annotation>>)
-> io::Result<()> {
- let data = mir.basic_block_data(block);
+ let data = &mir[block];
// Basic block label at the top.
writeln!(w, "{}{:?}: {{", INDENT, block)?;
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) {
// 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)),
// 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 }
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);
}
}
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
}
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,
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 {
}
_ => 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;
}
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
};
// 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), _) => {
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());
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;
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();
}
}
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() {
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 {
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 };
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);
}
_ => {}
};
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 {
}
}
- 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);
}
// Keep track of already seen blocks to detect loops
let mut seen: Vec<BasicBlock> = 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;
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 => {
}
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() {
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()];
}
}
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);
}
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;
{
fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
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 |
fn propagate<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
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] {
}
}
- 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);
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);
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] {
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 {
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| {
// Allocate a `Block` for every basic block
let block_bcxs: IndexVec<mir::BasicBlock, Block<'blk,'tcx>> =
- 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];
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);
// 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