]> 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
-    /// 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>,
 
-    /// 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.
@@ -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>,
-               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
     {
+        // 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,
-            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,
@@ -161,56 +166,63 @@ pub fn dominators(&self) -> Dominators<BasicBlock> {
         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
@@ -308,49 +320,76 @@ pub enum BorrowKind {
 ///////////////////////////////////////////////////////////////////////////
 // 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)]
-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,
 
-    /// 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>,
 
-    /// 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.
@@ -442,7 +481,7 @@ pub enum TerminatorKind<'tcx> {
     /// 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,
 
@@ -759,31 +798,16 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 ///////////////////////////////////////////////////////////////////////////
 // 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> {
-    /// 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),
 
-    /// the return pointer of the fn
-    ReturnPointer,
-
     /// 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,
         }))
     }
-
-    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> {
@@ -890,13 +896,9 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
         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))),
-            ReturnPointer =>
-                write!(fmt, "return"),
             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 {
-            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 {
-                    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()
@@ -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> {
-        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 },
-            &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),
         }
     }
index bd42eb3211a8b8acf4b6e1bc89ba8a25b1586eae..9e0bafa4e310f22bafe9244c0c3dfff26c979840 100644 (file)
@@ -236,19 +236,9 @@ fn visit_typed_const_val(&mut self,
                 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,
@@ -272,16 +262,8 @@ fn super_mir(&mut self,
 
                 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);
@@ -584,10 +566,7 @@ fn super_lvalue(&mut self,
                             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);
@@ -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: _,
-                    name: _,
                     ref $($mutability)* ty,
+                    name: _,
                     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);
+                if let Some(ref $($mutability)* info) = *source_info {
+                    self.visit_source_info(info);
+                }
             }
 
             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 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};
@@ -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] {
-        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(_) => {
+            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;
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>>,
-    drop_flags: FnvHashMap<MovePathIndex, Temp>,
+    drop_flags: FnvHashMap<MovePathIndex, Local>,
     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>> {
-        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
@@ -847,14 +847,14 @@ fn unelaborated_free_block<'a>(
             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;
-        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)));
@@ -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());
-            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() {
-            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> {
-    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
@@ -218,16 +212,9 @@ fn new(mir: &'a Mir<'tcx>,
                 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(),
-                    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,
@@ -272,23 +259,9 @@ fn move_path_for(&mut self, lval: &Lvalue<'tcx>)
     {
         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),
-            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)
             }
@@ -373,11 +346,8 @@ impl<'tcx> MovePathLookup<'tcx> {
     // 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::ReturnPointer => LookupResult::Exact(self.return_ptr.unwrap()),
             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 => {
-                self.gather_move(loc, &Lvalue::ReturnPointer);
+                self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
             }
 
             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;
-    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,
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>)>,
-    new_temps: Vec<TempDecl<'tcx>>,
+    new_locals: Vec<LocalDecl<'tcx>>,
     resume_block: BasicBlock,
-    next_temp: usize,
+    next_local: usize,
 }
 
 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![],
-            new_temps: vec![],
             new_statements: vec![],
-            next_temp: mir.temp_decls.len(),
+            new_locals: vec![],
+            next_local: mir.local_decls.len(),
             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 {
@@ -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 {}: {:?}",
-               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);
-        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);
index ae5ccbfd820996f8c1b582e66a501032f538797f..a9dfc6ea651e411499c584d392518a5b6b7d7233 100644 (file)
@@ -77,11 +77,11 @@ fn expr_as_lvalue(&mut self,
                 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];
-                block.and(Lvalue::Var(index))
+                block.and(Lvalue::Local(index))
             }
             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 {
-                    Some(value) => unpack!(this.into(&Lvalue::ReturnPointer, block, value)),
+                    Some(value) => {
+                        unpack!(this.into(&Lvalue::Local(RETURN_POINTER), block, value))
+                    }
                     None => {
-                        this.cfg.push_assign_unit(block, source_info, &Lvalue::ReturnPointer);
+                        this.cfg.push_assign_unit(block,
+                                                  source_info,
+                                                  &Lvalue::Local(RETURN_POINTER));
                         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);
-                let lvalue = Lvalue::Var(self.var_indices[&var]);
+                let lvalue = Lvalue::Local(self.var_indices[&var]);
                 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, .. } => {
-                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,
@@ -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,
-                kind: StatementKind::StorageLive(Lvalue::Var(var_index))
+                kind: StatementKind::StorageLive(Lvalue::Local(var_index))
             });
             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>)
-                       -> Var
+                       -> Local
     {
         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,
-            name: name,
             ty: var_ty.clone(),
+            name: Some(name),
+            source_info: Some(source_info),
         });
         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);
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> {
-        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 {:?}",
-               lvalue, self.temp_decls[temp].ty);
+               lvalue, self.local_decls[temp].ty);
         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,
+    arg_count: usize,
 
     /// 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,
 
-    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
@@ -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>)>
 {
+    let arguments: Vec<_> = arguments.collect();
+
     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 =
@@ -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;
-    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);
@@ -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);
-        return_block.and(arg_decls)
+        return_block.unit()
     }));
     assert_eq!(block, builder.return_block());
 
@@ -217,7 +220,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         }).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)
 }
@@ -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();
+    let ty = tcx.expr_ty_adjusted(ast_expr);
     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);
-        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();
@@ -247,23 +251,26 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
         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> {
-    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,
+            arg_count: arg_count,
             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,
@@ -279,7 +286,6 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span) -> Builder<'a, 'gcx, 'tcx> {
 
     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() {
@@ -292,27 +298,45 @@ fn finish(self,
                   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)
     }
 
-    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 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);
@@ -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);
 
-            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 {
@@ -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
-        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> {
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
-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
@@ -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
-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
@@ -322,7 +322,11 @@ pub fn pop_scope(&mut self,
         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));
@@ -362,7 +366,11 @@ pub fn exit_scope(&mut self,
                 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);
@@ -454,7 +462,7 @@ pub fn schedule_drop(&mut self,
         } 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
             }
         };
@@ -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>],
-                           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() {
@@ -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 {
-                    Lvalue::Temp(_) | Lvalue::Var(_) => {}
+                    Lvalue::Local(index) if index.index() > arg_count => {}
                     _ => continue
                 }
 
index 11b4441c8460a62e486194febb783ba9b2d1ec0c..343d802119ea0d8287c58aa22f1d26e5dbb5b38f 100644 (file)
 
 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>>,
-    mir_summary: MirSummary,
 }
 
 #[derive(Clone)]
@@ -35,15 +34,13 @@ pub struct Use<'tcx> {
 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()),
-            mir_summary: self.mir_summary,
         };
         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,
-                                  self.mir_summary,
                                   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>>,
-    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;
-        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,
-    mir_summary: MirSummary,
     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,
-            mir_summary: mir_summary,
             phantom: PhantomData,
         }
     }
@@ -155,43 +153,11 @@ fn visit_lvalue(&mut self,
                     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.
-    for (i, arg) in mir.arg_decls.iter().enumerate() {
+    for (i, arg) in mir.arg_iter().enumerate() {
         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"/>"#)?;
 
-    // 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 ")?;
-        if var.mutability == Mutability::Mut {
+        if decl.mutability == Mutability::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, ">;")
@@ -172,3 +173,5 @@ fn node(block: BasicBlock) -> String {
 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))
 }
 
+/// 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>>,
@@ -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).
-        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;
-            }
+            };
 
             let mut_str = if var.mutability == Mutability::Mut {
                 "mut "
@@ -251,13 +257,13 @@ fn write_scope_tree(tcx: TyCtxt,
                                        INDENT,
                                        indent,
                                        mut_str,
-                                       id,
+                                       local,
                                        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)?;
@@ -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_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)
@@ -313,30 +333,27 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
         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, "{:?}: {}", Lvalue::Arg(i), arg.ty)?;
+            write!(w, "{:?}: {}", Lvalue::Local(arg), mir.local_decls[arg].ty)?;
         }
 
         write!(w, ") -> {}", mir.return_ty)
     } else {
-        assert!(mir.arg_decls.is_empty());
+        assert_eq!(mir.arg_count, 0);
         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.
-    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(())
 }
+
+// TODO manually test
index 79fd16012d9ee24780e6449bd8baa4706a3ad109..783162cd5588fd90510ad4c7b6c008d57691b13e 100644 (file)
 //! (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_data_structures::indexed_vec::Idx;
 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;
-            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;
@@ -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 {
-                        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 {
-                        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 {
-                        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| {
@@ -121,11 +119,11 @@ fn run_pass<'a>(&mut self,
 
                     // 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) => {
-                                    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)
@@ -162,15 +160,14 @@ enum 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.
-        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.
@@ -225,9 +222,9 @@ fn perform(self,
                 // 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)
@@ -240,7 +237,7 @@ fn perform(self,
                 }
 
                 // 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.
@@ -253,8 +250,8 @@ fn perform(self,
                 // 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 {
@@ -264,8 +261,7 @@ fn perform(self,
                 }
 
                 // 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)
@@ -298,17 +294,15 @@ fn perform(self,
 struct ConstantPropagationVisitor<'tcx> {
     dest_local: Local,
     constant: Constant<'tcx>,
-    mir_summary: MirSummary,
     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,
-            mir_summary: mir_summary,
             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 {
-            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
     }
 }
-
index a0331f03b019742e9d1b2f51486deee00187b756..b4159af6f071d8d64de0c6eb5d52a729543944f9 100644 (file)
 
 //! 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_data_structures::indexed_vec::Idx;
 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)) => {
-                    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 `&*`!"),
             };
@@ -107,4 +109,3 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: 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 std::iter;
 use std::mem;
 use std::usize;
 
@@ -74,15 +75,21 @@ pub enum Candidate {
     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);
-        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.
@@ -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 {
-        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);
@@ -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>,
-    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.
@@ -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.
-    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 {
@@ -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 {
-            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, ..}  => {
-                    *destination = Some((Lvalue::Temp(new_temp), new_target));
+                    *destination = Some((Lvalue::Local(new_temp), new_target));
                 }
                 _ => 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
         });
-        self.assign(Lvalue::ReturnPointer, rvalue, span);
+
+        self.assign(Lvalue::Local(RETURN_POINTER), rvalue, span);
         self.source.promoted.push(self.promoted);
     }
 }
@@ -330,8 +338,10 @@ fn visit_lvalue(&mut self,
                     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);
     }
@@ -339,7 +349,7 @@ fn visit_lvalue(&mut self,
 
 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() {
@@ -353,7 +363,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
                                   "expected assignment to promote");
                     }
                 };
-                if let Lvalue::Temp(index) = *dest {
+                if let Lvalue::Local(index) = *dest {
                     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 {
-            source: mir,
             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,
-                IndexVec::new(),
-                IndexVec::new(),
-                IndexVec::new(),
+                initial_locals,
+                0,
                 vec![],
                 span
             ),
+            source: mir,
             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.
-    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 {
-                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
@@ -414,7 +426,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         });
         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
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>>,
-    temp_qualif: IndexVec<Temp, Option<Qualif>>,
+    temp_qualif: IndexVec<Local, Option<Qualif>>,
     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>
 }
 
@@ -173,10 +173,10 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             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(),
-            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![]
         }
@@ -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 {
-            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]);
                 }
             }
@@ -341,13 +343,20 @@ fn assign(&mut self, dest: &Lvalue<'tcx>, location: Location) {
         }
 
         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 {
-                base: Lvalue::Temp(index),
+                base: Lvalue::Local(index),
                 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)
                }) => {
@@ -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 {
+        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());
@@ -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.
-                    for temp in mir.temp_decls.indices() {
+                    for temp in mir.temp_iter() {
                         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;
-                    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,
                             });
@@ -480,23 +492,28 @@ fn visit_lvalue(&mut self,
                     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 {
@@ -505,9 +522,6 @@ fn visit_lvalue(&mut self,
                                a constant instead", self.mode);
                 }
             }
-            Lvalue::ReturnPointer => {
-                self.not_const();
-            }
             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 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.
-        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.
-                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) {
-                    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;
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);
-        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;
@@ -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 {
-            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::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 {
@@ -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 {
-                    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>) {
+        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.
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());
-    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.
index 5de59b9f6bded47cb54591fbbfb25195b4a5b1a5..455cf4eb455162c10f5a637de44a846157fdfdb8 100644 (file)
@@ -20,7 +20,6 @@
 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>,
@@ -30,11 +29,7 @@ pub fn lvalue_locals<'bcx, 'tcx>(bcx: Block<'bcx,'tcx>,
 
     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() ||
@@ -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> {
-        let local_count = mir.count_locals();
         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);
 
-        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);
@@ -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 {
-            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()));
@@ -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);
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 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) => {
@@ -218,7 +217,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                     }
                     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);
@@ -844,7 +843,7 @@ fn make_return_dest(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
         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,
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>,
-           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,
-            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() {
-            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
@@ -238,7 +239,7 @@ fn new(ccx: &'a CrateContext<'a, '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) {
@@ -311,8 +312,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr> {
                 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");
                     }));
                 }
@@ -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) {
-        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);
@@ -387,17 +387,14 @@ fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span)
                     -> 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 {
-            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)),
index 0ce5544c3bfc5b50bb650226e1f7601e32d23edb..7102bd81caf36e3d5243ab5a3014d11aa1650f6c 100644 (file)
@@ -91,7 +91,7 @@ pub fn trans_lvalue(&mut self,
         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;
@@ -103,10 +103,7 @@ pub fn trans_lvalue(&mut self,
         }
 
         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),
@@ -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
     {
-        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) => {
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);
-        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 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 {
-                // 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
@@ -346,10 +356,10 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
         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 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
@@ -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() {
-                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;
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
-        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;
@@ -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 {
-            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),
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) => {
-                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)
@@ -86,7 +86,7 @@ fn trans_storage_liveness(&self,
                               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);
             }
index e57a9674cf683d4be0421655c911bd7928076eb1..66c3dfbf48cf36dd6713dc0ba1c41c1d23874a7b 100644 (file)
@@ -23,19 +23,19 @@ fn main() {}
 // 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: {
-//     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
 // }
-// 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: {
-//     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: {
-//     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
 // }
-// 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;
 }
 
+// TODO The StorageDead for local1 (a) after local6's (c) is missing!
+
 // 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: {