]> git.lizzy.rs Git - rust.git/commitdiff
[WIP] Move MIR towards a single kind of local
authorJonas Schievink <jonasschievink@gmail.com>
Sat, 24 Sep 2016 23:38:27 +0000 (01:38 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Mon, 26 Sep 2016 18:41:54 +0000 (20:41 +0200)
33 files changed:
src/librustc/mir/repr.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mir/patch.rs
src/librustc_mir/build/expr/as_lvalue.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/def_use.rs
src/librustc_mir/graphviz.rs
src/librustc_mir/pretty.rs
src/librustc_mir/transform/copy_prop.rs
src/librustc_mir/transform/instcombine.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_trans/debuginfo/create_scope_map.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/lvalue.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/mir/operand.rs
src/librustc_trans/mir/statement.rs
src/test/mir-opt/deaggregator_test.rs
src/test/mir-opt/deaggregator_test_enum.rs
src/test/mir-opt/storage_ranges.rs

index f236c4ebb977d68fc380034dd8bfc47fe3f7d776..1c8f1dc1525f4685c71bef9e80423864ca6f1901 100644 (file)
@@ -70,24 +70,26 @@ pub struct Mir<'tcx> {
 
     /// Rvalues promoted from this function, such as borrows of constants.
     /// Each of them is the Mir of a constant with the fn's type parameters
 
     /// Rvalues promoted from this function, such as borrows of constants.
     /// Each of them is the Mir of a constant with the fn's type parameters
-    /// in scope, but no vars or args and a separate set of temps.
+    /// in scope, but a separate set of locals.
     pub promoted: IndexVec<Promoted, Mir<'tcx>>,
 
     /// Return type of the function.
     pub return_ty: Ty<'tcx>,
 
     pub promoted: IndexVec<Promoted, Mir<'tcx>>,
 
     /// Return type of the function.
     pub return_ty: Ty<'tcx>,
 
-    /// Variables: these are stack slots corresponding to user variables. They may be
-    /// assigned many times.
-    pub var_decls: IndexVec<Var, VarDecl<'tcx>>,
-
-    /// Args: these are stack slots corresponding to the input arguments.
-    pub arg_decls: IndexVec<Arg, ArgDecl<'tcx>>,
+    /// Declarations of locals.
+    ///
+    /// The first local is the return value pointer, followed by `arg_count`
+    /// locals for the function arguments, followed by any user-declared
+    /// variables and temporaries.
+    pub local_decls: IndexVec<Local, LocalDecl<'tcx>>,
 
 
-    /// Temp declarations: stack slots that for temporaries created by
-    /// the compiler. These are assigned once, but they are not SSA
-    /// values in that it is possible to borrow them and mutate them
-    /// through the resulting reference.
-    pub temp_decls: IndexVec<Temp, TempDecl<'tcx>>,
+    /// Number of arguments this function takes.
+    ///
+    /// Starting at local1, `arg_count` locals will be provided by the caller
+    /// and can be assumed to be initialized.
+    ///
+    /// If this MIR was built for a constant, this will be 0.
+    pub arg_count: usize,
 
     /// Names and capture modes of all the closure upvars, assuming
     /// the first argument is either the closure or a reference to it.
 
     /// Names and capture modes of all the closure upvars, assuming
     /// the first argument is either the closure or a reference to it.
@@ -114,20 +116,23 @@ pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
                visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
                promoted: IndexVec<Promoted, Mir<'tcx>>,
                return_ty: Ty<'tcx>,
                visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
                promoted: IndexVec<Promoted, Mir<'tcx>>,
                return_ty: Ty<'tcx>,
-               var_decls: IndexVec<Var, VarDecl<'tcx>>,
-               arg_decls: IndexVec<Arg, ArgDecl<'tcx>>,
-               temp_decls: IndexVec<Temp, TempDecl<'tcx>>,
+               local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+               arg_count: usize,
                upvar_decls: Vec<UpvarDecl>,
                span: Span) -> Self
     {
                upvar_decls: Vec<UpvarDecl>,
                span: Span) -> Self
     {
+        // We need `arg_count` locals, and one for the return pointer
+        assert!(local_decls.len() >= arg_count + 1,
+            "expected at least {} locals, got {}", arg_count + 1, local_decls.len());
+        assert_eq!(local_decls[RETURN_POINTER].ty, return_ty);
+
         Mir {
             basic_blocks: basic_blocks,
             visibility_scopes: visibility_scopes,
             promoted: promoted,
             return_ty: return_ty,
         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,
+            local_decls: local_decls,
+            arg_count: arg_count,
             upvar_decls: upvar_decls,
             spread_last_arg: false,
             span: span,
             upvar_decls: upvar_decls,
             spread_last_arg: false,
             span: span,
@@ -161,56 +166,63 @@ pub fn dominators(&self) -> Dominators<BasicBlock> {
         dominators(self)
     }
 
         dominators(self)
     }
 
-    /// Maps locals (Arg's, Var's, Temp's and ReturnPointer, in that order)
-    /// to their index in the whole list of locals. This is useful if you
-    /// want to treat all locals the same instead of repeating yourself.
-    pub fn local_index(&self, lvalue: &Lvalue<'tcx>) -> Option<Local> {
-        let idx = match *lvalue {
-            Lvalue::Arg(arg) => arg.index(),
-            Lvalue::Var(var) => {
-                self.arg_decls.len() +
-                var.index()
-            }
-            Lvalue::Temp(temp) => {
-                self.arg_decls.len() +
-                self.var_decls.len() +
-                temp.index()
+    #[inline]
+    pub fn local_kind(&self, local: Local) -> LocalKind {
+        let index = local.0 as usize;
+        if index == 0 {
+            debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
+                          "return pointer should be mutable");
+
+            LocalKind::ReturnPointer
+        } else if index < self.arg_count + 1 {
+            LocalKind::Arg
+        } else if self.local_decls[local].name.is_some() {
+            LocalKind::Var
+        } else {
+            debug_assert!(self.local_decls[local].mutability == Mutability::Mut,
+                          "temp should be mutable");
+
+            LocalKind::Temp
+        }
+    }
+
+    /// Returns an iterator over all temporaries.
+    #[inline]
+    pub fn temp_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
+        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
+            let local = Local::new(index);
+            if self.local_decls[local].source_info.is_none() {
+                Some(local)
+            } else {
+                None
             }
             }
-            Lvalue::ReturnPointer => {
-                self.arg_decls.len() +
-                self.var_decls.len() +
-                self.temp_decls.len()
+        })
+    }
+
+    /// Returns an iterator over all user-declared locals.
+    #[inline]
+    pub fn var_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
+        (self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
+            let local = Local::new(index);
+            if self.local_decls[local].source_info.is_none() {
+                None
+            } else {
+                Some(local)
             }
             }
-            Lvalue::Static(_) |
-            Lvalue::Projection(_) => return None
-        };
-        Some(Local::new(idx))
+        })
     }
 
     }
 
-    /// Counts the number of locals, such that local_index
-    /// will always return an index smaller than this count.
-    pub fn count_locals(&self) -> usize {
-        self.arg_decls.len() +
-        self.var_decls.len() +
-        self.temp_decls.len() + 1
+    /// Returns an iterator over all function arguments.
+    #[inline]
+    pub fn arg_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
+        (1..self.arg_count+1).map(Local::new)
     }
 
     }
 
-    pub fn format_local(&self, local: Local) -> String {
-        let mut index = local.index();
-        index = match index.checked_sub(self.arg_decls.len()) {
-            None => return format!("{:?}", Arg::new(index)),
-            Some(index) => index,
-        };
-        index = match index.checked_sub(self.var_decls.len()) {
-            None => return format!("{:?}", Var::new(index)),
-            Some(index) => index,
-        };
-        index = match index.checked_sub(self.temp_decls.len()) {
-            None => return format!("{:?}", Temp::new(index)),
-            Some(index) => index,
-        };
-        debug_assert!(index == 0);
-        return "ReturnPointer".to_string()
+    /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
+    /// locals that are neither arguments nor the return pointer).
+    #[inline]
+    pub fn var_and_temp_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
+        (self.arg_count+1..self.local_decls.len()).map(Local::new)
     }
 
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
     }
 
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
@@ -308,49 +320,76 @@ pub enum BorrowKind {
 ///////////////////////////////////////////////////////////////////////////
 // Variables and temps
 
 ///////////////////////////////////////////////////////////////////////////
 // Variables and temps
 
-/// A "variable" is a binding declared by the user as part of the fn
-/// decl, a let, etc.
+newtype_index!(Local, "local");
+
+pub const RETURN_POINTER: Local = Local(0);
+
+/// Classifies locals into categories. See `Mir::local_kind`.
+#[derive(PartialEq, Eq, Debug)]
+pub enum LocalKind {
+    /// User-declared variable binding
+    Var,
+    /// Compiler-introduced temporary
+    Temp,
+    /// Function argument
+    Arg,
+    /// Location of function's return value
+    ReturnPointer,
+}
+
+/// A MIR local.
+///
+/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
+/// argument, or the return pointer.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct VarDecl<'tcx> {
-    /// `let mut x` vs `let x`
+pub struct LocalDecl<'tcx> {
+    /// `let mut x` vs `let x`.
+    ///
+    /// Temporaries and the return pointer are always mutable.
     pub mutability: Mutability,
 
     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 = ...`)
+    /// Type of this local.
     pub ty: Ty<'tcx>,
 
     pub ty: Ty<'tcx>,
 
-    /// source information (span, scope, etc.) for the declaration
-    pub source_info: SourceInfo,
-}
+    /// Name of the local, used in debuginfo and pretty-printing.
+    ///
+    /// Note that function arguments can also have this set to `Some(_)`
+    /// to generate better debuginfo.
+    pub name: Option<Name>,
 
 
-/// A "temp" is a temporary that we place on the stack. They are
-/// anonymous, always mutable, and have only a type.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct TempDecl<'tcx> {
-    pub ty: Ty<'tcx>,
+    /// For user-declared variables, stores their source information.
+    ///
+    /// For temporaries, this is `None`.
+    ///
+    /// This is the primary way to differentiate between user-declared
+    /// variables and compiler-generated temporaries.
+    pub source_info: Option<SourceInfo>,
 }
 
 }
 
-/// A "arg" is one of the function's formal arguments. These are
-/// anonymous and distinct from the bindings that the user declares.
-///
-/// For example, in this function:
-///
-/// ```
-/// fn foo((x, y): (i32, u32)) { ... }
-/// ```
-///
-/// there is only one argument, of type `(i32, u32)`, but two bindings
-/// (`x` and `y`).
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct ArgDecl<'tcx> {
-    pub ty: Ty<'tcx>,
+impl<'tcx> LocalDecl<'tcx> {
+    /// Create a new `LocalDecl` for a temporary.
+    #[inline]
+    pub fn new_temp(ty: Ty<'tcx>) -> Self {
+        LocalDecl {
+            mutability: Mutability::Mut,
+            ty: ty,
+            name: None,
+            source_info: None,
+        }
+    }
 
 
-    /// Either keywords::Invalid or the name of a single-binding
-    /// pattern associated with this argument. Useful for debuginfo.
-    pub debug_name: Name
+    /// Builds a `LocalDecl` for the return pointer.
+    ///
+    /// This must be inserted into the `local_decls` list as the first local.
+    #[inline]
+    pub fn new_return_pointer(return_ty: Ty) -> LocalDecl {
+        LocalDecl {
+            mutability: Mutability::Mut,
+            ty: return_ty,
+            source_info: None,
+            name: None,     // FIXME maybe we do want some name here?
+        }
+    }
 }
 
 /// A closure capture, with its name and mode.
 }
 
 /// A closure capture, with its name and mode.
@@ -442,7 +481,7 @@ pub enum TerminatorKind<'tcx> {
     /// continue. Emitted by build::scope::diverge_cleanup.
     Resume,
 
     /// continue. Emitted by build::scope::diverge_cleanup.
     Resume,
 
-    /// Indicates a normal return. The ReturnPointer lvalue should
+    /// Indicates a normal return. The return pointer lvalue should
     /// have been filled in by now. This should occur at most once.
     Return,
 
     /// have been filled in by now. This should occur at most once.
     Return,
 
@@ -759,31 +798,16 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 ///////////////////////////////////////////////////////////////////////////
 // Lvalues
 
 ///////////////////////////////////////////////////////////////////////////
 // Lvalues
 
-newtype_index!(Var, "var");
-newtype_index!(Temp, "tmp");
-newtype_index!(Arg, "arg");
-newtype_index!(Local, "local");
-
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum Lvalue<'tcx> {
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum Lvalue<'tcx> {
-    /// local variable declared by the user
-    Var(Var),
-
-    /// temporary introduced during lowering into MIR
-    Temp(Temp),
-
-    /// formal parameter of the function; note that these are NOT the
-    /// bindings that the user declares, which are vars
-    Arg(Arg),
+    /// local variable
+    Local(Local),
 
     /// static or static mut variable
     Static(DefId),
 
 
     /// static or static mut variable
     Static(DefId),
 
-    /// the return pointer of the fn
-    ReturnPointer,
-
     /// projection out of an lvalue (access a field, deref a pointer, etc)
     Projection(Box<LvalueProjection<'tcx>>),
 }
     /// projection out of an lvalue (access a field, deref a pointer, etc)
     Projection(Box<LvalueProjection<'tcx>>),
 }
@@ -865,24 +889,6 @@ pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> {
             elem: elem,
         }))
     }
             elem: elem,
         }))
     }
-
-    pub fn from_local(mir: &Mir<'tcx>, local: Local) -> Lvalue<'tcx> {
-        let mut index = local.index();
-        index = match index.checked_sub(mir.arg_decls.len()) {
-            None => return Lvalue::Arg(Arg(index as u32)),
-            Some(index) => index,
-        };
-        index = match index.checked_sub(mir.var_decls.len()) {
-            None => return Lvalue::Var(Var(index as u32)),
-            Some(index) => index,
-        };
-        index = match index.checked_sub(mir.temp_decls.len()) {
-            None => return Lvalue::Temp(Temp(index as u32)),
-            Some(index) => index,
-        };
-        debug_assert!(index == 0);
-        Lvalue::ReturnPointer
-    }
 }
 
 impl<'tcx> Debug for Lvalue<'tcx> {
 }
 
 impl<'tcx> Debug for Lvalue<'tcx> {
@@ -890,13 +896,9 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
         use self::Lvalue::*;
 
         match *self {
         use self::Lvalue::*;
 
         match *self {
-            Var(id) => write!(fmt, "{:?}", id),
-            Arg(id) => write!(fmt, "{:?}", id),
-            Temp(id) => write!(fmt, "{:?}", id),
+            Local(id) => write!(fmt, "{:?}", id),
             Static(def_id) =>
                 write!(fmt, "{}", ty::tls::with(|tcx| tcx.item_path_str(def_id))),
             Static(def_id) =>
                 write!(fmt, "{}", ty::tls::with(|tcx| tcx.item_path_str(def_id))),
-            ReturnPointer =>
-                write!(fmt, "return"),
             Projection(ref data) =>
                 match data.elem {
                     ProjectionElem::Downcast(ref adt_def, index) =>
             Projection(ref data) =>
                 match data.elem {
                     ProjectionElem::Downcast(ref adt_def, index) =>
index 74ad6c602f6cdf47f3bd59bb96d07d29dab6a579..19e980ec73eb148464f492cd0553ef9333fc8515 100644 (file)
@@ -49,12 +49,17 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                          -> LvalueTy<'tcx>
     {
         match *elem {
                          -> LvalueTy<'tcx>
     {
         match *elem {
-            ProjectionElem::Deref =>
+            ProjectionElem::Deref => {
+                let ty = self.to_ty(tcx)
+                             .builtin_deref(true, ty::LvaluePreference::NoPreference)
+                             .unwrap_or_else(|| {
+                                 bug!("deref projection of non-dereferencable ty {:?}", self)
+                             })
+                             .ty;
                 LvalueTy::Ty {
                 LvalueTy::Ty {
-                    ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
-                                          .unwrap()
-                                          .ty
-                },
+                    ty: ty,
+                }
+            }
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                 LvalueTy::Ty {
                     ty: self.to_ty(tcx).builtin_index().unwrap()
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                 LvalueTy::Ty {
                     ty: self.to_ty(tcx).builtin_index().unwrap()
@@ -116,18 +121,12 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 
 impl<'tcx> Lvalue<'tcx> {
     pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
 
 impl<'tcx> Lvalue<'tcx> {
     pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
-        match self {
-            &Lvalue::Var(index) =>
-                LvalueTy::Ty { ty: mir.var_decls[index].ty },
-            &Lvalue::Temp(index) =>
-                LvalueTy::Ty { ty: mir.temp_decls[index].ty },
-            &Lvalue::Arg(index) =>
-                LvalueTy::Ty { ty: mir.arg_decls[index].ty },
-            &Lvalue::Static(def_id) =>
+        match *self {
+            Lvalue::Local(index) =>
+                LvalueTy::Ty { ty: mir.local_decls[index].ty },
+            Lvalue::Static(def_id) =>
                 LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
                 LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
-            &Lvalue::ReturnPointer =>
-                LvalueTy::Ty { ty: mir.return_ty },
-            &Lvalue::Projection(ref proj) =>
+            Lvalue::Projection(ref proj) =>
                 proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
         }
     }
                 proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
         }
     }
index bd42eb3211a8b8acf4b6e1bc89ba8a25b1586eae..9e0bafa4e310f22bafe9244c0c3dfff26c979840 100644 (file)
@@ -236,19 +236,9 @@ fn visit_typed_const_val(&mut self,
                 self.super_typed_const_val(val, location);
             }
 
                 self.super_typed_const_val(val, location);
             }
 
-            fn visit_var_decl(&mut self,
-                              var_decl: & $($mutability)* VarDecl<'tcx>) {
-                self.super_var_decl(var_decl);
-            }
-
-            fn visit_temp_decl(&mut self,
-                               temp_decl: & $($mutability)* TempDecl<'tcx>) {
-                self.super_temp_decl(temp_decl);
-            }
-
-            fn visit_arg_decl(&mut self,
-                              arg_decl: & $($mutability)* ArgDecl<'tcx>) {
-                self.super_arg_decl(arg_decl);
+            fn visit_local_decl(&mut self,
+                                local_decl: & $($mutability)* LocalDecl<'tcx>) {
+                self.super_local_decl(local_decl);
             }
 
             fn visit_visibility_scope(&mut self,
             }
 
             fn visit_visibility_scope(&mut self,
@@ -272,16 +262,8 @@ fn super_mir(&mut self,
 
                 self.visit_ty(&$($mutability)* mir.return_ty);
 
 
                 self.visit_ty(&$($mutability)* mir.return_ty);
 
-                for var_decl in &$($mutability)* mir.var_decls {
-                    self.visit_var_decl(var_decl);
-                }
-
-                for arg_decl in &$($mutability)* mir.arg_decls {
-                    self.visit_arg_decl(arg_decl);
-                }
-
-                for temp_decl in &$($mutability)* mir.temp_decls {
-                    self.visit_temp_decl(temp_decl);
+                for local_decl in &$($mutability)* mir.local_decls {
+                    self.visit_local_decl(local_decl);
                 }
 
                 self.visit_span(&$($mutability)* mir.span);
                 }
 
                 self.visit_span(&$($mutability)* mir.span);
@@ -584,10 +566,7 @@ fn super_lvalue(&mut self,
                             context: LvalueContext<'tcx>,
                             location: Location) {
                 match *lvalue {
                             context: LvalueContext<'tcx>,
                             location: Location) {
                 match *lvalue {
-                    Lvalue::Var(_) |
-                    Lvalue::Temp(_) |
-                    Lvalue::Arg(_) |
-                    Lvalue::ReturnPointer => {
+                    Lvalue::Local(_) => {
                     }
                     Lvalue::Static(ref $($mutability)* def_id) => {
                         self.visit_def_id(def_id, location);
                     }
                     Lvalue::Static(ref $($mutability)* def_id) => {
                         self.visit_def_id(def_id, location);
@@ -639,36 +618,19 @@ fn super_projection_elem(&mut self,
                 }
             }
 
                 }
             }
 
-            fn super_var_decl(&mut self,
-                              var_decl: & $($mutability)* VarDecl<'tcx>) {
-                let VarDecl {
+            fn super_local_decl(&mut self,
+                                local_decl: & $($mutability)* LocalDecl<'tcx>) {
+                let LocalDecl {
                     mutability: _,
                     mutability: _,
-                    name: _,
                     ref $($mutability)* ty,
                     ref $($mutability)* ty,
+                    name: _,
                     ref $($mutability)* source_info,
                     ref $($mutability)* source_info,
-                } = *var_decl;
-
-                self.visit_ty(ty);
-                self.visit_source_info(source_info);
-            }
-
-            fn super_temp_decl(&mut self,
-                               temp_decl: & $($mutability)* TempDecl<'tcx>) {
-                let TempDecl {
-                    ref $($mutability)* ty,
-                } = *temp_decl;
-
-                self.visit_ty(ty);
-            }
-
-            fn super_arg_decl(&mut self,
-                              arg_decl: & $($mutability)* ArgDecl<'tcx>) {
-                let ArgDecl {
-                    ref $($mutability)* ty,
-                    debug_name: _
-                } = *arg_decl;
+                } = *local_decl;
 
                 self.visit_ty(ty);
 
                 self.visit_ty(ty);
+                if let Some(ref $($mutability)* info) = *source_info {
+                    self.visit_source_info(info);
+                }
             }
 
             fn super_visibility_scope(&mut self,
             }
 
             fn super_visibility_scope(&mut self,
index aeb91f06a9aa455947d200861ac94c294adbbee4..a6d8e1fa3c0488552d4d7c0c8ef5a79d2201730a 100644 (file)
@@ -13,7 +13,7 @@
 use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
 use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
-use rustc::mir::repr::{self, Mir};
+use rustc::mir::repr::{self, Mir, LocalKind};
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::super::gather_moves::{MovePathIndex, LookupResult};
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::super::gather_moves::{MovePathIndex, LookupResult};
@@ -73,11 +73,20 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
     assert!(args.len() == 1);
     let peek_arg_lval = match args[0] {
     };
     assert!(args.len() == 1);
     let peek_arg_lval = match args[0] {
-        repr::Operand::Consume(ref lval @ repr::Lvalue::Temp(_)) => {
-            lval
-        }
-        repr::Operand::Consume(_) |
+        repr::Operand::Consume(ref lval) => match *lval {
+             repr::Lvalue::Local(local) if mir.local_kind(local) == LocalKind::Temp => {
+                 Some(lval)
+             }
+             _ => None
+        },
         repr::Operand::Constant(_) => {
         repr::Operand::Constant(_) => {
+            None
+        }
+    };
+
+    let peek_arg_lval = match peek_arg_lval {
+        Some(arg) => arg,
+        None => {
             tcx.sess.diagnostic().span_err(
                 span, "dataflow::sanity_check cannot feed a non-temp to rustc_peek.");
             return;
             tcx.sess.diagnostic().span_err(
                 span, "dataflow::sanity_check cannot feed a non-temp to rustc_peek.");
             return;
index 96702b209a1f5d0b271b8a5e0c7e6f2b5b6e9e1b..188fce467be52c8024be3e5f2606fb51493b7afa 100644 (file)
@@ -118,7 +118,7 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
     env: &'a MoveDataParamEnv<'tcx>,
     flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx>>,
     flow_uninits:  DataflowResults<MaybeUninitializedLvals<'a, 'tcx>>,
     env: &'a MoveDataParamEnv<'tcx>,
     flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx>>,
     flow_uninits:  DataflowResults<MaybeUninitializedLvals<'a, 'tcx>>,
-    drop_flags: FnvHashMap<MovePathIndex, Temp>,
+    drop_flags: FnvHashMap<MovePathIndex, Local>,
     patch: MirPatch<'tcx>,
 }
 
     patch: MirPatch<'tcx>,
 }
 
@@ -164,7 +164,7 @@ fn create_drop_flag(&mut self, index: MovePathIndex) {
     }
 
     fn drop_flag(&mut self, index: MovePathIndex) -> Option<Lvalue<'tcx>> {
     }
 
     fn drop_flag(&mut self, index: MovePathIndex) -> Option<Lvalue<'tcx>> {
-        self.drop_flags.get(&index).map(|t| Lvalue::Temp(*t))
+        self.drop_flags.get(&index).map(|t| Lvalue::Local(*t))
     }
 
     /// create a patch that elaborates all drops in the input
     }
 
     /// create a patch that elaborates all drops in the input
@@ -847,14 +847,14 @@ fn unelaborated_free_block<'a>(
             statements.push(Statement {
                 source_info: c.source_info,
                 kind: StatementKind::Assign(
             statements.push(Statement {
                 source_info: c.source_info,
                 kind: StatementKind::Assign(
-                    Lvalue::Temp(flag),
+                    Lvalue::Local(flag),
                     self.constant_bool(c.source_info.span, false)
                 )
             });
         }
 
         let tcx = self.tcx;
                     self.constant_bool(c.source_info.span, false)
                 )
             });
         }
 
         let tcx = self.tcx;
-        let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil()));
+        let unit_temp = Lvalue::Local(self.patch.new_temp(tcx.mk_nil()));
         let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
             .unwrap_or_else(|e| tcx.sess.fatal(&e));
         let substs = Substs::new(tcx, iter::once(Kind::from(ty)));
         let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
             .unwrap_or_else(|e| tcx.sess.fatal(&e));
         let substs = Substs::new(tcx, iter::once(Kind::from(ty)));
@@ -917,7 +917,7 @@ fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagSta
         if let Some(&flag) = self.drop_flags.get(&path) {
             let span = self.patch.source_info_for_location(self.mir, loc).span;
             let val = self.constant_bool(span, val.value());
         if let Some(&flag) = self.drop_flags.get(&path) {
             let span = self.patch.source_info_for_location(self.mir, loc).span;
             let val = self.constant_bool(span, val.value());
-            self.patch.add_assign(loc, Lvalue::Temp(flag), val);
+            self.patch.add_assign(loc, Lvalue::Local(flag), val);
         }
     }
 
         }
     }
 
@@ -926,7 +926,7 @@ fn drop_flags_on_init(&mut self) {
         let span = self.patch.source_info_for_location(self.mir, loc).span;
         let false_ = self.constant_bool(span, false);
         for flag in self.drop_flags.values() {
         let span = self.patch.source_info_for_location(self.mir, loc).span;
         let false_ = self.constant_bool(span, false);
         for flag in self.drop_flags.values() {
-            self.patch.add_assign(loc, Lvalue::Temp(*flag), false_.clone());
+            self.patch.add_assign(loc, Lvalue::Local(*flag), false_.clone());
         }
     }
 
         }
     }
 
index 6346c1e58897e12e62d32e05abc82e3c38c80fc3..16e25d2b7725810c6bfa3f8086f5f819e995ab22 100644 (file)
@@ -173,13 +173,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 /// Tables mapping from an l-value to its MovePathIndex.
 #[derive(Debug)]
 pub struct MovePathLookup<'tcx> {
 /// Tables mapping from an l-value to its MovePathIndex.
 #[derive(Debug)]
 pub struct MovePathLookup<'tcx> {
-    vars: IndexVec<Var, MovePathIndex>,
-    temps: IndexVec<Temp, MovePathIndex>,
-    args: IndexVec<Arg, MovePathIndex>,
-
-    /// The move path representing the return value is constructed
-    /// lazily when we first encounter it in the input MIR.
-    return_ptr: Option<MovePathIndex>,
+    locals: IndexVec<Local, MovePathIndex>,
 
     /// projections are made from a base-lvalue and a projection
     /// elem. The base-lvalue will have a unique MovePathIndex; we use
 
     /// projections are made from a base-lvalue and a projection
     /// elem. The base-lvalue will have a unique MovePathIndex; we use
@@ -218,16 +212,9 @@ fn new(mir: &'a Mir<'tcx>,
                 moves: IndexVec::new(),
                 loc_map: LocationMap::new(mir),
                 rev_lookup: MovePathLookup {
                 moves: IndexVec::new(),
                 loc_map: LocationMap::new(mir),
                 rev_lookup: MovePathLookup {
-                    vars: mir.var_decls.indices().map(Lvalue::Var).map(|v| {
+                    locals: mir.local_decls.indices().map(Lvalue::Local).map(|v| {
                         Self::new_move_path(&mut move_paths, &mut path_map, None, v)
                     }).collect(),
                         Self::new_move_path(&mut move_paths, &mut path_map, None, v)
                     }).collect(),
-                    temps: mir.temp_decls.indices().map(Lvalue::Temp).map(|t| {
-                        Self::new_move_path(&mut move_paths, &mut path_map, None, t)
-                    }).collect(),
-                    args: mir.arg_decls.indices().map(Lvalue::Arg).map(|a| {
-                        Self::new_move_path(&mut move_paths, &mut path_map, None, a)
-                    }).collect(),
-                    return_ptr: None,
                     projections: FnvHashMap(),
                 },
                 move_paths: move_paths,
                     projections: FnvHashMap(),
                 },
                 move_paths: move_paths,
@@ -272,23 +259,9 @@ fn move_path_for(&mut self, lval: &Lvalue<'tcx>)
     {
         debug!("lookup({:?})", lval);
         match *lval {
     {
         debug!("lookup({:?})", lval);
         match *lval {
-            Lvalue::Var(var) => Ok(self.data.rev_lookup.vars[var]),
-            Lvalue::Arg(arg) => Ok(self.data.rev_lookup.args[arg]),
-            Lvalue::Temp(temp) => Ok(self.data.rev_lookup.temps[temp]),
+            Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]),
             // error: can't move out of a static
             Lvalue::Static(..) => Err(MovePathError::IllegalMove),
             // error: can't move out of a static
             Lvalue::Static(..) => Err(MovePathError::IllegalMove),
-            Lvalue::ReturnPointer => match self.data.rev_lookup.return_ptr {
-                Some(ptr) => Ok(ptr),
-                ref mut ptr @ None => {
-                    let path = Self::new_move_path(
-                        &mut self.data.move_paths,
-                        &mut self.data.path_map,
-                        None,
-                        lval.clone());
-                    *ptr = Some(path);
-                    Ok(path)
-                }
-            },
             Lvalue::Projection(ref proj) => {
                 self.move_path_for_projection(lval, proj)
             }
             Lvalue::Projection(ref proj) => {
                 self.move_path_for_projection(lval, proj)
             }
@@ -373,11 +346,8 @@ impl<'tcx> MovePathLookup<'tcx> {
     // parent.
     pub fn find(&self, lval: &Lvalue<'tcx>) -> LookupResult {
         match *lval {
     // parent.
     pub fn find(&self, lval: &Lvalue<'tcx>) -> LookupResult {
         match *lval {
-            Lvalue::Var(var) => LookupResult::Exact(self.vars[var]),
-            Lvalue::Temp(temp) => LookupResult::Exact(self.temps[temp]),
-            Lvalue::Arg(arg) => LookupResult::Exact(self.args[arg]),
+            Lvalue::Local(local) => LookupResult::Exact(self.locals[local]),
             Lvalue::Static(..) => LookupResult::Parent(None),
             Lvalue::Static(..) => LookupResult::Parent(None),
-            Lvalue::ReturnPointer => LookupResult::Exact(self.return_ptr.unwrap()),
             Lvalue::Projection(ref proj) => {
                 match self.find(&proj.base) {
                     LookupResult::Exact(base_path) => {
             Lvalue::Projection(ref proj) => {
                 match self.find(&proj.base) {
                     LookupResult::Exact(base_path) => {
@@ -486,7 +456,7 @@ fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
             TerminatorKind::Unreachable => { }
 
             TerminatorKind::Return => {
             TerminatorKind::Unreachable => { }
 
             TerminatorKind::Return => {
-                self.gather_move(loc, &Lvalue::ReturnPointer);
+                self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
             }
 
             TerminatorKind::If { .. } |
             }
 
             TerminatorKind::If { .. } |
index f26afdc2b857280ae51891af7712098027323db4..450d29696e77d9ddb5d52021aa67e40d0d3d923a 100644 (file)
@@ -338,8 +338,8 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
     where F: FnMut(MovePathIndex, DropFlagState)
 {
     let move_data = &ctxt.move_data;
     where F: FnMut(MovePathIndex, DropFlagState)
 {
     let move_data = &ctxt.move_data;
-    for (arg, _) in mir.arg_decls.iter_enumerated() {
-        let lvalue = repr::Lvalue::Arg(arg);
+    for arg in mir.arg_iter() {
+        let lvalue = repr::Lvalue::Local(arg);
         let lookup_result = move_data.rev_lookup.find(&lvalue);
         on_lookup_result_bits(tcx, mir, move_data,
                               lookup_result,
         let lookup_result = move_data.rev_lookup.find(&lvalue);
         on_lookup_result_bits(tcx, mir, move_data,
                               lookup_result,
index 52cd1a9f949bf6219b7e1cd7e101a9a7c6ea0d8e..5d018c98684e32870315574b771efd6c814bdb36 100644 (file)
@@ -19,9 +19,9 @@ pub struct MirPatch<'tcx> {
     patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
     new_blocks: Vec<BasicBlockData<'tcx>>,
     new_statements: Vec<(Location, StatementKind<'tcx>)>,
     patch_map: IndexVec<BasicBlock, Option<TerminatorKind<'tcx>>>,
     new_blocks: Vec<BasicBlockData<'tcx>>,
     new_statements: Vec<(Location, StatementKind<'tcx>)>,
-    new_temps: Vec<TempDecl<'tcx>>,
+    new_locals: Vec<LocalDecl<'tcx>>,
     resume_block: BasicBlock,
     resume_block: BasicBlock,
-    next_temp: usize,
+    next_local: usize,
 }
 
 impl<'tcx> MirPatch<'tcx> {
 }
 
 impl<'tcx> MirPatch<'tcx> {
@@ -29,9 +29,9 @@ pub fn new(mir: &Mir<'tcx>) -> Self {
         let mut result = MirPatch {
             patch_map: IndexVec::from_elem(None, mir.basic_blocks()),
             new_blocks: vec![],
         let mut result = MirPatch {
             patch_map: IndexVec::from_elem(None, mir.basic_blocks()),
             new_blocks: vec![],
-            new_temps: vec![],
             new_statements: vec![],
             new_statements: vec![],
-            next_temp: mir.temp_decls.len(),
+            new_locals: vec![],
+            next_local: mir.local_decls.len(),
             resume_block: START_BLOCK
         };
 
             resume_block: START_BLOCK
         };
 
@@ -92,11 +92,11 @@ pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
         }
     }
 
         }
     }
 
-    pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Temp {
-        let index = self.next_temp;
-        self.next_temp += 1;
-        self.new_temps.push(TempDecl { ty: ty });
-        Temp::new(index as usize)
+    pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Local {
+        let index = self.next_local;
+        self.next_local += 1;
+        self.new_locals.push(LocalDecl::new_temp(ty));
+        Local::new(index as usize)
     }
 
     pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
     }
 
     pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
@@ -124,11 +124,11 @@ pub fn add_assign(&mut self, loc: Location, lv: Lvalue<'tcx>, rv: Rvalue<'tcx>)
 
     pub fn apply(self, mir: &mut Mir<'tcx>) {
         debug!("MirPatch: {:?} new temps, starting from index {}: {:?}",
 
     pub fn apply(self, mir: &mut Mir<'tcx>) {
         debug!("MirPatch: {:?} new temps, starting from index {}: {:?}",
-               self.new_temps.len(), mir.temp_decls.len(), self.new_temps);
+               self.new_locals.len(), mir.local_decls.len(), self.new_locals);
         debug!("MirPatch: {} new blocks, starting from index {}",
                self.new_blocks.len(), mir.basic_blocks().len());
         mir.basic_blocks_mut().extend(self.new_blocks);
         debug!("MirPatch: {} new blocks, starting from index {}",
                self.new_blocks.len(), mir.basic_blocks().len());
         mir.basic_blocks_mut().extend(self.new_blocks);
-        mir.temp_decls.extend(self.new_temps);
+        mir.local_decls.extend(self.new_locals);
         for (src, patch) in self.patch_map.into_iter_enumerated() {
             if let Some(patch) = patch {
                 debug!("MirPatch: patching block {:?}", src);
         for (src, patch) in self.patch_map.into_iter_enumerated() {
             if let Some(patch) = patch {
                 debug!("MirPatch: patching block {:?}", src);
index ae5ccbfd820996f8c1b582e66a501032f538797f..a9dfc6ea651e411499c584d392518a5b6b7d7233 100644 (file)
@@ -77,11 +77,11 @@ fn expr_as_lvalue(&mut self,
                 success.and(slice.index(idx))
             }
             ExprKind::SelfRef => {
                 success.and(slice.index(idx))
             }
             ExprKind::SelfRef => {
-                block.and(Lvalue::Arg(Arg::new(0)))
+                block.and(Lvalue::Local(Local::new(1)))
             }
             ExprKind::VarRef { id } => {
                 let index = this.var_indices[&id];
             }
             ExprKind::VarRef { id } => {
                 let index = this.var_indices[&id];
-                block.and(Lvalue::Var(index))
+                block.and(Lvalue::Local(index))
             }
             ExprKind::StaticRef { id } => {
                 block.and(Lvalue::Static(id))
             }
             ExprKind::StaticRef { id } => {
                 block.and(Lvalue::Static(id))
index 8ae23c9103b02ca7c51d7925b05715724e1cda83..9448527e6e65f0b9d21cc42084641be7faaf8d3f 100644 (file)
@@ -90,9 +90,13 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
             }
             ExprKind::Return { value } => {
                 block = match value {
             }
             ExprKind::Return { value } => {
                 block = match value {
-                    Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
+                    Some(value) => {
+                        unpack!(this.into(&Lvalue::Local(RETURN_POINTER), block, value))
+                    }
                     None => {
                     None => {
-                        this.cfg.push_assign_unit(block, source_info, &Lvalue::ReturnPointer);
+                        this.cfg.push_assign_unit(block,
+                                                  source_info,
+                                                  &Lvalue::Local(RETURN_POINTER));
                         block
                     }
                 };
                         block
                     }
                 };
index 1b64b4d0b5317861712ebae924b4fec20e60fa32..a9ea82140b536eaf4b985bccba170057bd14aa88 100644 (file)
@@ -123,7 +123,7 @@ pub fn expr_into_pattern(&mut self,
                                    var,
                                    subpattern: None, .. } => {
                 self.storage_live_for_bindings(block, &irrefutable_pat);
                                    var,
                                    subpattern: None, .. } => {
                 self.storage_live_for_bindings(block, &irrefutable_pat);
-                let lvalue = Lvalue::Var(self.var_indices[&var]);
+                let lvalue = Lvalue::Local(self.var_indices[&var]);
                 return self.into(&lvalue, block, initializer);
             }
             _ => {}
                 return self.into(&lvalue, block, initializer);
             }
             _ => {}
@@ -214,7 +214,7 @@ pub fn storage_live_for_bindings(&mut self,
                                      pattern: &Pattern<'tcx>) {
         match *pattern.kind {
             PatternKind::Binding { var, ref subpattern, .. } => {
                                      pattern: &Pattern<'tcx>) {
         match *pattern.kind {
             PatternKind::Binding { var, ref subpattern, .. } => {
-                let lvalue = Lvalue::Var(self.var_indices[&var]);
+                let lvalue = Lvalue::Local(self.var_indices[&var]);
                 let source_info = self.source_info(pattern.span);
                 self.cfg.push(block, Statement {
                     source_info: source_info,
                 let source_info = self.source_info(pattern.span);
                 self.cfg.push(block, Statement {
                     source_info: source_info,
@@ -705,10 +705,10 @@ fn bind_matched_candidate(&mut self,
             let source_info = self.source_info(binding.span);
             self.cfg.push(block, Statement {
                 source_info: source_info,
             let source_info = self.source_info(binding.span);
             self.cfg.push(block, Statement {
                 source_info: source_info,
-                kind: StatementKind::StorageLive(Lvalue::Var(var_index))
+                kind: StatementKind::StorageLive(Lvalue::Local(var_index))
             });
             self.cfg.push_assign(block, source_info,
             });
             self.cfg.push_assign(block, source_info,
-                                 &Lvalue::Var(var_index), rvalue);
+                                 &Lvalue::Local(var_index), rvalue);
         }
     }
 
         }
     }
 
@@ -718,19 +718,19 @@ fn declare_binding(&mut self,
                        name: Name,
                        var_id: NodeId,
                        var_ty: Ty<'tcx>)
                        name: Name,
                        var_id: NodeId,
                        var_ty: Ty<'tcx>)
-                       -> Var
+                       -> Local
     {
         debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?})",
                var_id, name, var_ty, source_info);
 
     {
         debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?})",
                var_id, name, var_ty, source_info);
 
-        let var = self.var_decls.push(VarDecl::<'tcx> {
-            source_info: source_info,
+        let var = self.local_decls.push(LocalDecl::<'tcx> {
             mutability: mutability,
             mutability: mutability,
-            name: name,
             ty: var_ty.clone(),
             ty: var_ty.clone(),
+            name: Some(name),
+            source_info: Some(source_info),
         });
         let extent = self.extent_of_innermost_scope();
         });
         let extent = self.extent_of_innermost_scope();
-        self.schedule_drop(source_info.span, extent, &Lvalue::Var(var), var_ty);
+        self.schedule_drop(source_info.span, extent, &Lvalue::Local(var), var_ty);
         self.var_indices.insert(var_id, var);
 
         debug!("declare_binding: var={:?}", var);
         self.var_indices.insert(var_id, var);
 
         debug!("declare_binding: var={:?}", var);
index 79a4cf73041d7c6e6d120018d37e2297d8ac1a6b..4bc51c3a6252db89c3b1fccadafdf871273ddcaa 100644 (file)
@@ -28,10 +28,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// NB: **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
     pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> {
     /// NB: **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
     pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> {
-        let temp = self.temp_decls.push(TempDecl { ty: ty });
-        let lvalue = Lvalue::Temp(temp);
+        let temp = self.local_decls.push(LocalDecl::new_temp(ty));
+        let lvalue = Lvalue::Local(temp);
         debug!("temp: created temp {:?} with type {:?}",
         debug!("temp: created temp {:?} with type {:?}",
-               lvalue, self.temp_decls[temp].ty);
+               lvalue, self.local_decls[temp].ty);
         lvalue
     }
 
         lvalue
     }
 
index 1f8dffe5871759d87a804f64e4343810deef457c..4f531c9a2f88787f7df8d8fff2713ddcff542e7f 100644 (file)
@@ -28,6 +28,7 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     cfg: CFG<'tcx>,
 
     fn_span: Span,
     cfg: CFG<'tcx>,
 
     fn_span: Span,
+    arg_count: usize,
 
     /// the current set of scopes, updated as we traverse;
     /// see the `scope` module for more details
 
     /// the current set of scopes, updated as we traverse;
     /// see the `scope` module for more details
@@ -49,9 +50,9 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
     visibility_scope: VisibilityScope,
 
     visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
     visibility_scope: VisibilityScope,
 
-    var_decls: IndexVec<Var, VarDecl<'tcx>>,
-    var_indices: NodeMap<Var>,
-    temp_decls: IndexVec<Temp, TempDecl<'tcx>>,
+    /// Maps node ids of variable bindings to the `Local`s created for them.
+    var_indices: NodeMap<Local>,
+    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
     unit_temp: Option<Lvalue<'tcx>>,
 
     /// cached block with the RESUME terminator; this is created
     unit_temp: Option<Lvalue<'tcx>>,
 
     /// cached block with the RESUME terminator; this is created
@@ -157,9 +158,11 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                        -> (Mir<'tcx>, ScopeAuxiliaryVec)
     where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
 {
                                        -> (Mir<'tcx>, ScopeAuxiliaryVec)
     where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
 {
+    let arguments: Vec<_> = arguments.collect();
+
     let tcx = hir.tcx();
     let span = tcx.map.span(fn_id);
     let tcx = hir.tcx();
     let span = tcx.map.span(fn_id);
-    let mut builder = Builder::new(hir, span);
+    let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
 
     let body_id = ast_block.id;
     let call_site_extent =
 
     let body_id = ast_block.id;
     let call_site_extent =
@@ -169,9 +172,9 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         tcx.region_maps.lookup_code_extent(
             CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
     let mut block = START_BLOCK;
         tcx.region_maps.lookup_code_extent(
             CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
     let mut block = START_BLOCK;
-    let arg_decls = unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
-        let arg_decls = unpack!(block = builder.in_scope(arg_extent, block, |builder| {
-            builder.args_and_body(block, return_ty, arguments, arg_extent, ast_block)
+    unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
+        unpack!(block = builder.in_scope(arg_extent, block, |builder| {
+            builder.args_and_body(block, return_ty, &arguments, arg_extent, ast_block)
         }));
 
         let source_info = builder.source_info(span);
         }));
 
         let source_info = builder.source_info(span);
@@ -180,7 +183,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                               TerminatorKind::Goto { target: return_block });
         builder.cfg.terminate(return_block, source_info,
                               TerminatorKind::Return);
                               TerminatorKind::Goto { target: return_block });
         builder.cfg.terminate(return_block, source_info,
                               TerminatorKind::Return);
-        return_block.and(arg_decls)
+        return_block.unit()
     }));
     assert_eq!(block, builder.return_block());
 
     }));
     assert_eq!(block, builder.return_block());
 
@@ -217,7 +220,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         }).collect()
     });
 
         }).collect()
     });
 
-    let (mut mir, aux) = builder.finish(upvar_decls, arg_decls, return_ty);
+    let (mut mir, aux) = builder.finish(upvar_decls, return_ty);
     mir.spread_last_arg = spread_last_arg;
     (mir, aux)
 }
     mir.spread_last_arg = spread_last_arg;
     (mir, aux)
 }
@@ -227,15 +230,16 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
                                        ast_expr: &'tcx hir::Expr)
                                        -> (Mir<'tcx>, ScopeAuxiliaryVec) {
     let tcx = hir.tcx();
                                        ast_expr: &'tcx hir::Expr)
                                        -> (Mir<'tcx>, ScopeAuxiliaryVec) {
     let tcx = hir.tcx();
+    let ty = tcx.expr_ty_adjusted(ast_expr);
     let span = tcx.map.span(item_id);
     let span = tcx.map.span(item_id);
-    let mut builder = Builder::new(hir, span);
+    let mut builder = Builder::new(hir, span, 0, ty);
 
     let extent = tcx.region_maps.temporary_scope(ast_expr.id)
                     .unwrap_or(ROOT_CODE_EXTENT);
     let mut block = START_BLOCK;
     let _ = builder.in_scope(extent, block, |builder| {
         let expr = builder.hir.mirror(ast_expr);
 
     let extent = tcx.region_maps.temporary_scope(ast_expr.id)
                     .unwrap_or(ROOT_CODE_EXTENT);
     let mut block = START_BLOCK;
     let _ = builder.in_scope(extent, block, |builder| {
         let expr = builder.hir.mirror(ast_expr);
-        unpack!(block = builder.into(&Lvalue::ReturnPointer, block, expr));
+        unpack!(block = builder.into(&Lvalue::Local(RETURN_POINTER), block, expr));
 
         let source_info = builder.source_info(span);
         let return_block = builder.return_block();
 
         let source_info = builder.source_info(span);
         let return_block = builder.return_block();
@@ -247,23 +251,26 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
         return_block.unit()
     });
 
         return_block.unit()
     });
 
-    let ty = tcx.expr_ty_adjusted(ast_expr);
-    builder.finish(vec![], IndexVec::new(), ty)
+    builder.finish(vec![], ty)
 }
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
-    fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span) -> Builder<'a, 'gcx, 'tcx> {
+    fn new(hir: Cx<'a, 'gcx, 'tcx>,
+           span: Span,
+           arg_count: usize,
+           return_ty: Ty<'tcx>)
+           -> Builder<'a, 'gcx, 'tcx> {
         let mut builder = Builder {
             hir: hir,
             cfg: CFG { basic_blocks: IndexVec::new() },
             fn_span: span,
         let mut builder = Builder {
             hir: hir,
             cfg: CFG { basic_blocks: IndexVec::new() },
             fn_span: span,
+            arg_count: arg_count,
             scopes: vec![],
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
             scope_auxiliary: IndexVec::new(),
             loop_scopes: vec![],
             scopes: vec![],
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
             scope_auxiliary: IndexVec::new(),
             loop_scopes: vec![],
-            temp_decls: IndexVec::new(),
-            var_decls: IndexVec::new(),
+            local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1),
             var_indices: NodeMap(),
             unit_temp: None,
             cached_resume_block: None,
             var_indices: NodeMap(),
             unit_temp: None,
             cached_resume_block: None,
@@ -279,7 +286,6 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span) -> Builder<'a, 'gcx, 'tcx> {
 
     fn finish(self,
               upvar_decls: Vec<UpvarDecl>,
 
     fn finish(self,
               upvar_decls: Vec<UpvarDecl>,
-              arg_decls: IndexVec<Arg, ArgDecl<'tcx>>,
               return_ty: Ty<'tcx>)
               -> (Mir<'tcx>, ScopeAuxiliaryVec) {
         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
               return_ty: Ty<'tcx>)
               -> (Mir<'tcx>, ScopeAuxiliaryVec) {
         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
@@ -292,27 +298,45 @@ fn finish(self,
                   self.visibility_scopes,
                   IndexVec::new(),
                   return_ty,
                   self.visibility_scopes,
                   IndexVec::new(),
                   return_ty,
-                  self.var_decls,
-                  arg_decls,
-                  self.temp_decls,
+                  self.local_decls,
+                  self.arg_count,
                   upvar_decls,
                   self.fn_span
         ), self.scope_auxiliary)
     }
 
                   upvar_decls,
                   self.fn_span
         ), self.scope_auxiliary)
     }
 
-    fn args_and_body<A>(&mut self,
-                        mut block: BasicBlock,
-                        return_ty: Ty<'tcx>,
-                        arguments: A,
-                        argument_extent: CodeExtent,
-                        ast_block: &'gcx hir::Block)
-                        -> BlockAnd<IndexVec<Arg, ArgDecl<'tcx>>>
-        where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
+    fn args_and_body(&mut self,
+                     mut block: BasicBlock,
+                     return_ty: Ty<'tcx>,
+                     arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
+                     argument_extent: CodeExtent,
+                     ast_block: &'gcx hir::Block)
+                     -> BlockAnd<()>
     {
     {
-        // to start, translate the argument patterns and collect the argument types.
+        // Allocate locals for the function arguments
+        for &(ty, pattern) in arguments.iter() {
+            // If this is a simple binding pattern, give the local a nice name for debuginfo.
+            let mut name = None;
+            if let Some(pat) = pattern {
+                if let hir::PatKind::Binding(_, ref ident, _) = pat.node {
+                    name = Some(ident.node);
+                }
+            }
+
+            self.local_decls.push(LocalDecl {
+                mutability: Mutability::Not,
+                ty: ty,
+                source_info: None,
+                name: name,
+            });
+        }
+
         let mut scope = None;
         let mut scope = None;
-        let arg_decls = arguments.enumerate().map(|(index, (ty, pattern))| {
-            let lvalue = Lvalue::Arg(Arg::new(index));
+        // Bind the argument patterns
+        for (index, &(ty, pattern)) in arguments.iter().enumerate() {
+            // Function arguments always get the first Local indices after the return pointer
+            let lvalue = Lvalue::Local(Local::new(index + 1));
+
             if let Some(pattern) = pattern {
                 let pattern = self.hir.irrefutable_pat(pattern);
                 scope = self.declare_bindings(scope, ast_block.span, &pattern);
             if let Some(pattern) = pattern {
                 let pattern = self.hir.irrefutable_pat(pattern);
                 scope = self.declare_bindings(scope, ast_block.span, &pattern);
@@ -323,18 +347,7 @@ fn args_and_body<A>(&mut self,
             self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
                                argument_extent, &lvalue, ty);
 
             self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
                                argument_extent, &lvalue, ty);
 
-            let mut name = keywords::Invalid.name();
-            if let Some(pat) = pattern {
-                if let hir::PatKind::Binding(_, ref ident, _) = pat.node {
-                    name = ident.node;
-                }
-            }
-
-            ArgDecl {
-                ty: ty,
-                debug_name: name
-            }
-        }).collect();
+        }
 
         // Enter the argument pattern bindings visibility scope, if it exists.
         if let Some(visibility_scope) = scope {
 
         // Enter the argument pattern bindings visibility scope, if it exists.
         if let Some(visibility_scope) = scope {
@@ -344,9 +357,10 @@ fn args_and_body<A>(&mut self,
         // FIXME(#32959): temporary hack for the issue at hand
         let return_is_unit = return_ty.is_nil();
         // start the first basic block and translate the body
         // FIXME(#32959): temporary hack for the issue at hand
         let return_is_unit = return_ty.is_nil();
         // start the first basic block and translate the body
-        unpack!(block = self.ast_block(&Lvalue::ReturnPointer, return_is_unit, block, ast_block));
+        unpack!(block = self.ast_block(&Lvalue::Local(RETURN_POINTER),
+                return_is_unit, block, ast_block));
 
 
-        block.and(arg_decls)
+        block.unit()
     }
 
     fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
     }
 
     fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
index 0b33e5a145083fabc58475ea20d0f153480413cb..88c2c17476eaf827eeeb197259f05e0a81fb539c 100644 (file)
@@ -26,7 +26,7 @@
 For now, we keep a mapping from each `CodeExtent` to its
 corresponding SEME region for later reference (see caveat in next
 paragraph). This is because region scopes are tied to
 For now, we keep a mapping from each `CodeExtent` to its
 corresponding SEME region for later reference (see caveat in next
 paragraph). This is because region scopes are tied to
-them. Eventually, when we shift to non-lexical lifetimes, three should
+them. Eventually, when we shift to non-lexical lifetimes, there should
 be no need to remember this mapping.
 
 There is one additional wrinkle, actually, that I wanted to hide from
 be no need to remember this mapping.
 
 There is one additional wrinkle, actually, that I wanted to hide from
@@ -67,7 +67,7 @@
 early exit occurs, the method `exit_scope` is called. It is given the
 current point in execution where the early exit occurs, as well as the
 scope you want to branch to (note that all early exits from to some
 early exit occurs, the method `exit_scope` is called. It is given the
 current point in execution where the early exit occurs, as well as the
 scope you want to branch to (note that all early exits from to some
-other enclosing scope). `exit_scope` will record thid exit point and
+other enclosing scope). `exit_scope` will record this exit point and
 also add all drops.
 
 Panics are handled in a similar fashion, except that a panic always
 also add all drops.
 
 Panics are handled in a similar fashion, except that a panic always
@@ -322,7 +322,11 @@ pub fn pop_scope(&mut self,
         self.diverge_cleanup();
         let scope = self.scopes.pop().unwrap();
         assert_eq!(scope.extent, extent);
         self.diverge_cleanup();
         let scope = self.scopes.pop().unwrap();
         assert_eq!(scope.extent, extent);
-        unpack!(block = build_scope_drops(&mut self.cfg, &scope, &self.scopes, block));
+        unpack!(block = build_scope_drops(&mut self.cfg,
+                                          &scope,
+                                          &self.scopes,
+                                          block,
+                                          self.arg_count));
         self.scope_auxiliary[scope.id]
             .postdoms
             .push(self.cfg.current_location(block));
         self.scope_auxiliary[scope.id]
             .postdoms
             .push(self.cfg.current_location(block));
@@ -362,7 +366,11 @@ pub fn exit_scope(&mut self,
                 scope.cached_exits.insert((target, extent), b);
                 b
             };
                 scope.cached_exits.insert((target, extent), b);
                 b
             };
-            unpack!(block = build_scope_drops(&mut self.cfg, scope, rest, block));
+            unpack!(block = build_scope_drops(&mut self.cfg,
+                                              scope,
+                                              rest,
+                                              block,
+                                              self.arg_count));
             if let Some(ref free_data) = scope.free {
                 let next = self.cfg.start_new_block();
                 let free = build_free(self.hir.tcx(), &tmp, free_data, next);
             if let Some(ref free_data) = scope.free {
                 let next = self.cfg.start_new_block();
                 let free = build_free(self.hir.tcx(), &tmp, free_data, next);
@@ -454,7 +462,7 @@ pub fn schedule_drop(&mut self,
         } else {
             // Only temps and vars need their storage dead.
             match *lvalue {
         } else {
             // Only temps and vars need their storage dead.
             match *lvalue {
-                Lvalue::Temp(_) | Lvalue::Var(_) => DropKind::Storage,
+                Lvalue::Local(index) if index.index() > self.arg_count + 1 => DropKind::Storage,
                 _ => return
             }
         };
                 _ => return
             }
         };
@@ -671,7 +679,8 @@ pub fn assert(&mut self, block: BasicBlock,
 fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
                            scope: &Scope<'tcx>,
                            earlier_scopes: &[Scope<'tcx>],
 fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
                            scope: &Scope<'tcx>,
                            earlier_scopes: &[Scope<'tcx>],
-                           mut block: BasicBlock)
+                           mut block: BasicBlock,
+                           arg_count: usize)
                            -> BlockAnd<()> {
     let mut iter = scope.drops.iter().rev().peekable();
     while let Some(drop_data) = iter.next() {
                            -> BlockAnd<()> {
     let mut iter = scope.drops.iter().rev().peekable();
     while let Some(drop_data) = iter.next() {
@@ -703,7 +712,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
             DropKind::Storage => {
                 // Only temps and vars need their storage dead.
                 match drop_data.location {
             DropKind::Storage => {
                 // Only temps and vars need their storage dead.
                 match drop_data.location {
-                    Lvalue::Temp(_) | Lvalue::Var(_) => {}
+                    Lvalue::Local(index) if index.index() > arg_count => {}
                     _ => continue
                 }
 
                     _ => continue
                 }
 
index 11b4441c8460a62e486194febb783ba9b2d1ec0c..343d802119ea0d8287c58aa22f1d26e5dbb5b38f 100644 (file)
 
 use rustc::mir::repr::{Local, Location, Lvalue, Mir};
 use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
 
 use rustc::mir::repr::{Local, Location, Lvalue, Mir};
 use rustc::mir::visit::{LvalueContext, MutVisitor, Visitor};
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::indexed_vec::IndexVec;
 use std::marker::PhantomData;
 use std::mem;
 
 pub struct DefUseAnalysis<'tcx> {
     info: IndexVec<Local, Info<'tcx>>,
 use std::marker::PhantomData;
 use std::mem;
 
 pub struct DefUseAnalysis<'tcx> {
     info: IndexVec<Local, Info<'tcx>>,
-    mir_summary: MirSummary,
 }
 
 #[derive(Clone)]
 }
 
 #[derive(Clone)]
@@ -35,15 +34,13 @@ pub struct Use<'tcx> {
 impl<'tcx> DefUseAnalysis<'tcx> {
     pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
         DefUseAnalysis {
 impl<'tcx> DefUseAnalysis<'tcx> {
     pub fn new(mir: &Mir<'tcx>) -> DefUseAnalysis<'tcx> {
         DefUseAnalysis {
-            info: IndexVec::from_elem_n(Info::new(), mir.count_locals()),
-            mir_summary: MirSummary::new(mir),
+            info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
         }
     }
 
     pub fn analyze(&mut self, mir: &Mir<'tcx>) {
         let mut finder = DefUseFinder {
             info: mem::replace(&mut self.info, IndexVec::new()),
         }
     }
 
     pub fn analyze(&mut self, mir: &Mir<'tcx>) {
         let mut finder = DefUseFinder {
             info: mem::replace(&mut self.info, IndexVec::new()),
-            mir_summary: self.mir_summary,
         };
         finder.visit_mir(mir);
         self.info = finder.info
         };
         finder.visit_mir(mir);
         self.info = finder.info
@@ -64,7 +61,6 @@ fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callbac
         for lvalue_use in &self.info[local].defs_and_uses {
             MutateUseVisitor::new(local,
                                   &mut callback,
         for lvalue_use in &self.info[local].defs_and_uses {
             MutateUseVisitor::new(local,
                                   &mut callback,
-                                  self.mir_summary,
                                   mir).visit_location(mir, lvalue_use.location)
         }
     }
                                   mir).visit_location(mir, lvalue_use.location)
         }
     }
@@ -80,13 +76,17 @@ pub fn replace_all_defs_and_uses_with(&self,
 
 struct DefUseFinder<'tcx> {
     info: IndexVec<Local, Info<'tcx>>,
 
 struct DefUseFinder<'tcx> {
     info: IndexVec<Local, Info<'tcx>>,
-    mir_summary: MirSummary,
 }
 
 impl<'tcx> DefUseFinder<'tcx> {
     fn lvalue_mut_info(&mut self, lvalue: &Lvalue<'tcx>) -> Option<&mut Info<'tcx>> {
         let info = &mut self.info;
 }
 
 impl<'tcx> DefUseFinder<'tcx> {
     fn lvalue_mut_info(&mut self, lvalue: &Lvalue<'tcx>) -> Option<&mut Info<'tcx>> {
         let info = &mut self.info;
-        self.mir_summary.local_index(lvalue).map(move |local| &mut info[local])
+
+        if let Lvalue::Local(local) = *lvalue {
+            Some(&mut info[local])
+        } else {
+            None
+        }
     }
 }
 
     }
 }
 
@@ -132,18 +132,16 @@ pub fn use_count(&self) -> usize {
 struct MutateUseVisitor<'tcx, F> {
     query: Local,
     callback: F,
 struct MutateUseVisitor<'tcx, F> {
     query: Local,
     callback: F,
-    mir_summary: MirSummary,
     phantom: PhantomData<&'tcx ()>,
 }
 
 impl<'tcx, F> MutateUseVisitor<'tcx, F> {
     phantom: PhantomData<&'tcx ()>,
 }
 
 impl<'tcx, F> MutateUseVisitor<'tcx, F> {
-    fn new(query: Local, callback: F, mir_summary: MirSummary, _: &Mir<'tcx>)
+    fn new(query: Local, callback: F, _: &Mir<'tcx>)
            -> MutateUseVisitor<'tcx, F>
            where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
         MutateUseVisitor {
             query: query,
             callback: callback,
            -> MutateUseVisitor<'tcx, F>
            where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
         MutateUseVisitor {
             query: query,
             callback: callback,
-            mir_summary: mir_summary,
             phantom: PhantomData,
         }
     }
             phantom: PhantomData,
         }
     }
@@ -155,43 +153,11 @@ fn visit_lvalue(&mut self,
                     lvalue: &mut Lvalue<'tcx>,
                     context: LvalueContext<'tcx>,
                     location: Location) {
                     lvalue: &mut Lvalue<'tcx>,
                     context: LvalueContext<'tcx>,
                     location: Location) {
-        if self.mir_summary.local_index(lvalue) == Some(self.query) {
-            (self.callback)(lvalue, context, location)
-        }
-        self.super_lvalue(lvalue, context, location)
-    }
-}
-
-/// A small structure that enables various metadata of the MIR to be queried
-/// without a reference to the MIR itself.
-#[derive(Clone, Copy)]
-pub struct MirSummary {
-    arg_count: usize,
-    var_count: usize,
-    temp_count: usize,
-}
-
-impl MirSummary {
-    pub fn new(mir: &Mir) -> MirSummary {
-        MirSummary {
-            arg_count: mir.arg_decls.len(),
-            var_count: mir.var_decls.len(),
-            temp_count: mir.temp_decls.len(),
-        }
-    }
-
-    pub fn local_index<'tcx>(&self, lvalue: &Lvalue<'tcx>) -> Option<Local> {
-        match *lvalue {
-            Lvalue::Arg(arg) => Some(Local::new(arg.index())),
-            Lvalue::Var(var) => Some(Local::new(var.index() + self.arg_count)),
-            Lvalue::Temp(temp) => {
-                Some(Local::new(temp.index() + self.arg_count + self.var_count))
+        if let Lvalue::Local(local) = *lvalue {
+            if local == self.query {
+                (self.callback)(lvalue, context, location)
             }
             }
-            Lvalue::ReturnPointer => {
-                Some(Local::new(self.arg_count + self.var_count + self.temp_count))
-            }
-            _ => None,
         }
         }
+        self.super_lvalue(lvalue, context, location)
     }
 }
     }
 }
-
index 72b6d7f0e5aa514605252addab0cc268760c4650..b80e11a63db7a0dd7c6895e4b3a2cbf973da3548 100644 (file)
@@ -136,30 +136,31 @@ fn write_graph_label<'a, 'tcx, W: Write>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
 
     // fn argument types.
     write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
 
     // fn argument types.
-    for (i, arg) in mir.arg_decls.iter().enumerate() {
+    for (i, arg) in mir.arg_iter().enumerate() {
         if i > 0 {
             write!(w, ", ")?;
         }
         if i > 0 {
             write!(w, ", ")?;
         }
-        write!(w, "{:?}: {}", Lvalue::Arg(Arg::new(i)), escape(&arg.ty))?;
+        write!(w, "{:?}: {}", Lvalue::Local(arg), escape(&mir.local_decls[arg].ty))?;
     }
 
     write!(w, ") -&gt; {}", escape(mir.return_ty))?;
     write!(w, r#"<br align="left"/>"#)?;
 
     }
 
     write!(w, ") -&gt; {}", escape(mir.return_ty))?;
     write!(w, r#"<br align="left"/>"#)?;
 
-    // User variable types (including the user's name in a comment).
-    for (i, var) in mir.var_decls.iter().enumerate() {
+    for local in mir.var_and_temp_iter() {
+        let decl = &mir.local_decls[local];
+
         write!(w, "let ")?;
         write!(w, "let ")?;
-        if var.mutability == Mutability::Mut {
+        if decl.mutability == Mutability::Mut {
             write!(w, "mut ")?;
         }
             write!(w, "mut ")?;
         }
-        write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
-               Lvalue::Var(Var::new(i)), escape(&var.ty), var.name)?;
-    }
 
 
-    // Compiler-introduced temporary types.
-    for (i, temp) in mir.temp_decls.iter().enumerate() {
-        write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
-               Lvalue::Temp(Temp::new(i)), escape(&temp.ty))?;
+        if let Some(name) = decl.name {
+            write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
+                   Lvalue::Local(local), escape(&decl.ty), name)?;
+        } else {
+            write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
+                   Lvalue::Local(local), escape(&decl.ty))?;
+        }
     }
 
     writeln!(w, ">;")
     }
 
     writeln!(w, ">;")
@@ -172,3 +173,5 @@ fn node(block: BasicBlock) -> String {
 fn escape<T: Debug>(t: &T) -> String {
     dot::escape_html(&format!("{:?}", t))
 }
 fn escape<T: Debug>(t: &T) -> String {
     dot::escape_html(&format!("{:?}", t))
 }
+
+// TODO manually test
index 01e2c6308ba01b9ef9d00a81e6da5519fb08a64f..b687c52447cdadb419b0e68189bf1b1f8745483a 100644 (file)
@@ -214,6 +214,9 @@ fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
     format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
 }
 
     format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
 }
 
+/// Prints user-defined variables in a scope tree.
+///
+/// Returns the total number of variables printed.
 fn write_scope_tree(tcx: TyCtxt,
                     mir: &Mir,
                     scope_tree: &FnvHashMap<VisibilityScope, Vec<VisibilityScope>>,
 fn write_scope_tree(tcx: TyCtxt,
                     mir: &Mir,
                     scope_tree: &FnvHashMap<VisibilityScope, Vec<VisibilityScope>>,
@@ -234,11 +237,14 @@ fn write_scope_tree(tcx: TyCtxt,
         writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
 
         // User variable types (including the user's name in a comment).
         writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
 
         // User variable types (including the user's name in a comment).
-        for (id, var) in mir.var_decls.iter_enumerated() {
-            // Skip if not declared in this scope.
-            if var.source_info.scope != child {
+        for local in mir.var_iter() {
+            let var = &mir.local_decls[local];
+            let (name, source_info) = if var.source_info.unwrap().scope == child {
+                (var.name.unwrap(), var.source_info.unwrap())
+            } else {
+                // Not a variable or not declared in this scope.
                 continue;
                 continue;
-            }
+            };
 
             let mut_str = if var.mutability == Mutability::Mut {
                 "mut "
 
             let mut_str = if var.mutability == Mutability::Mut {
                 "mut "
@@ -251,13 +257,13 @@ fn write_scope_tree(tcx: TyCtxt,
                                        INDENT,
                                        indent,
                                        mut_str,
                                        INDENT,
                                        indent,
                                        mut_str,
-                                       id,
+                                       local,
                                        var.ty);
             writeln!(w, "{0:1$} // \"{2}\" in {3}",
                      indented_var,
                      ALIGN,
                                        var.ty);
             writeln!(w, "{0:1$} // \"{2}\" in {3}",
                      indented_var,
                      ALIGN,
-                     var.name,
-                     comment(tcx, var.source_info))?;
+                     name,
+                     comment(tcx, source_info))?;
         }
 
         write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
         }
 
         write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
@@ -291,9 +297,23 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
         }
     }
 
+    // Print return pointer
+    let indented_retptr = format!("{}let mut {:?}: {};",
+                                  INDENT,
+                                  RETURN_POINTER,
+                                  mir.return_ty);
+    writeln!(w, "{0:1$} // return pointer",
+             indented_retptr,
+             ALIGN)?;
+
     write_scope_tree(tcx, mir, &scope_tree, w, ARGUMENT_VISIBILITY_SCOPE, 1)?;
 
     write_scope_tree(tcx, mir, &scope_tree, w, ARGUMENT_VISIBILITY_SCOPE, 1)?;
 
-    write_mir_decls(mir, w)
+    write_temp_decls(mir, w)?;
+
+    // Add an empty line before the first block is printed.
+    writeln!(w, "")?;
+
+    Ok(())
 }
 
 fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
 }
 
 fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
@@ -313,30 +333,27 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
         write!(w, "(")?;
 
         // fn argument types.
         write!(w, "(")?;
 
         // fn argument types.
-        for (i, arg) in mir.arg_decls.iter_enumerated() {
-            if i.index() != 0 {
+        for (i, arg) in mir.arg_iter().enumerate() {
+            if i != 0 {
                 write!(w, ", ")?;
             }
                 write!(w, ", ")?;
             }
-            write!(w, "{:?}: {}", Lvalue::Arg(i), arg.ty)?;
+            write!(w, "{:?}: {}", Lvalue::Local(arg), mir.local_decls[arg].ty)?;
         }
 
         write!(w, ") -> {}", mir.return_ty)
     } else {
         }
 
         write!(w, ") -> {}", mir.return_ty)
     } else {
-        assert!(mir.arg_decls.is_empty());
+        assert_eq!(mir.arg_count, 0);
         write!(w, ": {} =", mir.return_ty)
     }
 }
 
         write!(w, ": {} =", mir.return_ty)
     }
 }
 
-fn write_mir_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
+fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
     // Compiler-introduced temporary types.
     // Compiler-introduced temporary types.
-    for (id, temp) in mir.temp_decls.iter_enumerated() {
-        writeln!(w, "{}let mut {:?}: {};", INDENT, id, temp.ty)?;
-    }
-
-    // Wrote any declaration? Add an empty line before the first block is printed.
-    if !mir.var_decls.is_empty() || !mir.temp_decls.is_empty() {
-        writeln!(w, "")?;
+    for temp in mir.temp_iter() {
+        writeln!(w, "{}let mut {:?}: {};", INDENT, temp, mir.local_decls[temp].ty)?;
     }
 
     Ok(())
 }
     }
 
     Ok(())
 }
+
+// TODO manually test
index 79fd16012d9ee24780e6449bd8baa4706a3ad109..783162cd5588fd90510ad4c7b6c008d57691b13e 100644 (file)
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
-use def_use::{DefUseAnalysis, MirSummary};
+use def_use::DefUseAnalysis;
 use rustc::mir::repr::{Constant, Local, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
 use rustc::mir::transform::{MirPass, MirSource, Pass};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
 use rustc::mir::repr::{Constant, Local, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
 use rustc::mir::transform::{MirPass, MirSource, Pass};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
-use rustc_data_structures::indexed_vec::Idx;
 use transform::qualify_consts;
 
 pub struct CopyPropagation;
 use transform::qualify_consts;
 
 pub struct CopyPropagation;
@@ -78,9 +77,8 @@ fn run_pass<'a>(&mut self,
             def_use_analysis.analyze(mir);
 
             let mut changed = false;
             def_use_analysis.analyze(mir);
 
             let mut changed = false;
-            for dest_local_index in 0..mir.count_locals() {
-                let dest_local = Local::new(dest_local_index);
-                debug!("Considering destination local: {}", mir.format_local(dest_local));
+            for dest_local in mir.local_decls.indices() {
+                debug!("Considering destination local: {:?}", dest_local);
 
                 let action;
                 let location;
 
                 let action;
                 let location;
@@ -89,19 +87,19 @@ fn run_pass<'a>(&mut self,
                     let dest_use_info = def_use_analysis.local_info(dest_local);
                     let dest_def_count = dest_use_info.def_count_not_including_drop();
                     if dest_def_count == 0 {
                     let dest_use_info = def_use_analysis.local_info(dest_local);
                     let dest_def_count = dest_use_info.def_count_not_including_drop();
                     if dest_def_count == 0 {
-                        debug!("  Can't copy-propagate local: dest {} undefined",
-                               mir.format_local(dest_local));
+                        debug!("  Can't copy-propagate local: dest {:?} undefined",
+                               dest_local);
                         continue
                     }
                     if dest_def_count > 1 {
                         continue
                     }
                     if dest_def_count > 1 {
-                        debug!("  Can't copy-propagate local: dest {} defined {} times",
-                               mir.format_local(dest_local),
+                        debug!("  Can't copy-propagate local: dest {:?} defined {} times",
+                               dest_local,
                                dest_use_info.def_count());
                         continue
                     }
                     if dest_use_info.use_count() == 0 {
                                dest_use_info.def_count());
                         continue
                     }
                     if dest_use_info.use_count() == 0 {
-                        debug!("  Can't copy-propagate local: dest {} unused",
-                               mir.format_local(dest_local));
+                        debug!("  Can't copy-propagate local: dest {:?} unused",
+                               dest_local);
                         continue
                     }
                     let dest_lvalue_def = dest_use_info.defs_and_uses.iter().filter(|lvalue_def| {
                         continue
                     }
                     let dest_lvalue_def = dest_use_info.defs_and_uses.iter().filter(|lvalue_def| {
@@ -121,11 +119,11 @@ fn run_pass<'a>(&mut self,
 
                     // That use of the source must be an assignment.
                     match statement.kind {
 
                     // That use of the source must be an assignment.
                     match statement.kind {
-                        StatementKind::Assign(ref dest_lvalue, Rvalue::Use(ref operand)) if
-                                Some(dest_local) == mir.local_index(dest_lvalue) => {
+                        StatementKind::Assign(Lvalue::Local(local), Rvalue::Use(ref operand)) if
+                                local == dest_local => {
                             let maybe_action = match *operand {
                                 Operand::Consume(ref src_lvalue) => {
                             let maybe_action = match *operand {
                                 Operand::Consume(ref src_lvalue) => {
-                                    Action::local_copy(mir, &def_use_analysis, src_lvalue)
+                                    Action::local_copy(&def_use_analysis, src_lvalue)
                                 }
                                 Operand::Constant(ref src_constant) => {
                                     Action::constant(src_constant)
                                 }
                                 Operand::Constant(ref src_constant) => {
                                     Action::constant(src_constant)
@@ -162,15 +160,14 @@ enum Action<'tcx> {
 }
 
 impl<'tcx> Action<'tcx> {
 }
 
 impl<'tcx> Action<'tcx> {
-    fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_lvalue: &Lvalue<'tcx>)
+    fn local_copy(def_use_analysis: &DefUseAnalysis, src_lvalue: &Lvalue<'tcx>)
                   -> Option<Action<'tcx>> {
         // The source must be a local.
                   -> Option<Action<'tcx>> {
         // The source must be a local.
-        let src_local = match mir.local_index(src_lvalue) {
-            Some(src_local) => src_local,
-            None => {
-                debug!("  Can't copy-propagate local: source is not a local");
-                return None
-            }
+        let src_local = if let Lvalue::Local(local) = *src_lvalue {
+            local
+        } else {
+            debug!("  Can't copy-propagate local: source is not a local");
+            return None;
         };
 
         // We're trying to copy propagate a local.
         };
 
         // We're trying to copy propagate a local.
@@ -225,9 +222,9 @@ fn perform(self,
                 // First, remove all markers.
                 //
                 // FIXME(pcwalton): Don't do this. Merge live ranges instead.
                 // First, remove all markers.
                 //
                 // FIXME(pcwalton): Don't do this. Merge live ranges instead.
-                debug!("  Replacing all uses of {} with {} (local)",
-                       mir.format_local(dest_local),
-                       mir.format_local(src_local));
+                debug!("  Replacing all uses of {:?} with {:?} (local)",
+                       dest_local,
+                       src_local);
                 for lvalue_use in &def_use_analysis.local_info(dest_local).defs_and_uses {
                     if lvalue_use.context.is_storage_marker() {
                         mir.make_statement_nop(lvalue_use.location)
                 for lvalue_use in &def_use_analysis.local_info(dest_local).defs_and_uses {
                     if lvalue_use.context.is_storage_marker() {
                         mir.make_statement_nop(lvalue_use.location)
@@ -240,7 +237,7 @@ fn perform(self,
                 }
 
                 // Replace all uses of the destination local with the source local.
                 }
 
                 // Replace all uses of the destination local with the source local.
-                let src_lvalue = Lvalue::from_local(mir, src_local);
+                let src_lvalue = Lvalue::Local(src_local);
                 def_use_analysis.replace_all_defs_and_uses_with(dest_local, mir, src_lvalue);
 
                 // Finally, zap the now-useless assignment instruction.
                 def_use_analysis.replace_all_defs_and_uses_with(dest_local, mir, src_lvalue);
 
                 // Finally, zap the now-useless assignment instruction.
@@ -253,8 +250,8 @@ fn perform(self,
                 // First, remove all markers.
                 //
                 // FIXME(pcwalton): Don't do this. Merge live ranges instead.
                 // First, remove all markers.
                 //
                 // FIXME(pcwalton): Don't do this. Merge live ranges instead.
-                debug!("  Replacing all uses of {} with {:?} (constant)",
-                       mir.format_local(dest_local),
+                debug!("  Replacing all uses of {:?} with {:?} (constant)",
+                       dest_local,
                        src_constant);
                 let dest_local_info = def_use_analysis.local_info(dest_local);
                 for lvalue_use in &dest_local_info.defs_and_uses {
                        src_constant);
                 let dest_local_info = def_use_analysis.local_info(dest_local);
                 for lvalue_use in &dest_local_info.defs_and_uses {
@@ -264,8 +261,7 @@ fn perform(self,
                 }
 
                 // Replace all uses of the destination local with the constant.
                 }
 
                 // Replace all uses of the destination local with the constant.
-                let mut visitor = ConstantPropagationVisitor::new(MirSummary::new(mir),
-                                                                  dest_local,
+                let mut visitor = ConstantPropagationVisitor::new(dest_local,
                                                                   src_constant);
                 for dest_lvalue_use in &dest_local_info.defs_and_uses {
                     visitor.visit_location(mir, dest_lvalue_use.location)
                                                                   src_constant);
                 for dest_lvalue_use in &dest_local_info.defs_and_uses {
                     visitor.visit_location(mir, dest_lvalue_use.location)
@@ -298,17 +294,15 @@ fn perform(self,
 struct ConstantPropagationVisitor<'tcx> {
     dest_local: Local,
     constant: Constant<'tcx>,
 struct ConstantPropagationVisitor<'tcx> {
     dest_local: Local,
     constant: Constant<'tcx>,
-    mir_summary: MirSummary,
     uses_replaced: usize,
 }
 
 impl<'tcx> ConstantPropagationVisitor<'tcx> {
     uses_replaced: usize,
 }
 
 impl<'tcx> ConstantPropagationVisitor<'tcx> {
-    fn new(mir_summary: MirSummary, dest_local: Local, constant: Constant<'tcx>)
+    fn new(dest_local: Local, constant: Constant<'tcx>)
            -> ConstantPropagationVisitor<'tcx> {
         ConstantPropagationVisitor {
             dest_local: dest_local,
             constant: constant,
            -> ConstantPropagationVisitor<'tcx> {
         ConstantPropagationVisitor {
             dest_local: dest_local,
             constant: constant,
-            mir_summary: mir_summary,
             uses_replaced: 0,
         }
     }
             uses_replaced: 0,
         }
     }
@@ -319,16 +313,11 @@ fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
         self.super_operand(operand, location);
 
         match *operand {
         self.super_operand(operand, location);
 
         match *operand {
-            Operand::Consume(ref lvalue) => {
-                if self.mir_summary.local_index(lvalue) != Some(self.dest_local) {
-                    return
-                }
-            }
-            Operand::Constant(_) => return,
+            Operand::Consume(Lvalue::Local(local)) if local == self.dest_local => {}
+            _ => return,
         }
 
         *operand = Operand::Constant(self.constant.clone());
         self.uses_replaced += 1
     }
 }
         }
 
         *operand = Operand::Constant(self.constant.clone());
         self.uses_replaced += 1
     }
 }
-
index a0331f03b019742e9d1b2f51486deee00187b756..b4159af6f071d8d64de0c6eb5d52a729543944f9 100644 (file)
 
 //! Performs various peephole optimizations.
 
 
 //! Performs various peephole optimizations.
 
-use rustc::mir::repr::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue};
+use rustc::mir::repr::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::transform::{MirPass, MirSource, Pass};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::TyCtxt;
 use rustc::util::nodemap::FnvHashSet;
 use rustc::mir::transform::{MirPass, MirSource, Pass};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::TyCtxt;
 use rustc::util::nodemap::FnvHashSet;
+use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
 
 pub struct InstCombine {
 use std::mem;
 
 pub struct InstCombine {
@@ -61,7 +62,8 @@ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
             debug!("Replacing `&*`: {:?}", rvalue);
             let new_lvalue = match *rvalue {
                 Rvalue::Ref(_, _, Lvalue::Projection(ref mut projection)) => {
             debug!("Replacing `&*`: {:?}", rvalue);
             let new_lvalue = match *rvalue {
                 Rvalue::Ref(_, _, Lvalue::Projection(ref mut projection)) => {
-                    mem::replace(&mut projection.base, Lvalue::ReturnPointer)
+                    // Replace with dummy
+                    mem::replace(&mut projection.base, Lvalue::Local(Local::new(0)))
                 }
                 _ => bug!("Detected `&*` but didn't find `&*`!"),
             };
                 }
                 _ => bug!("Detected `&*` but didn't find `&*`!"),
             };
@@ -107,4 +109,3 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
 struct OptimizationList {
     and_stars: FnvHashSet<Location>,
 }
 struct OptimizationList {
     and_stars: FnvHashSet<Location>,
 }
-
index 57de68fce1d1a4543e435b08bf4cc0b847fa00ba..939531a16bc8659c8a508fd02145446195048d95 100644 (file)
@@ -30,6 +30,7 @@
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
+use std::iter;
 use std::mem;
 use std::usize;
 
 use std::mem;
 use std::usize;
 
@@ -74,15 +75,21 @@ pub enum Candidate {
     ShuffleIndices(BasicBlock)
 }
 
     ShuffleIndices(BasicBlock)
 }
 
-struct TempCollector {
-    temps: IndexVec<Temp, TempState>,
-    span: Span
+struct TempCollector<'tcx> {
+    temps: IndexVec<Local, TempState>,
+    span: Span,
+    mir: &'tcx Mir<'tcx>,
 }
 
 }
 
-impl<'tcx> Visitor<'tcx> for TempCollector {
-    fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext, location: Location) {
+impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
+    fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext<'tcx>, location: Location) {
         self.super_lvalue(lvalue, context, location);
         self.super_lvalue(lvalue, context, location);
-        if let Lvalue::Temp(index) = *lvalue {
+        if let Lvalue::Local(index) = *lvalue {
+            // We're only interested in temporaries
+            if self.mir.local_kind(index) != LocalKind::Temp {
+                return;
+            }
+
             // Ignore drops, if the temp gets promoted,
             // then it's constant and thus drop is noop.
             // Storage live ranges are also irrelevant.
             // Ignore drops, if the temp gets promoted,
             // then it's constant and thus drop is noop.
             // Storage live ranges are also irrelevant.
@@ -126,10 +133,11 @@ fn visit_source_info(&mut self, source_info: &SourceInfo) {
     }
 }
 
     }
 }
 
-pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec<Temp, TempState> {
+pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec<Local, TempState> {
     let mut collector = TempCollector {
     let mut collector = TempCollector {
-        temps: IndexVec::from_elem(TempState::Undefined, &mir.temp_decls),
-        span: mir.span
+        temps: IndexVec::from_elem(TempState::Undefined, &mir.local_decls),
+        span: mir.span,
+        mir: mir,
     };
     for (bb, data) in rpo {
         collector.visit_basic_block_data(bb, data);
     };
     for (bb, data) in rpo {
         collector.visit_basic_block_data(bb, data);
@@ -140,7 +148,7 @@ pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec<Temp, Te
 struct Promoter<'a, 'tcx: 'a> {
     source: &'a mut Mir<'tcx>,
     promoted: Mir<'tcx>,
 struct Promoter<'a, 'tcx: 'a> {
     source: &'a mut Mir<'tcx>,
     promoted: Mir<'tcx>,
-    temps: &'a mut IndexVec<Temp, TempState>,
+    temps: &'a mut IndexVec<Local, TempState>,
 
     /// If true, all nested temps are also kept in the
     /// source MIR, not moved to the promoted MIR.
 
     /// If true, all nested temps are also kept in the
     /// source MIR, not moved to the promoted MIR.
@@ -177,7 +185,7 @@ fn assign(&mut self, dest: Lvalue<'tcx>, rvalue: Rvalue<'tcx>, span: Span) {
 
     /// Copy the initialization of this temp to the
     /// promoted MIR, recursing through temps.
 
     /// Copy the initialization of this temp to the
     /// promoted MIR, recursing through temps.
-    fn promote_temp(&mut self, temp: Temp) -> Temp {
+    fn promote_temp(&mut self, temp: Local) -> Local {
         let old_keep_original = self.keep_original;
         let (bb, stmt_idx) = match self.temps[temp] {
             TempState::Defined {
         let old_keep_original = self.keep_original;
         let (bb, stmt_idx) = match self.temps[temp] {
             TempState::Defined {
@@ -259,20 +267,19 @@ fn promote_temp(&mut self, temp: Temp) -> Temp {
             });
         }
 
             });
         }
 
-        let new_temp = self.promoted.temp_decls.push(TempDecl {
-            ty: self.source.temp_decls[temp].ty
-        });
+        let new_temp = self.promoted.local_decls.push(
+            LocalDecl::new_temp(self.source.local_decls[temp].ty));
 
         // Inject the Rvalue or Call into the promoted MIR.
         if stmt_idx < no_stmts {
 
         // Inject the Rvalue or Call into the promoted MIR.
         if stmt_idx < no_stmts {
-            self.assign(Lvalue::Temp(new_temp), rvalue.unwrap(), source_info.span);
+            self.assign(Lvalue::Local(new_temp), rvalue.unwrap(), source_info.span);
         } else {
             let last = self.promoted.basic_blocks().last().unwrap();
             let new_target = self.new_block();
             let mut call = call.unwrap();
             match call {
                 TerminatorKind::Call { ref mut destination, ..}  => {
         } else {
             let last = self.promoted.basic_blocks().last().unwrap();
             let new_target = self.new_block();
             let mut call = call.unwrap();
             match call {
                 TerminatorKind::Call { ref mut destination, ..}  => {
-                    *destination = Some((Lvalue::Temp(new_temp), new_target));
+                    *destination = Some((Lvalue::Local(new_temp), new_target));
                 }
                 _ => bug!()
             }
                 }
                 _ => bug!()
             }
@@ -315,11 +322,12 @@ fn promote_candidate(mut self, candidate: Candidate) {
                 }
             }
         };
                 }
             }
         };
-        self.visit_rvalue(&mut rvalue, Location{
+        self.visit_rvalue(&mut rvalue, Location {
             block: BasicBlock::new(0),
             statement_index: usize::MAX
         });
             block: BasicBlock::new(0),
             statement_index: usize::MAX
         });
-        self.assign(Lvalue::ReturnPointer, rvalue, span);
+
+        self.assign(Lvalue::Local(RETURN_POINTER), rvalue, span);
         self.source.promoted.push(self.promoted);
     }
 }
         self.source.promoted.push(self.promoted);
     }
 }
@@ -330,8 +338,10 @@ fn visit_lvalue(&mut self,
                     lvalue: &mut Lvalue<'tcx>,
                     context: LvalueContext<'tcx>,
                     location: Location) {
                     lvalue: &mut Lvalue<'tcx>,
                     context: LvalueContext<'tcx>,
                     location: Location) {
-        if let Lvalue::Temp(ref mut temp) = *lvalue {
-            *temp = self.promote_temp(*temp);
+        if let Lvalue::Local(ref mut temp) = *lvalue {
+            if self.source.local_kind(*temp) == LocalKind::Temp {
+                *temp = self.promote_temp(*temp);
+            }
         }
         self.super_lvalue(lvalue, context, location);
     }
         }
         self.super_lvalue(lvalue, context, location);
     }
@@ -339,7 +349,7 @@ fn visit_lvalue(&mut self,
 
 pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                    mut temps: IndexVec<Temp, TempState>,
+                                    mut temps: IndexVec<Local, TempState>,
                                     candidates: Vec<Candidate>) {
     // Visit candidates in reverse, in case they're nested.
     for candidate in candidates.into_iter().rev() {
                                     candidates: Vec<Candidate>) {
     // Visit candidates in reverse, in case they're nested.
     for candidate in candidates.into_iter().rev() {
@@ -353,7 +363,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
                                   "expected assignment to promote");
                     }
                 };
                                   "expected assignment to promote");
                     }
                 };
-                if let Lvalue::Temp(index) = *dest {
+                if let Lvalue::Local(index) = *dest {
                     if temps[index] == TempState::PromotedOut {
                         // Already promoted.
                         continue;
                     if temps[index] == TempState::PromotedOut {
                         // Already promoted.
                         continue;
@@ -376,8 +386,10 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
             }
         };
 
             }
         };
 
+        // Declare return pointer local
+        let initial_locals = iter::once(LocalDecl::new_return_pointer(ty)).collect();
+
         let mut promoter = Promoter {
         let mut promoter = Promoter {
-            source: mir,
             promoted: Mir::new(
                 IndexVec::new(),
                 Some(VisibilityScopeData {
             promoted: Mir::new(
                 IndexVec::new(),
                 Some(VisibilityScopeData {
@@ -386,12 +398,12 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
                 }).into_iter().collect(),
                 IndexVec::new(),
                 ty,
                 }).into_iter().collect(),
                 IndexVec::new(),
                 ty,
-                IndexVec::new(),
-                IndexVec::new(),
-                IndexVec::new(),
+                initial_locals,
+                0,
                 vec![],
                 span
             ),
                 vec![],
                 span
             ),
+            source: mir,
             temps: &mut temps,
             keep_original: false
         };
             temps: &mut temps,
             keep_original: false
         };
@@ -400,13 +412,13 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
     }
 
     // Eliminate assignments to, and drops of promoted temps.
     }
 
     // Eliminate assignments to, and drops of promoted temps.
-    let promoted = |index: Temp| temps[index] == TempState::PromotedOut;
+    let promoted = |index: Local| temps[index] == TempState::PromotedOut;
     for block in mir.basic_blocks_mut() {
         block.statements.retain(|statement| {
             match statement.kind {
     for block in mir.basic_blocks_mut() {
         block.statements.retain(|statement| {
             match statement.kind {
-                StatementKind::Assign(Lvalue::Temp(index), _) |
-                StatementKind::StorageLive(Lvalue::Temp(index)) |
-                StatementKind::StorageDead(Lvalue::Temp(index)) => {
+                StatementKind::Assign(Lvalue::Local(index), _) |
+                StatementKind::StorageLive(Lvalue::Local(index)) |
+                StatementKind::StorageDead(Lvalue::Local(index)) => {
                     !promoted(index)
                 }
                 _ => true
                     !promoted(index)
                 }
                 _ => true
@@ -414,7 +426,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         });
         let terminator = block.terminator_mut();
         match terminator.kind {
         });
         let terminator = block.terminator_mut();
         match terminator.kind {
-            TerminatorKind::Drop { location: Lvalue::Temp(index), target, .. } => {
+            TerminatorKind::Drop { location: Lvalue::Local(index), target, .. } => {
                 if promoted(index) {
                     terminator.kind = TerminatorKind::Goto {
                         target: target
                 if promoted(index) {
                     terminator.kind = TerminatorKind::Goto {
                         target: target
index 2c03af2c8e97a93d67fa655683e662e0c38afa80..acc3084c906dcfc26d2a7ffc27ba8dfe49f2b07a 100644 (file)
@@ -143,11 +143,11 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     param_env: ty::ParameterEnvironment<'tcx>,
     qualif_map: &'a mut DefIdMap<Qualif>,
     mir_map: Option<&'a MirMap<'tcx>>,
     param_env: ty::ParameterEnvironment<'tcx>,
     qualif_map: &'a mut DefIdMap<Qualif>,
     mir_map: Option<&'a MirMap<'tcx>>,
-    temp_qualif: IndexVec<Temp, Option<Qualif>>,
+    temp_qualif: IndexVec<Local, Option<Qualif>>,
     return_qualif: Option<Qualif>,
     qualif: Qualif,
     const_fn_arg_vars: BitVector,
     return_qualif: Option<Qualif>,
     qualif: Qualif,
     const_fn_arg_vars: BitVector,
-    temp_promotion_state: IndexVec<Temp, TempState>,
+    temp_promotion_state: IndexVec<Local, TempState>,
     promotion_candidates: Vec<Candidate>
 }
 
     promotion_candidates: Vec<Candidate>
 }
 
@@ -173,10 +173,10 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             param_env: param_env,
             qualif_map: qualif_map,
             mir_map: mir_map,
             param_env: param_env,
             qualif_map: qualif_map,
             mir_map: mir_map,
-            temp_qualif: IndexVec::from_elem(None, &mir.temp_decls),
+            temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
             return_qualif: None,
             qualif: Qualif::empty(),
             return_qualif: None,
             qualif: Qualif::empty(),
-            const_fn_arg_vars: BitVector::new(mir.var_decls.len()),
+            const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
@@ -332,8 +332,10 @@ fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) {
 
         // Only handle promotable temps in non-const functions.
         if self.mode == Mode::Fn {
 
         // Only handle promotable temps in non-const functions.
         if self.mode == Mode::Fn {
-            if let Lvalue::Temp(index) = *dest {
-                if self.temp_promotion_state[index].is_promotable() {
+            if let Lvalue::Local(index) = *dest {
+                if self.mir.local_kind(index) == LocalKind::Temp
+                && self.temp_promotion_state[index].is_promotable() {
+                    debug!("store to promotable temp {:?}", index);
                     store(&mut self.temp_qualif[index]);
                 }
             }
                     store(&mut self.temp_qualif[index]);
                 }
             }
@@ -341,13 +343,20 @@ fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) {
         }
 
         match *dest {
         }
 
         match *dest {
-            Lvalue::Temp(index) => store(&mut self.temp_qualif[index]),
-            Lvalue::ReturnPointer => store(&mut self.return_qualif),
+            Lvalue::Local(index) if self.mir.local_kind(index) == LocalKind::Temp => {
+                debug!("store to temp {:?}", index);
+                store(&mut self.temp_qualif[index])
+            }
+            Lvalue::Local(index) if self.mir.local_kind(index) == LocalKind::ReturnPointer => {
+                debug!("store to return pointer {:?}", index);
+                store(&mut self.return_qualif)
+            }
 
             Lvalue::Projection(box Projection {
 
             Lvalue::Projection(box Projection {
-                base: Lvalue::Temp(index),
+                base: Lvalue::Local(index),
                 elem: ProjectionElem::Deref
                 elem: ProjectionElem::Deref
-            }) if self.mir.temp_decls[index].ty.is_unique()
+            }) if self.mir.local_kind(index) == LocalKind::Temp
+               && self.mir.local_decls[index].ty.is_unique()
                && self.temp_qualif[index].map_or(false, |qualif| {
                     qualif.intersects(Qualif::NOT_CONST)
                }) => {
                && self.temp_qualif[index].map_or(false, |qualif| {
                     qualif.intersects(Qualif::NOT_CONST)
                }) => {
@@ -366,6 +375,8 @@ fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) {
 
     /// Qualify a whole const, static initializer or const fn.
     fn qualify_const(&mut self) -> Qualif {
 
     /// Qualify a whole const, static initializer or const fn.
     fn qualify_const(&mut self) -> Qualif {
+        debug!("qualifying {} {}", self.mode, self.tcx.item_path_str(self.def_id));
+
         let mir = self.mir;
 
         let mut seen_blocks = BitVector::new(mir.basic_blocks().len());
         let mir = self.mir;
 
         let mut seen_blocks = BitVector::new(mir.basic_blocks().len());
@@ -399,7 +410,7 @@ fn qualify_const(&mut self) -> Qualif {
                 TerminatorKind::Return => {
                     // Check for unused values. This usually means
                     // there are extra statements in the AST.
                 TerminatorKind::Return => {
                     // Check for unused values. This usually means
                     // there are extra statements in the AST.
-                    for temp in mir.temp_decls.indices() {
+                    for temp in mir.temp_iter() {
                         if self.temp_qualif[temp].is_none() {
                             continue;
                         }
                         if self.temp_qualif[temp].is_none() {
                             continue;
                         }
@@ -424,9 +435,10 @@ fn qualify_const(&mut self) -> Qualif {
 
                     // Make sure there are no extra unassigned variables.
                     self.qualif = Qualif::NOT_CONST;
 
                     // Make sure there are no extra unassigned variables.
                     self.qualif = Qualif::NOT_CONST;
-                    for index in 0..mir.var_decls.len() {
-                        if !self.const_fn_arg_vars.contains(index) {
-                            self.assign(&Lvalue::Var(Var::new(index)), Location {
+                    for index in mir.var_iter() {
+                        if !self.const_fn_arg_vars.contains(index.index()) {
+                            debug!("unassigned variable {:?}", index);
+                            self.assign(&Lvalue::Local(index), Location {
                                 block: bb,
                                 statement_index: usize::MAX,
                             });
                                 block: bb,
                                 statement_index: usize::MAX,
                             });
@@ -480,23 +492,28 @@ fn visit_lvalue(&mut self,
                     context: LvalueContext<'tcx>,
                     location: Location) {
         match *lvalue {
                     context: LvalueContext<'tcx>,
                     location: Location) {
         match *lvalue {
-            Lvalue::Arg(_) => {
-                self.add(Qualif::FN_ARGUMENT);
-            }
-            Lvalue::Var(_) => {
-                self.add(Qualif::NOT_CONST);
-            }
-            Lvalue::Temp(index) => {
-                if !self.temp_promotion_state[index].is_promotable() {
-                    self.add(Qualif::NOT_PROMOTABLE);
+            Lvalue::Local(local) => match self.mir.local_kind(local) {
+                LocalKind::ReturnPointer => {
+                    self.not_const();
+                }
+                LocalKind::Arg => {
+                    self.add(Qualif::FN_ARGUMENT);
+                }
+                LocalKind::Var => {
+                    self.add(Qualif::NOT_CONST);
                 }
                 }
+                LocalKind::Temp => {
+                    if !self.temp_promotion_state[local].is_promotable() {
+                        self.add(Qualif::NOT_PROMOTABLE);
+                    }
 
 
-                if let Some(qualif) = self.temp_qualif[index] {
-                    self.add(qualif);
-                } else {
-                    self.not_const();
+                    if let Some(qualif) = self.temp_qualif[local] {
+                        self.add(qualif);
+                    } else {
+                        self.not_const();
+                    }
                 }
                 }
-            }
+            },
             Lvalue::Static(_) => {
                 self.add(Qualif::STATIC);
                 if self.mode == Mode::Const || self.mode == Mode::ConstFn {
             Lvalue::Static(_) => {
                 self.add(Qualif::STATIC);
                 if self.mode == Mode::Const || self.mode == Mode::ConstFn {
@@ -505,9 +522,6 @@ fn visit_lvalue(&mut self,
                                a constant instead", self.mode);
                 }
             }
                                a constant instead", self.mode);
                 }
             }
-            Lvalue::ReturnPointer => {
-                self.not_const();
-            }
             Lvalue::Projection(ref proj) => {
                 self.nest(|this| {
                     this.super_lvalue(lvalue, context, location);
             Lvalue::Projection(ref proj) => {
                 self.nest(|this| {
                     this.super_lvalue(lvalue, context, location);
@@ -685,8 +699,10 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                 if self.mode == Mode::Fn || self.mode == Mode::ConstFn {
                     if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
                         // We can only promote direct borrows of temps.
                 if self.mode == Mode::Fn || self.mode == Mode::ConstFn {
                     if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
                         // We can only promote direct borrows of temps.
-                        if let Lvalue::Temp(_) = *lvalue {
-                            self.promotion_candidates.push(candidate);
+                        if let Lvalue::Local(local) = *lvalue {
+                            if self.mir.local_kind(local) == LocalKind::Temp {
+                                self.promotion_candidates.push(candidate);
+                            }
                         }
                     }
                 }
                         }
                     }
                 }
@@ -879,17 +895,21 @@ fn visit_assign(&mut self,
         self.visit_rvalue(rvalue, location);
 
         // Check the allowed const fn argument forms.
         self.visit_rvalue(rvalue, location);
 
         // Check the allowed const fn argument forms.
-        if let (Mode::ConstFn, &Lvalue::Var(index)) = (self.mode, dest) {
-            if self.const_fn_arg_vars.insert(index.index()) {
+        if let (Mode::ConstFn, &Lvalue::Local(index)) = (self.mode, dest) {
+            if self.mir.local_kind(index) == LocalKind::Var &&
+               self.const_fn_arg_vars.insert(index.index()) {
+
                 // Direct use of an argument is permitted.
                 // Direct use of an argument is permitted.
-                if let Rvalue::Use(Operand::Consume(Lvalue::Arg(_))) = *rvalue {
-                    return;
+                if let Rvalue::Use(Operand::Consume(Lvalue::Local(local))) = *rvalue {
+                    if self.mir.local_kind(local) == LocalKind::Arg {
+                        return;
+                    }
                 }
 
                 // Avoid a generic error for other uses of arguments.
                 if self.qualif.intersects(Qualif::FN_ARGUMENT) {
                 }
 
                 // Avoid a generic error for other uses of arguments.
                 if self.qualif.intersects(Qualif::FN_ARGUMENT) {
-                    let decl = &self.mir.var_decls[index];
-                    span_err!(self.tcx.sess, decl.source_info.span, E0022,
+                    let decl = &self.mir.local_decls[index];
+                    span_err!(self.tcx.sess, decl.source_info.unwrap().span, E0022,
                               "arguments of constant functions can only \
                                be immutable by-value bindings");
                     return;
                               "arguments of constant functions can only \
                                be immutable by-value bindings");
                     return;
index 7b6a2f5580819c98ddce4ee4265185aeb3ada921..7a6822924295431230d4022c33797d0ab3453d1f 100644 (file)
@@ -90,14 +90,8 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
 
     fn visit_mir(&mut self, mir: &Mir<'tcx>) {
         self.sanitize_type(&"return type", mir.return_ty);
 
     fn visit_mir(&mut self, mir: &Mir<'tcx>) {
         self.sanitize_type(&"return type", mir.return_ty);
-        for var_decl in &mir.var_decls {
-            self.sanitize_type(var_decl, var_decl.ty);
-        }
-        for (n, arg_decl) in mir.arg_decls.iter().enumerate() {
-            self.sanitize_type(&(n, arg_decl), arg_decl.ty);
-        }
-        for (n, tmp_decl) in mir.temp_decls.iter().enumerate() {
-            self.sanitize_type(&(n, tmp_decl), tmp_decl.ty);
+        for local_decl in &mir.local_decls {
+            self.sanitize_type(local_decl, local_decl.ty);
         }
         if self.errors_reported {
             return;
         }
         if self.errors_reported {
             return;
@@ -131,14 +125,9 @@ fn sanitize_type(&mut self, parent: &fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
     fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>, location: Location) -> LvalueTy<'tcx> {
         debug!("sanitize_lvalue: {:?}", lvalue);
         match *lvalue {
     fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>, location: Location) -> LvalueTy<'tcx> {
         debug!("sanitize_lvalue: {:?}", lvalue);
         match *lvalue {
-            Lvalue::Var(index) => LvalueTy::Ty { ty: self.mir.var_decls[index].ty },
-            Lvalue::Temp(index) => LvalueTy::Ty { ty: self.mir.temp_decls[index].ty },
-            Lvalue::Arg(index) => LvalueTy::Ty { ty: self.mir.arg_decls[index].ty },
+            Lvalue::Local(index) => LvalueTy::Ty { ty: self.mir.local_decls[index].ty },
             Lvalue::Static(def_id) =>
                 LvalueTy::Ty { ty: self.tcx().lookup_item_type(def_id).ty },
             Lvalue::Static(def_id) =>
                 LvalueTy::Ty { ty: self.tcx().lookup_item_type(def_id).ty },
-            Lvalue::ReturnPointer => {
-                LvalueTy::Ty { ty: self.mir.return_ty }
-            }
             Lvalue::Projection(ref proj) => {
                 let base_ty = self.sanitize_lvalue(&proj.base, location);
                 if let LvalueTy::Ty { ty } = base_ty {
             Lvalue::Projection(ref proj) => {
                 let base_ty = self.sanitize_lvalue(&proj.base, location);
                 if let LvalueTy::Ty { ty } = base_ty {
@@ -380,9 +369,9 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>) {
             StatementKind::StorageLive(ref lv) |
             StatementKind::StorageDead(ref lv) => {
                 match *lv {
             StatementKind::StorageLive(ref lv) |
             StatementKind::StorageDead(ref lv) => {
                 match *lv {
-                    Lvalue::Temp(_) | Lvalue::Var(_) => {}
+                    Lvalue::Local(_) => {}
                     _ => {
                     _ => {
-                        span_mirbug!(self, stmt, "bad lvalue: expected temp or var");
+                        span_mirbug!(self, stmt, "bad lvalue: expected local");
                     }
                 }
             }
                     }
                 }
             }
@@ -711,6 +700,8 @@ pub fn new() -> Self {
 impl<'tcx> MirPass<'tcx> for TypeckMir {
     fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     src: MirSource, mir: &mut Mir<'tcx>) {
 impl<'tcx> MirPass<'tcx> for TypeckMir {
     fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     src: MirSource, mir: &mut Mir<'tcx>) {
+        debug!("run_pass: {}", tcx.node_path_str(src.item_id()));
+
         if tcx.sess.err_count() > 0 {
             // compiling a broken program can obviously result in a
             // broken MIR, so try not to report duplicate errors.
         if tcx.sess.err_count() > 0 {
             // compiling a broken program can obviously result in a
             // broken MIR, so try not to report duplicate errors.
index 21716d55ac6fa33c67d950d467f4d49deae26574..f453b27f9b97a87bbf0b34e105c1038cff2a0b7a 100644 (file)
@@ -63,8 +63,9 @@ pub fn create_mir_scopes(fcx: &FunctionContext) -> IndexVec<VisibilityScope, Mir
 
     // Find all the scopes with variables defined in them.
     let mut has_variables = BitVector::new(mir.visibility_scopes.len());
 
     // Find all the scopes with variables defined in them.
     let mut has_variables = BitVector::new(mir.visibility_scopes.len());
-    for var in &mir.var_decls {
-        has_variables.insert(var.source_info.scope.index());
+    for var in mir.var_iter() {
+        let decl = &mir.local_decls[var];
+        has_variables.insert(decl.source_info.unwrap().scope.index());
     }
 
     // Instantiate all scopes.
     }
 
     // Instantiate all scopes.
index 5de59b9f6bded47cb54591fbbfb25195b4a5b1a5..455cf4eb455162c10f5a637de44a846157fdfdb8 100644 (file)
@@ -20,7 +20,6 @@
 use rustc::mir::traversal;
 use common::{self, Block, BlockAndBuilder};
 use glue;
 use rustc::mir::traversal;
 use common::{self, Block, BlockAndBuilder};
 use glue;
-use std::iter;
 use super::rvalue;
 
 pub fn lvalue_locals<'bcx, 'tcx>(bcx: Block<'bcx,'tcx>,
 use super::rvalue;
 
 pub fn lvalue_locals<'bcx, 'tcx>(bcx: Block<'bcx,'tcx>,
@@ -30,11 +29,7 @@ pub fn lvalue_locals<'bcx, 'tcx>(bcx: Block<'bcx,'tcx>,
 
     analyzer.visit_mir(mir);
 
 
     analyzer.visit_mir(mir);
 
-    let local_types = mir.arg_decls.iter().map(|a| a.ty)
-               .chain(mir.var_decls.iter().map(|v| v.ty))
-               .chain(mir.temp_decls.iter().map(|t| t.ty))
-               .chain(iter::once(mir.return_ty));
-    for (index, ty) in local_types.enumerate() {
+    for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() {
         let ty = bcx.monomorphize(&ty);
         debug!("local {} has type {:?}", index, ty);
         if ty.is_scalar() ||
         let ty = bcx.monomorphize(&ty);
         debug!("local {} has type {:?}", index, ty);
         if ty.is_scalar() ||
@@ -80,12 +75,11 @@ impl<'mir, 'bcx, 'tcx> LocalAnalyzer<'mir, 'bcx, 'tcx> {
     fn new(mir: &'mir mir::Mir<'tcx>,
            bcx: &'mir BlockAndBuilder<'bcx, 'tcx>)
            -> LocalAnalyzer<'mir, 'bcx, 'tcx> {
     fn new(mir: &'mir mir::Mir<'tcx>,
            bcx: &'mir BlockAndBuilder<'bcx, 'tcx>)
            -> LocalAnalyzer<'mir, 'bcx, 'tcx> {
-        let local_count = mir.count_locals();
         LocalAnalyzer {
             mir: mir,
             bcx: bcx,
         LocalAnalyzer {
             mir: mir,
             bcx: bcx,
-            lvalue_locals: BitVector::new(local_count),
-            seen_assigned: BitVector::new(local_count)
+            lvalue_locals: BitVector::new(mir.local_decls.len()),
+            seen_assigned: BitVector::new(mir.local_decls.len())
         }
     }
 
         }
     }
 
@@ -109,7 +103,7 @@ fn visit_assign(&mut self,
                     location: Location) {
         debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue);
 
                     location: Location) {
         debug!("visit_assign(block={:?}, lvalue={:?}, rvalue={:?})", block, lvalue, rvalue);
 
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             self.mark_assigned(index);
             if !rvalue::rvalue_creates_operand(self.mir, self.bcx, rvalue) {
                 self.mark_as_lvalue(index);
             self.mark_assigned(index);
             if !rvalue::rvalue_creates_operand(self.mir, self.bcx, rvalue) {
                 self.mark_as_lvalue(index);
@@ -153,7 +147,7 @@ fn visit_lvalue(&mut self,
 
         // Allow uses of projections of immediate pair fields.
         if let mir::Lvalue::Projection(ref proj) = *lvalue {
 
         // Allow uses of projections of immediate pair fields.
         if let mir::Lvalue::Projection(ref proj) = *lvalue {
-            if self.mir.local_index(&proj.base).is_some() {
+            if let mir::Lvalue::Local(_) = proj.base {
                 let ty = proj.base.ty(self.mir, self.bcx.tcx());
 
                 let ty = self.bcx.monomorphize(&ty.to_ty(self.bcx.tcx()));
                 let ty = proj.base.ty(self.mir, self.bcx.tcx());
 
                 let ty = self.bcx.monomorphize(&ty.to_ty(self.bcx.tcx()));
@@ -167,7 +161,7 @@ fn visit_lvalue(&mut self,
             }
         }
 
             }
         }
 
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             match context {
                 LvalueContext::Call => {
                     self.mark_assigned(index);
             match context {
                 LvalueContext::Call => {
                     self.mark_assigned(index);
index 003830123ff3b9c7f136ea0c854025bc3bce6350..9e2d947c5e56342647bdeaaa9053275f07b65e45 100644 (file)
@@ -192,8 +192,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                 }
 
                 let llval = if let Some(cast_ty) = ret.cast {
                 }
 
                 let llval = if let Some(cast_ty) = ret.cast {
-                    let index = mir.local_index(&mir::Lvalue::ReturnPointer).unwrap();
-                    let op = match self.locals[index] {
+                    let op = match self.locals[mir::RETURN_POINTER] {
                         LocalRef::Operand(Some(op)) => op,
                         LocalRef::Operand(None) => bug!("use of return before def"),
                         LocalRef::Lvalue(tr_lvalue) => {
                         LocalRef::Operand(Some(op)) => op,
                         LocalRef::Operand(None) => bug!("use of return before def"),
                         LocalRef::Lvalue(tr_lvalue) => {
@@ -218,7 +217,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                     }
                     load
                 } else {
                     }
                     load
                 } else {
-                    let op = self.trans_consume(&bcx, &mir::Lvalue::ReturnPointer);
+                    let op = self.trans_consume(&bcx, &mir::Lvalue::Local(mir::RETURN_POINTER));
                     op.pack_if_pair(&bcx).immediate()
                 };
                 bcx.ret(llval);
                     op.pack_if_pair(&bcx).immediate()
                 };
                 bcx.ret(llval);
@@ -844,7 +843,7 @@ fn make_return_dest(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
         if fn_ret_ty.is_ignore() {
             return ReturnDest::Nothing;
         }
         if fn_ret_ty.is_ignore() {
             return ReturnDest::Nothing;
         }
-        let dest = if let Some(index) = self.mir.local_index(dest) {
+        let dest = if let mir::Lvalue::Local(index) = *dest {
             let ret_ty = self.monomorphized_lvalue_ty(dest);
             match self.locals[index] {
                 LocalRef::Lvalue(dest) => dest,
             let ret_ty = self.monomorphized_lvalue_ty(dest);
             match self.locals[index] {
                 LocalRef::Lvalue(dest) => dest,
index b74d56ce368a9cb64eddc86559f0c5fd721dc76b..b68a9a962c71077a3901ab5004c9f823cf9ee5e2 100644 (file)
@@ -221,16 +221,17 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
     fn new(ccx: &'a CrateContext<'a, 'tcx>,
            mir: &'a mir::Mir<'tcx>,
            substs: &'tcx Substs<'tcx>,
     fn new(ccx: &'a CrateContext<'a, 'tcx>,
            mir: &'a mir::Mir<'tcx>,
            substs: &'tcx Substs<'tcx>,
-           args: IndexVec<mir::Arg, Const<'tcx>>)
+           args: IndexVec<mir::Local, Const<'tcx>>)
            -> MirConstContext<'a, 'tcx> {
         let mut context = MirConstContext {
             ccx: ccx,
             mir: mir,
             substs: substs,
            -> MirConstContext<'a, 'tcx> {
         let mut context = MirConstContext {
             ccx: ccx,
             mir: mir,
             substs: substs,
-            locals: (0..mir.count_locals()).map(|_| None).collect(),
+            locals: (0..mir.local_decls.len()).map(|_| None).collect(),
         };
         for (i, arg) in args.into_iter().enumerate() {
         };
         for (i, arg) in args.into_iter().enumerate() {
-            let index = mir.local_index(&mir::Lvalue::Arg(mir::Arg::new(i))).unwrap();
+            // Locals after local0 are the function arguments
+            let index = mir::Local::new(i + 1);
             context.locals[index] = Some(arg);
         }
         context
             context.locals[index] = Some(arg);
         }
         context
@@ -238,7 +239,7 @@ fn new(ccx: &'a CrateContext<'a, 'tcx>,
 
     fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
                  mut instance: Instance<'tcx>,
 
     fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
                  mut instance: Instance<'tcx>,
-                 args: IndexVec<mir::Arg, Const<'tcx>>)
+                 args: IndexVec<mir::Local, Const<'tcx>>)
                  -> Result<Const<'tcx>, ConstEvalErr> {
         // Try to resolve associated constants.
         if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) {
                  -> Result<Const<'tcx>, ConstEvalErr> {
         // Try to resolve associated constants.
         if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) {
@@ -311,8 +312,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr> {
                 mir::TerminatorKind::Goto { target } => target,
                 mir::TerminatorKind::Return => {
                     failure?;
                 mir::TerminatorKind::Goto { target } => target,
                 mir::TerminatorKind::Return => {
                     failure?;
-                    let index = self.mir.local_index(&mir::Lvalue::ReturnPointer).unwrap();
-                    return Ok(self.locals[index].unwrap_or_else(|| {
+                    return Ok(self.locals[mir::RETURN_POINTER].unwrap_or_else(|| {
                         span_bug!(span, "no returned value in constant");
                     }));
                 }
                         span_bug!(span, "no returned value in constant");
                     }));
                 }
@@ -376,7 +376,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr> {
     }
 
     fn store(&mut self, dest: &mir::Lvalue<'tcx>, value: Const<'tcx>, span: Span) {
     }
 
     fn store(&mut self, dest: &mir::Lvalue<'tcx>, value: Const<'tcx>, span: Span) {
-        if let Some(index) = self.mir.local_index(dest) {
+        if let mir::Lvalue::Local(index) = *dest {
             self.locals[index] = Some(value);
         } else {
             span_bug!(span, "assignment to {:?} in constant", dest);
             self.locals[index] = Some(value);
         } else {
             span_bug!(span, "assignment to {:?} in constant", dest);
@@ -387,17 +387,14 @@ fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span)
                     -> Result<ConstLvalue<'tcx>, ConstEvalErr> {
         let tcx = self.ccx.tcx();
 
                     -> Result<ConstLvalue<'tcx>, ConstEvalErr> {
         let tcx = self.ccx.tcx();
 
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             return Ok(self.locals[index].unwrap_or_else(|| {
                 span_bug!(span, "{:?} not initialized", lvalue)
             }).as_lvalue());
         }
 
         let lvalue = match *lvalue {
             return Ok(self.locals[index].unwrap_or_else(|| {
                 span_bug!(span, "{:?} not initialized", lvalue)
             }).as_lvalue());
         }
 
         let lvalue = match *lvalue {
-            mir::Lvalue::Var(_) |
-            mir::Lvalue::Temp(_) |
-            mir::Lvalue::Arg(_) |
-            mir::Lvalue::ReturnPointer => bug!(), // handled above
+            mir::Lvalue::Local(_)  => bug!(), // handled above
             mir::Lvalue::Static(def_id) => {
                 ConstLvalue {
                     base: Base::Static(consts::get_static(self.ccx, def_id)),
             mir::Lvalue::Static(def_id) => {
                 ConstLvalue {
                     base: Base::Static(consts::get_static(self.ccx, def_id)),
index 0ce5544c3bfc5b50bb650226e1f7601e32d23edb..7102bd81caf36e3d5243ab5a3014d11aa1650f6c 100644 (file)
@@ -91,7 +91,7 @@ pub fn trans_lvalue(&mut self,
         let ccx = bcx.ccx();
         let tcx = bcx.tcx();
 
         let ccx = bcx.ccx();
         let tcx = bcx.tcx();
 
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             match self.locals[index] {
                 LocalRef::Lvalue(lvalue) => {
                     return lvalue;
             match self.locals[index] {
                 LocalRef::Lvalue(lvalue) => {
                     return lvalue;
@@ -103,10 +103,7 @@ pub fn trans_lvalue(&mut self,
         }
 
         let result = match *lvalue {
         }
 
         let result = match *lvalue {
-            mir::Lvalue::Var(_) |
-            mir::Lvalue::Temp(_) |
-            mir::Lvalue::Arg(_) |
-            mir::Lvalue::ReturnPointer => bug!(), // handled above
+            mir::Lvalue::Local(_) => bug!(), // handled above
             mir::Lvalue::Static(def_id) => {
                 let const_ty = self.monomorphized_lvalue_ty(lvalue);
                 LvalueRef::new_sized(consts::get_static(ccx, def_id),
             mir::Lvalue::Static(def_id) => {
                 let const_ty = self.monomorphized_lvalue_ty(lvalue);
                 LvalueRef::new_sized(consts::get_static(ccx, def_id),
@@ -235,7 +232,7 @@ pub fn with_lvalue_ref<F, U>(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
                                  lvalue: &mir::Lvalue<'tcx>, f: F) -> U
     where F: FnOnce(&mut Self, LvalueRef<'tcx>) -> U
     {
                                  lvalue: &mir::Lvalue<'tcx>, f: F) -> U
     where F: FnOnce(&mut Self, LvalueRef<'tcx>) -> U
     {
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             match self.locals[index] {
                 LocalRef::Lvalue(lvalue) => f(self, lvalue),
                 LocalRef::Operand(None) => {
             match self.locals[index] {
                 LocalRef::Lvalue(lvalue) => f(self, lvalue),
                 LocalRef::Operand(None) => {
index efbab3a3b4dcec65d57787e360ea1596b29c6822..699900dc4cbac8d99eaa0785def660af038edd84 100644 (file)
@@ -237,51 +237,61 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
     // Allocate variable and temp allocas
     mircx.locals = {
         let args = arg_local_refs(&bcx, &mir, &mircx.scopes, &lvalue_locals);
     // Allocate variable and temp allocas
     mircx.locals = {
         let args = arg_local_refs(&bcx, &mir, &mircx.scopes, &lvalue_locals);
-        let vars = mir.var_decls.iter().enumerate().map(|(i, decl)| {
+
+        let mut allocate_local = |local| {
+            let decl = &mir.local_decls[local];
             let ty = bcx.monomorphize(&decl.ty);
             let ty = bcx.monomorphize(&decl.ty);
-            let debug_scope = mircx.scopes[decl.source_info.scope];
-            let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
 
 
-            let local = mir.local_index(&mir::Lvalue::Var(mir::Var::new(i))).unwrap();
-            if !lvalue_locals.contains(local.index()) && !dbg {
-                return LocalRef::new_operand(bcx.ccx(), ty);
-            }
+            if let Some(name) = decl.name {
+                // User variable
+                let source_info = decl.source_info.unwrap();
+                let debug_scope = mircx.scopes[source_info.scope];
+                let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo;
 
 
-            let lvalue = LvalueRef::alloca(&bcx, ty, &decl.name.as_str());
-            if dbg {
-                let dbg_loc = mircx.debug_loc(decl.source_info);
-                if let DebugLoc::ScopeAt(scope, span) = dbg_loc {
-                    bcx.with_block(|bcx| {
-                        declare_local(bcx, decl.name, ty, scope,
-                                    VariableAccess::DirectVariable { alloca: lvalue.llval },
-                                    VariableKind::LocalVariable, span);
-                    });
-                } else {
-                    panic!("Unexpected");
+                if !lvalue_locals.contains(local.index()) && !dbg {
+                    debug!("alloc: {:?} ({}) -> operand", local, name);
+                    return LocalRef::new_operand(bcx.ccx(), ty);
                 }
                 }
-            }
-            LocalRef::Lvalue(lvalue)
-        });
-
-        let locals = mir.temp_decls.iter().enumerate().map(|(i, decl)| {
-            (mir::Lvalue::Temp(mir::Temp::new(i)), decl.ty)
-        }).chain(iter::once((mir::Lvalue::ReturnPointer, mir.return_ty)));
-
-        args.into_iter().chain(vars).chain(locals.map(|(lvalue, ty)| {
-            let ty = bcx.monomorphize(&ty);
-            let local = mir.local_index(&lvalue).unwrap();
-            if lvalue == mir::Lvalue::ReturnPointer && fcx.fn_ty.ret.is_indirect() {
-                let llretptr = llvm::get_param(fcx.llfn, 0);
-                LocalRef::Lvalue(LvalueRef::new_sized(llretptr, LvalueTy::from_ty(ty)))
-            } else if lvalue_locals.contains(local.index()) {
-                LocalRef::Lvalue(LvalueRef::alloca(&bcx, ty, &format!("{:?}", lvalue)))
+
+                debug!("alloc: {:?} ({}) -> lvalue", local, name);
+                let lvalue = LvalueRef::alloca(&bcx, ty, &name.as_str());
+                if dbg {
+                    let dbg_loc = mircx.debug_loc(source_info);
+                    if let DebugLoc::ScopeAt(scope, span) = dbg_loc {
+                        bcx.with_block(|bcx| {
+                            declare_local(bcx, name, ty, scope,
+                                        VariableAccess::DirectVariable { alloca: lvalue.llval },
+                                        VariableKind::LocalVariable, span);
+                        });
+                    } else {
+                        panic!("Unexpected");
+                    }
+                }
+                LocalRef::Lvalue(lvalue)
             } else {
             } else {
-                // If this is an immediate local, we do not create an
-                // alloca in advance. Instead we wait until we see the
-                // definition and update the operand there.
-                LocalRef::new_operand(bcx.ccx(), ty)
+                // Temporary or return pointer
+                if local == mir::RETURN_POINTER && fcx.fn_ty.ret.is_indirect() {
+                    debug!("alloc: {:?} (return pointer) -> lvalue", local);
+                    let llretptr = llvm::get_param(fcx.llfn, 0);
+                    LocalRef::Lvalue(LvalueRef::new_sized(llretptr, LvalueTy::from_ty(ty)))
+                } else if lvalue_locals.contains(local.index()) {
+                    debug!("alloc: {:?} -> lvalue", local);
+                    LocalRef::Lvalue(LvalueRef::alloca(&bcx, ty, &format!("{:?}", local)))
+                } else {
+                    // If this is an immediate local, we do not create an
+                    // alloca in advance. Instead we wait until we see the
+                    // definition and update the operand there.
+                    debug!("alloc: {:?} -> operand", local);
+                    LocalRef::new_operand(bcx.ccx(), ty)
+                }
             }
             }
-        })).collect()
+        };
+
+        let retptr = allocate_local(mir::RETURN_POINTER);
+        iter::once(retptr)
+            .chain(args.into_iter())
+            .chain(mir.var_and_temp_iter().map(&mut allocate_local))
+            .collect()
     };
 
     // Branch to the START block
     };
 
     // Branch to the START block
@@ -346,10 +356,10 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
         None
     };
 
         None
     };
 
-    mir.arg_decls.iter().enumerate().map(|(arg_index, arg_decl)| {
+    mir.arg_iter().enumerate().map(|(arg_index, local)| {
+        let arg_decl = &mir.local_decls[local];
         let arg_ty = bcx.monomorphize(&arg_decl.ty);
         let arg_ty = bcx.monomorphize(&arg_decl.ty);
-        let local = mir.local_index(&mir::Lvalue::Arg(mir::Arg::new(arg_index))).unwrap();
-        if mir.spread_last_arg && arg_index == mir.arg_decls.len() - 1 {
+        if mir.spread_last_arg && arg_index == mir.arg_count - 1 {
             // This argument (e.g. the last argument in the "rust-call" ABI)
             // is a tuple that was spread at the ABI level and now we have
             // to reconstruct it into a tuple local variable, from multiple
             // This argument (e.g. the last argument in the "rust-call" ABI)
             // is a tuple that was spread at the ABI level and now we have
             // to reconstruct it into a tuple local variable, from multiple
@@ -467,8 +477,8 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
         bcx.with_block(|bcx| arg_scope.map(|scope| {
             // Is this a regular argument?
             if arg_index > 0 || mir.upvar_decls.is_empty() {
         bcx.with_block(|bcx| arg_scope.map(|scope| {
             // Is this a regular argument?
             if arg_index > 0 || mir.upvar_decls.is_empty() {
-                declare_local(bcx, arg_decl.debug_name, arg_ty, scope,
-                              VariableAccess::DirectVariable { alloca: llval },
+                declare_local(bcx, arg_decl.name.unwrap_or(keywords::Invalid.name()), arg_ty,
+                              scope, VariableAccess::DirectVariable { alloca: llval },
                               VariableKind::ArgumentVariable(arg_index + 1),
                               bcx.fcx().span.unwrap_or(DUMMY_SP));
                 return;
                               VariableKind::ArgumentVariable(arg_index + 1),
                               bcx.fcx().span.unwrap_or(DUMMY_SP));
                 return;
index 270033be9375c20029f763de31b8da3816bc930d..4f1ec40398ca97659d1bbcf2881a199981c82dcc 100644 (file)
@@ -175,7 +175,7 @@ pub fn trans_consume(&mut self,
 
         // watch out for locals that do not have an
         // alloca; they are handled somewhat differently
 
         // watch out for locals that do not have an
         // alloca; they are handled somewhat differently
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             match self.locals[index] {
                 LocalRef::Operand(Some(o)) => {
                     return o;
             match self.locals[index] {
                 LocalRef::Operand(Some(o)) => {
                     return o;
@@ -191,7 +191,7 @@ pub fn trans_consume(&mut self,
 
         // Moves out of pair fields are trivial.
         if let &mir::Lvalue::Projection(ref proj) = lvalue {
 
         // Moves out of pair fields are trivial.
         if let &mir::Lvalue::Projection(ref proj) = lvalue {
-            if let Some(index) = self.mir.local_index(&proj.base) {
+            if let mir::Lvalue::Local(index) = proj.base {
                 if let LocalRef::Operand(Some(o)) = self.locals[index] {
                     match (o.val, &proj.elem) {
                         (OperandValue::Pair(a, b),
                 if let LocalRef::Operand(Some(o)) = self.locals[index] {
                     match (o.val, &proj.elem) {
                         (OperandValue::Pair(a, b),
index 9943acbc88e6d2365857e89ac7300483816ebb28..3d6aad37ed571fd16a3960efdf17aafb66b46473 100644 (file)
@@ -30,7 +30,7 @@ pub fn trans_statement(&mut self,
         debug_loc.apply(bcx.fcx());
         match statement.kind {
             mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
         debug_loc.apply(bcx.fcx());
         match statement.kind {
             mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
-                if let Some(index) = self.mir.local_index(lvalue) {
+                if let mir::Lvalue::Local(index) = *lvalue {
                     match self.locals[index] {
                         LocalRef::Lvalue(tr_dest) => {
                             self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc)
                     match self.locals[index] {
                         LocalRef::Lvalue(tr_dest) => {
                             self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc)
@@ -86,7 +86,7 @@ fn trans_storage_liveness(&self,
                               lvalue: &mir::Lvalue<'tcx>,
                               intrinsic: base::Lifetime)
                               -> BlockAndBuilder<'bcx, 'tcx> {
                               lvalue: &mir::Lvalue<'tcx>,
                               intrinsic: base::Lifetime)
                               -> BlockAndBuilder<'bcx, 'tcx> {
-        if let Some(index) = self.mir.local_index(lvalue) {
+        if let mir::Lvalue::Local(index) = *lvalue {
             if let LocalRef::Lvalue(tr_lval) = self.locals[index] {
                 intrinsic.call(&bcx, tr_lval.llval);
             }
             if let LocalRef::Lvalue(tr_lval) = self.locals[index] {
                 intrinsic.call(&bcx, tr_lval.llval);
             }
index e57a9674cf683d4be0421655c911bd7928076eb1..66c3dfbf48cf36dd6713dc0ba1c41c1d23874a7b 100644 (file)
@@ -23,19 +23,19 @@ fn main() {}
 // END RUST SOURCE
 // START rustc.node13.Deaggregator.before.mir
 // bb0: {
 // END RUST SOURCE
 // START rustc.node13.Deaggregator.before.mir
 // bb0: {
-//     var0 = arg0;                     // scope 0 at main.rs:8:8: 8:9
-//     tmp0 = var0;                     // scope 1 at main.rs:9:14: 9:15
-//     return = Baz { x: tmp0, y: const F32(0), z: const false }; // scope ...
+//     local2 = local1;                     // scope 0 at main.rs:8:8: 8:9
+//     local3 = local2;                     // scope 1 at main.rs:9:14: 9:15
+//     local0 = Baz { x: local3, y: const F32(0), z: const false }; // scope ...
 //     goto -> bb1;                     // scope 1 at main.rs:8:1: 10:2
 // }
 // END rustc.node13.Deaggregator.before.mir
 // START rustc.node13.Deaggregator.after.mir
 // bb0: {
 //     goto -> bb1;                     // scope 1 at main.rs:8:1: 10:2
 // }
 // END rustc.node13.Deaggregator.before.mir
 // START rustc.node13.Deaggregator.after.mir
 // bb0: {
-//     var0 = arg0;                     // scope 0 at main.rs:8:8: 8:9
-//     tmp0 = var0;                     // scope 1 at main.rs:9:14: 9:15
-//     (return.0: usize) = tmp0;        // scope 1 at main.rs:9:5: 9:34
-//     (return.1: f32) = const F32(0);  // scope 1 at main.rs:9:5: 9:34
-//     (return.2: bool) = const false;  // scope 1 at main.rs:9:5: 9:34
+//     local2 = local1;                     // scope 0 at main.rs:8:8: 8:9
+//     local3 = local2;                     // scope 1 at main.rs:9:14: 9:15
+//     (local0.0: usize) = local3;        // scope 1 at main.rs:9:5: 9:34
+//     (local0.1: f32) = const F32(0);  // scope 1 at main.rs:9:5: 9:34
+//     (local0.2: bool) = const false;  // scope 1 at main.rs:9:5: 9:34
 //     goto -> bb1;                     // scope 1 at main.rs:8:1: 10:2
 // }
 //     goto -> bb1;                     // scope 1 at main.rs:8:1: 10:2
 // }
-// END rustc.node13.Deaggregator.after.mir
\ No newline at end of file
+// END rustc.node13.Deaggregator.after.mir
index ccfa760a28c76823905845e7524ec023c191a833..5d182f367b5fdd381f5a6d0f7abf0e570a2de924 100644 (file)
@@ -28,18 +28,18 @@ fn main() {
 // END RUST SOURCE
 // START rustc.node10.Deaggregator.before.mir
 // bb0: {
 // END RUST SOURCE
 // START rustc.node10.Deaggregator.before.mir
 // bb0: {
-//     var0 = arg0;                     // scope 0 at main.rs:7:8: 7:9
-//     tmp0 = var0;                     // scope 1 at main.rs:8:19: 8:20
-//     return = Baz::Foo { x: tmp0 };   // scope 1 at main.rs:8:5: 8:21
+//     local2 = local1;                     // scope 0 at main.rs:7:8: 7:9
+//     local3 = local2;                     // scope 1 at main.rs:8:19: 8:20
+//     local0 = Baz::Foo { x: local3 };   // scope 1 at main.rs:8:5: 8:21
 //     goto -> bb1;                     // scope 1 at main.rs:7:1: 9:2
 // }
 // END rustc.node10.Deaggregator.before.mir
 // START rustc.node10.Deaggregator.after.mir
 // bb0: {
 //     goto -> bb1;                     // scope 1 at main.rs:7:1: 9:2
 // }
 // END rustc.node10.Deaggregator.before.mir
 // START rustc.node10.Deaggregator.after.mir
 // bb0: {
-//     var0 = arg0;                     // scope 0 at main.rs:7:8: 7:9
-//     tmp0 = var0;                     // scope 1 at main.rs:8:19: 8:20
-//     ((return as Foo).0: usize) = tmp0; // scope 1 at main.rs:8:5: 8:21
-//     discriminant(return) = 1;         // scope 1 at main.rs:8:5: 8:21
+//     local2 = local1;                     // scope 0 at main.rs:7:8: 7:9
+//     local3 = local2;                     // scope 1 at main.rs:8:19: 8:20
+//     ((local0 as Foo).0: usize) = local3; // scope 1 at main.rs:8:5: 8:21
+//     discriminant(local0) = 1;         // scope 1 at main.rs:8:5: 8:21
 //     goto -> bb1;                     // scope 1 at main.rs:7:1: 9:2
 // }
 //     goto -> bb1;                     // scope 1 at main.rs:7:1: 9:2
 // }
-// END rustc.node10.Deaggregator.after.mir
\ No newline at end of file
+// END rustc.node10.Deaggregator.after.mir
index 4ed0c8bc9ffa4184fb9da7e22c0ecab48a24c1c5..e2dd1bc3795ab050d961e3925ebeb75d64d5ce1b 100644 (file)
@@ -18,27 +18,28 @@ fn main() {
     let c = 1;
 }
 
     let c = 1;
 }
 
+// TODO The StorageDead for local1 (a) after local6's (c) is missing!
+
 // END RUST SOURCE
 // START rustc.node4.TypeckMir.before.mir
 //     bb0: {
 // END RUST SOURCE
 // START rustc.node4.TypeckMir.before.mir
 //     bb0: {
-//         StorageLive(var0);               // scope 0 at storage_ranges.rs:14:9: 14:10
-//         var0 = const 0i32;               // scope 0 at storage_ranges.rs:14:13: 14:14
-//         StorageLive(var1);               // scope 1 at storage_ranges.rs:16:13: 16:14
-//         StorageLive(tmp1);               // scope 1 at storage_ranges.rs:16:18: 16:25
-//         StorageLive(tmp2);               // scope 1 at storage_ranges.rs:16:23: 16:24
-//         tmp2 = var0;                     // scope 1 at storage_ranges.rs:16:23: 16:24
-//         tmp1 = std::option::Option<i32>::Some(tmp2,); // scope 1 at storage_ranges.rs:16:18: 16:25
-//         var1 = &tmp1;                    // scope 1 at storage_ranges.rs:16:17: 16:25
-//         StorageDead(tmp2);               // scope 1 at storage_ranges.rs:16:23: 16:24
-//         tmp0 = ();                       // scope 2 at storage_ranges.rs:15:5: 17:6
-//         StorageDead(tmp1);               // scope 1 at storage_ranges.rs:16:18: 16:25
-//         StorageDead(var1);               // scope 1 at storage_ranges.rs:16:13: 16:14
-//         StorageLive(var2);               // scope 1 at storage_ranges.rs:18:9: 18:10
-//         var2 = const 1i32;               // scope 1 at storage_ranges.rs:18:13: 18:14
-//         return = ();                     // scope 3 at storage_ranges.rs:13:11: 19:2
-//         StorageDead(var2);               // scope 1 at storage_ranges.rs:18:9: 18:10
-//         StorageDead(var0);               // scope 0 at storage_ranges.rs:14:9: 14:10
-//         goto -> bb1;                     // scope 0 at storage_ranges.rs:13:1: 19:2
+//         StorageLive(local1);             // scope 0 at storage_ranges.rs:12:9: 12:10
+//         local1 = const 0i32;             // scope 0 at storage_ranges.rs:12:13: 12:14
+//         StorageLive(local3);             // scope 1 at storage_ranges.rs:14:13: 14:14
+//         StorageLive(local4);             // scope 1 at storage_ranges.rs:14:18: 14:25
+//         StorageLive(local5);             // scope 1 at storage_ranges.rs:14:23: 14:24
+//         local5 = local1;                 // scope 1 at storage_ranges.rs:14:23: 14:24
+//         local4 = std::option::Option<i32>::Some(local5,); // scope 1 at storage_ranges.rs:14:18: 14:25
+//         local3 = &local4;                // scope 1 at storage_ranges.rs:14:17: 14:25
+//         StorageDead(local5);             // scope 1 at storage_ranges.rs:14:23: 14:24
+//         local2 = ();                     // scope 2 at storage_ranges.rs:13:5: 15:6
+//         StorageDead(local4);             // scope 1 at storage_ranges.rs:14:18: 14:25
+//         StorageDead(local3);             // scope 1 at storage_ranges.rs:14:13: 14:14
+//         StorageLive(local6);             // scope 1 at storage_ranges.rs:16:9: 16:10
+//         local6 = const 1i32;             // scope 1 at storage_ranges.rs:16:13: 16:14
+//         local0 = ();                     // scope 3 at storage_ranges.rs:11:11: 17:2
+//         StorageDead(local6);             // scope 1 at storage_ranges.rs:16:9: 16:10
+//         goto -> bb1;                     // scope 0 at storage_ranges.rs:11:1: 17:2
 //     }
 //
 //     bb1: {
 //     }
 //
 //     bb1: {