]> git.lizzy.rs Git - rust.git/commitdiff
make StorageLive lazy as well
authorRalf Jung <post@ralfj.de>
Sun, 7 Apr 2019 10:27:48 +0000 (12:27 +0200)
committerRalf Jung <post@ralfj.de>
Sun, 7 Apr 2019 10:27:48 +0000 (12:27 +0200)
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/operand.rs

index c3726c63ea4a90380f307a74e7b77d8d631a3517..05207c47d5d9d4bad5129607a37312d1fcddf466 100644 (file)
@@ -131,6 +131,22 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
     Live(Operand<Tag, Id>),
 }
 
+impl<Tag: Copy> LocalValue<Tag> {
+    /// The initial value of a local: ZST get "initialized" because they can be read from without
+    /// ever having been written to.
+    fn uninit_local(
+        layout: TyLayout<'_>
+    ) -> LocalValue<Tag> {
+        // FIXME: Can we avoid this ZST special case? That would likely require MIR
+        // generation changes.
+        if layout.is_zst() {
+            LocalValue::Live(Operand::Immediate(Immediate::Scalar(Scalar::zst().into())))
+        } else {
+            LocalValue::Uninitialized
+        }
+    }
+}
+
 impl<'tcx, Tag: Copy> LocalState<'tcx, Tag> {
     pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
         match self.state {
@@ -518,19 +534,15 @@ pub fn push_stack_frame(
                     }
                 },
             }
-            // FIXME: We initialize live ZST here.  This should not be needed if MIR was
-            // consistently generated for ZST, but that seems to not be the case -- there
-            // is MIR (around promoteds in particular) that reads local ZSTs that never
-            // were written to.
+            // The remaining locals are uninitialized, fill them with `uninit_local`.
+            // (For ZST this is not a NOP.)
             for (idx, local) in locals.iter_enumerated_mut() {
                 match local.state {
                     LocalValue::Uninitialized => {
                         // This needs to be properly initialized.
                         let ty = self.monomorphize(mir.local_decls[idx].ty)?;
                         let layout = self.layout_of(ty)?;
-                        if layout.is_zst() {
-                            local.state = LocalValue::Live(self.uninit_operand(layout)?);
-                        }
+                        local.state = LocalValue::uninit_local(layout);
                         local.layout = Cell::new(Some(layout));
                     }
                     LocalValue::Dead => {
@@ -622,9 +634,9 @@ pub fn storage_live(
         trace!("{:?} is now live", local);
 
         let layout = self.layout_of_local(self.frame(), local, None)?;
-        let init = LocalValue::Live(self.uninit_operand(layout)?);
+        let local_val = LocalValue::uninit_local(layout);
         // StorageLive *always* kills the value that's currently stored
-        Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
+        Ok(mem::replace(&mut self.frame_mut().locals[local].state, local_val))
     }
 
     /// Returns the old value of the local.
index 7ea56e3647437c54e9baba72bf7e86b75f7ebf3f..4ece062f380d68f6b2f00ad09040f9c79f6e356c 100644 (file)
@@ -14,7 +14,7 @@
 };
 use super::{
     InterpretCx, Machine,
-    MemPlace, MPlaceTy, PlaceTy, Place, MemoryKind,
+    MemPlace, MPlaceTy, PlaceTy, Place,
 };
 pub use rustc::mir::interpret::ScalarMaybeUndef;
 
@@ -373,33 +373,6 @@ pub fn read_str(
         Ok(str)
     }
 
-    pub fn uninit_operand(
-        &mut self,
-        layout: TyLayout<'tcx>
-    ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
-        // This decides which types we will use the Immediate optimization for, and hence should
-        // match what `try_read_immediate` and `eval_place_to_op` support.
-        if layout.is_zst() {
-            return Ok(Operand::Immediate(Immediate::Scalar(Scalar::zst().into())));
-        }
-
-        Ok(match layout.abi {
-            layout::Abi::Scalar(..) =>
-                Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef)),
-            layout::Abi::ScalarPair(..) =>
-                Operand::Immediate(Immediate::ScalarPair(
-                    ScalarMaybeUndef::Undef,
-                    ScalarMaybeUndef::Undef,
-                )),
-            _ => {
-                trace!("Forcing allocation for local of type {:?}", layout.ty);
-                Operand::Indirect(
-                    *self.allocate(layout, MemoryKind::Stack)
-                )
-            }
-        })
-    }
-
     /// Projection functions
     pub fn operand_field(
         &self,