Skip to content

Scopes in mir #32428

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

Merged
merged 24 commits into from
Mar 25, 2016
Merged
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
464c02e
integrate scopes into MIR
nikomatsakis Mar 9, 2016
323d7f4
record a scope for each `VarDecl`
nikomatsakis Mar 9, 2016
e752d4c
track the innermost scope for every stmt
nikomatsakis Mar 9, 2016
3a16f57
extend Terminator into a struct so it can have additional fields
nikomatsakis Mar 10, 2016
9d00dee
add span/scope-id to terminator
nikomatsakis Mar 18, 2016
caac0b9
reformat mir text pretty printer
nikomatsakis Mar 19, 2016
d32bde3
augment MIR pretty printer to print scopes
nikomatsakis Mar 22, 2016
0d93989
adjust pretty printer to print scopes / auxiliary
nikomatsakis Mar 22, 2016
a61c175
allow dumping intermediate IR with -Z dump-mir
nikomatsakis Mar 22, 2016
f976e22
fix bug in `simplify_cfg` with inf. loops
nikomatsakis Mar 22, 2016
cb04e49
rewrite drop code
nikomatsakis Mar 23, 2016
f66fd89
replace DUMMY_SP on resume with span from fn
nikomatsakis Mar 23, 2016
14a5657
Rename `MirPlusPlus` to `MirAndScopeAuxiliary`
nikomatsakis Mar 23, 2016
a2bab6f
Address nit: use doc-comments for fields of VarDecl
nikomatsakis Mar 23, 2016
c1a53a6
Address nit: doc-comments on fields
nikomatsakis Mar 23, 2016
b3d2059
Address nit: block.unit()
nikomatsakis Mar 23, 2016
70d0123
Address nit: Remove `ScopedDataVec` newtype
nikomatsakis Mar 23, 2016
c36707a
Add `ScopeAuxiliaryVec`, return MIR+aux via tuple
nikomatsakis Mar 23, 2016
2b96cfb
add comments on remaining fields
nikomatsakis Mar 23, 2016
1c0fa34
Update borrowck to use `repr::*` instead of a mix
nikomatsakis Mar 23, 2016
a276e75
introduce "call-site-scope" as the outermost scope
nikomatsakis Mar 23, 2016
0769865
rewrite scope drop to be iterative
nikomatsakis Mar 24, 2016
ed7c30b
rework MIR visitor
nikomatsakis Mar 24, 2016
091a007
pacify the merciless tidy
nikomatsakis Mar 24, 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
107 changes: 97 additions & 10 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ pub struct Mir<'tcx> {
/// that indexes into this vector.
pub basic_blocks: Vec<BasicBlockData<'tcx>>,

/// List of lexical scopes; these are referenced by statements and
/// used (eventually) for debuginfo. Indexed by a `ScopeId`.
pub scopes: Vec<ScopeData>,

/// Return type of the function.
pub return_ty: FnOutput<'tcx>,

Expand Down Expand Up @@ -152,9 +156,21 @@ pub enum BorrowKind {
/// decl, a let, etc.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct VarDecl<'tcx> {
/// `let mut x` vs `let x`
pub mutability: Mutability,

/// name that user gave the variable; not that, internally,
/// mir references variables by index
pub name: Name,

/// type inferred for this variable (`let x: ty = ...`)
pub ty: Ty<'tcx>,

/// scope in which variable was declared
pub scope: ScopeId,

/// span where variable was declared
pub span: Span,
}

/// A "temp" is a temporary that we place on the stack. They are
Expand Down Expand Up @@ -191,7 +207,7 @@ pub struct ArgDecl<'tcx> {
/// list of the `Mir`.
///
/// (We use a `u32` internally just to save memory.)
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct BasicBlock(u32);

impl BasicBlock {
Expand All @@ -217,13 +233,35 @@ impl Debug for BasicBlock {

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BasicBlockData<'tcx> {
/// List of statements in this block.
pub statements: Vec<Statement<'tcx>>,

/// Terminator for this block.
///
/// NB. This should generally ONLY be `None` during construction.
/// Therefore, you should generally access it via the
/// `terminator()` or `terminator_mut()` methods. The only
/// exception is that certain passes, such as `simplify_cfg`, swap
/// out the terminator temporarily with `None` while they continue
/// to recurse over the set of basic blocks.
pub terminator: Option<Terminator<'tcx>>,

/// If true, this block lies on an unwind path. This is used
/// during trans where distinct kinds of basic blocks may be
/// generated (particularly for MSVC cleanup). Unwind blocks must
/// only branch to other unwind blocks.
pub is_cleanup: bool,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Terminator<'tcx> {
pub span: Span,
pub scope: ScopeId,
pub kind: TerminatorKind<'tcx>
}

#[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum Terminator<'tcx> {
pub enum TerminatorKind<'tcx> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a galaxy far, far away they have neater ADTs 😞

/// block should have one successor in the graph; we jump there
Goto {
target: BasicBlock,
Expand Down Expand Up @@ -293,7 +331,17 @@ pub enum Terminator<'tcx> {

impl<'tcx> Terminator<'tcx> {
pub fn successors(&self) -> Cow<[BasicBlock]> {
use self::Terminator::*;
self.kind.successors()
}

pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
self.kind.successors_mut()
}
}

impl<'tcx> TerminatorKind<'tcx> {
pub fn successors(&self) -> Cow<[BasicBlock]> {
use self::TerminatorKind::*;
match *self {
Goto { target: ref b } => slice::ref_slice(b).into_cow(),
If { targets: (b1, b2), .. } => vec![b1, b2].into_cow(),
Expand All @@ -314,7 +362,7 @@ impl<'tcx> Terminator<'tcx> {
// FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
// `Vec<&mut BasicBlock>` would look like in the first place.
pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
use self::Terminator::*;
use self::TerminatorKind::*;
match *self {
Goto { target: ref mut b } => vec![b],
If { targets: (ref mut b1, ref mut b2), .. } => vec![b1, b2],
Expand Down Expand Up @@ -354,7 +402,7 @@ impl<'tcx> BasicBlockData<'tcx> {
}
}

impl<'tcx> Debug for Terminator<'tcx> {
impl<'tcx> Debug for TerminatorKind<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.fmt_head(fmt)?;
let successors = self.successors();
Expand All @@ -381,12 +429,12 @@ impl<'tcx> Debug for Terminator<'tcx> {
}
}

impl<'tcx> Terminator<'tcx> {
impl<'tcx> TerminatorKind<'tcx> {
/// Write the "head" part of the terminator; that is, its name and the data it uses to pick the
/// successor basic block, if any. The only information not inlcuded is the list of possible
/// successors, which may be rendered differently between the text and the graphviz format.
pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
use self::Terminator::*;
use self::TerminatorKind::*;
match *self {
Goto { .. } => write!(fmt, "goto"),
If { cond: ref lv, .. } => write!(fmt, "if({:?})", lv),
Expand All @@ -413,7 +461,7 @@ impl<'tcx> Terminator<'tcx> {

/// Return the list of labels for the edges to the successor basic blocks.
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
use self::Terminator::*;
use self::TerminatorKind::*;
match *self {
Return | Resume => vec![],
Goto { .. } => vec!["".into()],
Expand Down Expand Up @@ -452,6 +500,7 @@ impl<'tcx> Terminator<'tcx> {
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct Statement<'tcx> {
pub span: Span,
pub scope: ScopeId,
pub kind: StatementKind<'tcx>,
}

Expand All @@ -468,6 +517,7 @@ impl<'tcx> Debug for Statement<'tcx> {
}
}
}

///////////////////////////////////////////////////////////////////////////
// Lvalues

Expand Down Expand Up @@ -613,13 +663,50 @@ impl<'tcx> Debug for Lvalue<'tcx> {
}
}

///////////////////////////////////////////////////////////////////////////
// Scopes

impl Index<ScopeId> for Vec<ScopeData> {
type Output = ScopeData;

#[inline]
fn index(&self, index: ScopeId) -> &ScopeData {
&self[index.index()]
}
}

impl IndexMut<ScopeId> for Vec<ScopeData> {
#[inline]
fn index_mut(&mut self, index: ScopeId) -> &mut ScopeData {
&mut self[index.index()]
}
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct ScopeId(u32);

impl ScopeId {
pub fn new(index: usize) -> ScopeId {
assert!(index < (u32::MAX as usize));
ScopeId(index as u32)
}

pub fn index(self) -> usize {
self.0 as usize
}
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ScopeData {
pub parent_scope: Option<ScopeId>,
}

///////////////////////////////////////////////////////////////////////////
// Operands
//

/// 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)]
pub enum Operand<'tcx> {
Consume(Lvalue<'tcx>),
Expand Down
Loading