]> git.lizzy.rs Git - rust.git/commitdiff
Implement length access and indexing for fixed-sized arrays.
authorScott Olson <scott@solson.me>
Mon, 21 Mar 2016 03:30:31 +0000 (21:30 -0600)
committerScott Olson <scott@solson.me>
Mon, 21 Mar 2016 03:30:31 +0000 (21:30 -0600)
src/interpreter.rs
test/arrays.rs

index 188c0590e52ace6adb743bdf350369d1050fea1e..3cc70a06270802cf0a0cb20731f548666e32411e 100644 (file)
@@ -531,6 +531,20 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
                 }
             }
 
+            Len(ref lvalue) => {
+                let ty = self.lvalue_ty(lvalue);
+                match ty.sty {
+                    ty::TyArray(_, n) => {
+                        let psize = self.memory.pointer_size;
+                        self.memory.write_uint(dest, n as u64, psize)
+                    }
+                    ty::TySlice(_) => {
+                        unimplemented!()
+                    }
+                    _ => panic!("Rvalue::Len expected array or slice, got {:?}", ty),
+                }
+            }
+
             Ref(_, _, ref lvalue) => {
                 let ptr = try!(self.eval_lvalue(lvalue));
                 self.memory.write_ptr(dest, ptr)
@@ -635,16 +649,14 @@ fn lvalue_repr(&self, lvalue: &mir::Lvalue<'tcx>) -> &'arena Repr {
         }
     }
 
-    fn eval_lvalue(&self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Pointer> {
-        let frame = self.current_frame();
-
+    fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Pointer> {
         use rustc::mir::repr::Lvalue::*;
         let ptr = match *lvalue {
-            ReturnPointer =>
-                frame.return_ptr.expect("ReturnPointer used in a function with no return value"),
-            Arg(i) => frame.locals[i as usize],
-            Var(i) => frame.locals[frame.var_offset + i as usize],
-            Temp(i) => frame.locals[frame.temp_offset + i as usize],
+            ReturnPointer => self.current_frame().return_ptr
+                .expect("ReturnPointer used in a function with no return value"),
+            Arg(i) => self.current_frame().locals[i as usize],
+            Var(i) => self.current_frame().locals[self.current_frame().var_offset + i as usize],
+            Temp(i) => self.current_frame().locals[self.current_frame().temp_offset + i as usize],
 
             Projection(ref proj) => {
                 let base_ptr = try!(self.eval_lvalue(&proj.base));
@@ -667,7 +679,19 @@ fn eval_lvalue(&self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Pointer> {
                     // FIXME(tsion): Wrong for fat pointers.
                     Deref => try!(self.memory.read_ptr(base_ptr)),
 
-                    _ => unimplemented!(),
+                    Index(ref operand) => {
+                        let base_ty = self.lvalue_ty(&proj.base);
+                        let elem_size = match base_ty.sty {
+                            ty::TyArray(elem_ty, _) => self.ty_size(elem_ty),
+                            ty::TySlice(elem_ty) => self.ty_size(elem_ty),
+                            _ => panic!("indexing expected an array or slice, got {:?}", base_ty),
+                        };
+                        let n_ptr = try!(self.eval_operand(operand));
+                        let n = try!(self.memory.read_uint(n_ptr, self.memory.pointer_size));
+                        base_ptr.offset(n as isize * elem_size as isize)
+                    }
+
+                    ref p => panic!("can't handle lvalue projection: {:?}", p),
                 }
             }
 
@@ -720,6 +744,10 @@ fn const_to_ptr(&mut self, const_val: &const_eval::ConstVal) -> EvalResult<Point
         }
     }
 
+    fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> ty::Ty<'tcx> {
+        self.current_frame().mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx)
+    }
+
     fn monomorphize(&self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
         let substituted = ty.subst(self.tcx, self.current_substs());
         infer::normalize_associated_type(self.tcx, &substituted)
@@ -762,7 +790,7 @@ fn ty_to_repr(&self, ty: ty::Ty<'tcx>) -> &'arena Repr {
                 self.make_aggregate_repr(variants)
             }
 
-            ty::TyArray(ref elem_ty, length) => Repr::Array {
+            ty::TyArray(elem_ty, length) => Repr::Array {
                 elem_size: self.ty_size(elem_ty),
                 length: length,
             },
@@ -823,7 +851,6 @@ fn make_aggregate_repr<V>(&self, variant_fields: V) -> Repr
             size: max_variant_size + discr_size,
             variants: variants,
         }
-
     }
 
     pub fn read_primval(&mut self, ptr: Pointer, ty: ty::Ty<'tcx>) -> EvalResult<PrimVal> {
index 1add02561e38ed21dde2f002d7eec3a5c8424ca2..2939acfeaee158f85abd2e9fbaa05c5c8d07144a 100755 (executable)
 }
 
 #[miri_run]
-fn indexing() -> i32 {
+fn index_unsafe() -> i32 {
     let a = [0, 10, 20, 30];
     unsafe { *a.get_unchecked(2) }
 }
+
+#[miri_run]
+fn index() -> i32 {
+    let a = [0, 10, 20, 30];
+    a[2]
+}