Skip to content

[WIP][MIR] Generic lattice-based DF framework #33628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#![cfg_attr(not(stage0), deny(warnings))]

#![feature(associated_consts)]
#![feature(inclusive_range_syntax)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(collections)]
Expand Down Expand Up @@ -108,6 +109,8 @@ pub mod mir {
pub mod visit;
pub mod transform;
pub mod mir_map;
pub mod cfg;
pub mod traversal;
}

pub mod session;
Expand Down
146 changes: 146 additions & 0 deletions src/librustc/mir/cfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use mir::repr::*;

use std::ops::{Index, IndexMut};
use syntax::codemap::Span;

#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct CFG<'tcx> {
pub basic_blocks: Vec<BasicBlockData<'tcx>>,
}

pub struct PredecessorIter(::std::vec::IntoIter<BasicBlock>);
impl Iterator for PredecessorIter {
type Item = BasicBlock;
fn next(&mut self) -> Option<BasicBlock> {
self.0.next()
}
}

pub struct SuccessorIter(::std::vec::IntoIter<BasicBlock>);
impl<'a> Iterator for SuccessorIter {
type Item = BasicBlock;
fn next(&mut self) -> Option<BasicBlock> {
self.0.next()
}
}

pub struct SuccessorIterMut<'a>(::std::vec::IntoIter<&'a mut BasicBlock>);
impl<'a> Iterator for SuccessorIterMut<'a> {
type Item = &'a mut BasicBlock;
fn next(&mut self) -> Option<&'a mut BasicBlock> {
self.0.next()
}
}

impl<'tcx> CFG<'tcx> {
pub fn len(&self) -> usize {
self.basic_blocks.len()
}

pub fn predecessors(&self, b: BasicBlock) -> PredecessorIter {
let mut preds = vec![];
for idx in 0..self.len() {
let bb = BasicBlock::new(idx);
if let Some(_) = self.successors(bb).find(|&x| x == b) {
preds.push(bb)
}
}
PredecessorIter(preds.into_iter())
}

pub fn successors(&self, b: BasicBlock) -> SuccessorIter {
let v: Vec<BasicBlock> = self[b].terminator().kind.successors().into_owned();
SuccessorIter(v.into_iter())
}

pub fn successors_mut(&mut self, b: BasicBlock) -> SuccessorIterMut {
SuccessorIterMut(self[b].terminator_mut().kind.successors_mut().into_iter())
}


pub fn swap(&mut self, b1: BasicBlock, b2: BasicBlock) {
// TODO: find all the branches to b2 from subgraph starting at b2 and replace them with b1.
self.basic_blocks.swap(b1.index(), b2.index());
}

pub fn start_new_block(&mut self) -> BasicBlock {
let node_index = self.basic_blocks.len();
self.basic_blocks.push(BasicBlockData::new(None));
BasicBlock::new(node_index)
}

pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
let bb = self.start_new_block();
self[bb].is_cleanup = true;
bb
}

pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
debug!("push({:?}, {:?})", block, statement);
self[block].statements.push(statement);
}

pub fn terminate(&mut self,
block: BasicBlock,
scope: ScopeId,
span: Span,
kind: TerminatorKind<'tcx>) {
debug_assert!(self[block].terminator.is_none(),
"terminate: block {:?} already has a terminator set", block);
self[block].terminator = Some(Terminator {
span: span,
scope: scope,
kind: kind,
});
}

pub fn push_assign(&mut self,
block: BasicBlock,
scope: ScopeId,
span: Span,
lvalue: &Lvalue<'tcx>,
rvalue: Rvalue<'tcx>) {
self.push(block, Statement {
scope: scope,
span: span,
kind: StatementKind::Assign(lvalue.clone(), rvalue)
});
}

pub fn push_assign_constant(&mut self,
block: BasicBlock,
scope: ScopeId,
span: Span,
temp: &Lvalue<'tcx>,
constant: Constant<'tcx>) {
self.push_assign(block, scope, span, temp,
Rvalue::Use(Operand::Constant(constant)));
}

pub fn push_assign_unit(&mut self,
block: BasicBlock,
scope: ScopeId,
span: Span,
lvalue: &Lvalue<'tcx>) {
self.push_assign(block, scope, span, lvalue, Rvalue::Aggregate(
AggregateKind::Tuple, vec![]
));
}
}

impl<'tcx> Index<BasicBlock> for CFG<'tcx> {
type Output = BasicBlockData<'tcx>;

#[inline]
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
&self.basic_blocks[index.index()]
}
}

impl<'tcx> IndexMut<BasicBlock> for CFG<'tcx> {
#[inline]
fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks[index.index()]
}
}

14 changes: 8 additions & 6 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub use mir::cfg::*;

use graphviz::IntoCow;
use middle::const_val::ConstVal;
use rustc_const_math::{ConstUsize, ConstInt};
Expand All @@ -30,7 +32,7 @@ use syntax::codemap::Span;
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: Vec<BasicBlockData<'tcx>>,
pub cfg: CFG<'tcx>,

/// List of lexical scopes; these are referenced by statements and
/// used (eventually) for debuginfo. Indexed by a `ScopeId`.
Expand Down Expand Up @@ -70,17 +72,17 @@ pub const START_BLOCK: BasicBlock = BasicBlock(0);

impl<'tcx> Mir<'tcx> {
pub fn all_basic_blocks(&self) -> Vec<BasicBlock> {
(0..self.basic_blocks.len())
(0..self.cfg.len())
.map(|i| BasicBlock::new(i))
.collect()
}

pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<'tcx> {
&self.basic_blocks[bb.index()]
&self.cfg[bb]
}

pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks[bb.index()]
&mut self.cfg[bb]
}
}

Expand Down Expand Up @@ -541,7 +543,7 @@ impl<'tcx> Debug for Statement<'tcx> {

/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum Lvalue<'tcx> {
/// local variable declared by the user
Var(u32),
Expand Down Expand Up @@ -726,7 +728,7 @@ pub struct ScopeData {
/// These are values that can appear inside an rvalue (or an index
/// lvalue). They are intentionally limited to prevent rvalues from
/// being nested in one another.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum Operand<'tcx> {
Consume(Lvalue<'tcx>),
Constant(Constant<'tcx>),
Expand Down
Loading