Skip to content
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

[WIP] [MIR] Generic lattice-based dataflow framework, rebased #34164

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bb183e2
Distinct CFG type for MIR, traversals to librustc
nagisa May 14, 2016
d7a0466
Impl a generic lattice-based DF framework
nagisa May 14, 2016
060d840
Implement a ACS propagation pass
nagisa May 14, 2016
e20d181
Remove use of specialization in Lattice to avoid use of unstable feat…
gereeter May 16, 2016
ea689a0
Remove DataflowPass
gereeter May 16, 2016
c1bb060
Add &self arguments to Transfer and Rewrite and start taking them by …
gereeter May 16, 2016
52eff47
Remove unused and buggy support for dataflow passes that introduce mu…
gereeter May 16, 2016
6413fe6
Let ar_forward generate its own queue
gereeter May 16, 2016
0756739
Change the fully capitalized ACS to the partially capitalized Acs, ma…
gereeter May 16, 2016
a0eebd3
Fix various nits in MIR Dataflow
gereeter May 22, 2016
7cbcb4b
Actually rewrite constants in AcsPropagate
gereeter May 22, 2016
4af1473
Remove some unnecessary `pub`s in AcsPropagate
gereeter May 25, 2016
ad37533
Invalidate values in AcsLattice that are overwritten, either by a wri…
gereeter May 25, 2016
9b3ecda
Temporarily completely disable Backward dataflow to fix unused varian…
gereeter May 25, 2016
b0fbbae
Rewrite AcsLattice to be more correct
gereeter May 27, 2016
7f1d4c8
Further correctness improvements to AcsRewrite
gereeter May 31, 2016
cfcf7cd
Remove unused import left over from rebase
gereeter Jun 7, 2016
ae0c91c
Properly reset basic blocks optimized based on overspeculative inform…
gereeter Jun 8, 2016
ffc2406
Implement MIR's CFG::swap correctly
gereeter Jun 8, 2016
3bd906c
Mutably update blocks when analyzing instead of creating new ones. ru…
gereeter Jun 8, 2016
07d073e
Fix make tidy
gereeter Jun 8, 2016
282d51d
Also clear the Acs cache on DropAndReplace
gereeter Jun 8, 2016
f4452c8
Use the generic WBottom for AcsLattice
gereeter Jun 8, 2016
c045fa4
Properly implement intersection in AcsLattice::join
gereeter Jun 9, 2016
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 @@ -107,6 +108,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
167 changes: 167 additions & 0 deletions src/librustc/mir/cfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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) {
if b1 != b2 {
for idx in 0..self.len() {
let bb = BasicBlock::new(idx);
for target in self.successors_mut(bb) {
if *target == b1 {
*target = b2;
} else if *target == b2 {
*target = 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, ConstMathErr};
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 @@ -611,7 +613,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 @@ -796,7 +798,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