]> git.lizzy.rs Git - rust.git/commitdiff
Refactoring: Couple values and types into an object when passed around together
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 24 Aug 2017 12:41:49 +0000 (14:41 +0200)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 24 Aug 2017 12:42:42 +0000 (14:42 +0200)
miri/fn_call.rs
miri/intrinsic.rs
miri/lib.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/lvalue.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/terminator/drop.rs
src/librustc_mir/interpret/terminator/mod.rs

index 3467322768cc44119bea7dee8afbe3b9bbc606ae..cb7ee73e9961852d353014621fea4fbf7c2cbecd 100644 (file)
@@ -19,7 +19,7 @@ pub trait EvalContextExt<'tcx> {
     fn call_c_abi(
         &mut self,
         def_id: DefId,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         dest: Lvalue,
         dest_ty: Ty<'tcx>,
         dest_block: mir::BasicBlock,
@@ -31,7 +31,7 @@ fn call_missing_fn(
         &mut self,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         sig: ty::FnSig<'tcx>,
         path: String,
     ) -> EvalResult<'tcx>;
@@ -40,7 +40,7 @@ fn eval_fn_call(
         &mut self,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         span: Span,
         sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx, bool>;
@@ -51,7 +51,7 @@ fn eval_fn_call(
         &mut self,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         span: Span,
         sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx, bool> {
@@ -63,7 +63,7 @@ fn eval_fn_call(
                 self.call_missing_fn(
                     instance,
                     destination,
-                    arg_operands,
+                    args,
                     sig,
                     path,
                 )?;
@@ -91,7 +91,7 @@ fn eval_fn_call(
     fn call_c_abi(
         &mut self,
         def_id: DefId,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         dest: Lvalue,
         dest_ty: Ty<'tcx>,
         dest_block: mir::BasicBlock,
@@ -102,17 +102,9 @@ fn call_c_abi(
             .unwrap_or(name)
             .as_str();
 
-        let args_res: EvalResult<Vec<Value>> = arg_operands
-            .iter()
-            .map(|arg| self.eval_operand(arg))
-            .collect();
-        let args = args_res?;
-
-        let usize = self.tcx.types.usize;
-
         match &link_name[..] {
             "malloc" => {
-                let size = self.value_to_primval(args[0], usize)?.to_u64()?;
+                let size = self.value_to_primval(args[0])?.to_u64()?;
                 if size == 0 {
                     self.write_null(dest, dest_ty)?;
                 } else {
@@ -139,7 +131,7 @@ fn call_c_abi(
                 //
                 // libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
                 // is called if a `HashMap` is created the regular way.
-                match self.value_to_primval(args[0], usize)?.to_u64()? {
+                match self.value_to_primval(args[0])?.to_u64()? {
                     318 | 511 => {
                         return err!(Unimplemented(
                             "miri does not support random number generators".to_owned(),
@@ -208,7 +200,7 @@ fn call_c_abi(
             "memcmp" => {
                 let left = args[0].into_ptr(&mut self.memory)?;
                 let right = args[1].into_ptr(&mut self.memory)?;
-                let n = self.value_to_primval(args[2], usize)?.to_u64()?;
+                let n = self.value_to_primval(args[2])?.to_u64()?;
 
                 let result = {
                     let left_bytes = self.memory.read_bytes(left, n)?;
@@ -231,8 +223,8 @@ fn call_c_abi(
 
             "memrchr" => {
                 let ptr = args[0].into_ptr(&mut self.memory)?;
-                let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
-                let num = self.value_to_primval(args[2], usize)?.to_u64()?;
+                let val = self.value_to_primval(args[1])?.to_u64()? as u8;
+                let num = self.value_to_primval(args[2])?.to_u64()?;
                 if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(
                     |&c| c == val,
                 )
@@ -246,8 +238,8 @@ fn call_c_abi(
 
             "memchr" => {
                 let ptr = args[0].into_ptr(&mut self.memory)?;
-                let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
-                let num = self.value_to_primval(args[2], usize)?.to_u64()?;
+                let val = self.value_to_primval(args[1])?.to_u64()? as u8;
+                let num = self.value_to_primval(args[2])?.to_u64()?;
                 if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(
                     |&c| c == val,
                 )
@@ -329,9 +321,9 @@ fn call_c_abi(
             }
 
             "write" => {
-                let fd = self.value_to_primval(args[0], usize)?.to_u64()?;
+                let fd = self.value_to_primval(args[0])?.to_u64()?;
                 let buf = args[1].into_ptr(&mut self.memory)?;
-                let n = self.value_to_primval(args[2], usize)?.to_u64()?;
+                let n = self.value_to_primval(args[2])?.to_u64()?;
                 trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
                 let result = if fd == 1 || fd == 2 {
                     // stdout/stderr
@@ -370,8 +362,7 @@ fn call_c_abi(
             }
 
             "sysconf" => {
-                let c_int = self.operand_ty(&arg_operands[0]);
-                let name = self.value_to_primval(args[0], c_int)?.to_u64()?;
+                let name = self.value_to_primval(args[0])?.to_u64()?;
                 trace!("sysconf() called with name {}", name);
                 // cache the sysconf integers via miri's global cache
                 let paths = &[
@@ -387,7 +378,7 @@ fn call_c_abi(
                         };
                         // compute global if not cached
                         let val = match self.globals.get(&cid).cloned() {
-                            Some(ptr) => self.value_to_primval(Value::ByRef(ptr), c_int)?.to_u64()?,
+                            Some(ptr) => self.value_to_primval(ValTy { value: Value::ByRef(ptr), ty: args[0].ty })?.to_u64()?,
                             None => eval_body_as_primval(self.tcx, instance)?.0.to_u64()?,
                         };
                         if val == name {
@@ -418,7 +409,7 @@ fn call_c_abi(
                 };
 
                 // Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t.
-                let key_type = self.operand_ty(&arg_operands[0]).builtin_deref(true, ty::LvaluePreference::NoPreference)
+                let key_type = args[0].ty.builtin_deref(true, ty::LvaluePreference::NoPreference)
                                    .ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
                 let key_size = {
                     let layout = self.type_layout(key_type)?;
@@ -442,20 +433,20 @@ fn call_c_abi(
             }
             "pthread_key_delete" => {
                 // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
-                let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
+                let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey;
                 self.memory.delete_tls_key(key)?;
                 // Return success (0)
                 self.write_null(dest, dest_ty)?;
             }
             "pthread_getspecific" => {
                 // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
-                let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
+                let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey;
                 let ptr = self.memory.load_tls(key)?;
                 self.write_ptr(dest, ptr, dest_ty)?;
             }
             "pthread_setspecific" => {
                 // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
-                let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
+                let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey;
                 let new_ptr = args[1].into_ptr(&mut self.memory)?;
                 self.memory.store_tls(key, new_ptr)?;
 
@@ -524,7 +515,7 @@ fn call_missing_fn(
         &mut self,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         sig: ty::FnSig<'tcx>,
         path: String,
     ) -> EvalResult<'tcx> {
@@ -546,7 +537,7 @@ fn call_missing_fn(
             // unify these two mechanisms for "hooking into missing functions".
             self.call_c_abi(
                 instance.def_id(),
-                arg_operands,
+                args,
                 dest,
                 dest_ty,
                 dest_block,
@@ -554,19 +545,11 @@ fn call_missing_fn(
             return Ok(());
         }
 
-        let args_res: EvalResult<Vec<Value>> = arg_operands
-            .iter()
-            .map(|arg| self.eval_operand(arg))
-            .collect();
-        let args = args_res?;
-
-        let usize = self.tcx.types.usize;
-
         match &path[..] {
             // Allocators are magic.  They have no MIR, even when the rest of libstd does.
             "alloc::heap::::__rust_alloc" => {
-                let size = self.value_to_primval(args[0], usize)?.to_u64()?;
-                let align = self.value_to_primval(args[1], usize)?.to_u64()?;
+                let size = self.value_to_primval(args[0])?.to_u64()?;
+                let align = self.value_to_primval(args[1])?.to_u64()?;
                 if size == 0 {
                     return err!(HeapAllocZeroBytes);
                 }
@@ -577,8 +560,8 @@ fn call_missing_fn(
                 self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
             }
             "alloc::heap::::__rust_alloc_zeroed" => {
-                let size = self.value_to_primval(args[0], usize)?.to_u64()?;
-                let align = self.value_to_primval(args[1], usize)?.to_u64()?;
+                let size = self.value_to_primval(args[0])?.to_u64()?;
+                let align = self.value_to_primval(args[1])?.to_u64()?;
                 if size == 0 {
                     return err!(HeapAllocZeroBytes);
                 }
@@ -591,8 +574,8 @@ fn call_missing_fn(
             }
             "alloc::heap::::__rust_dealloc" => {
                 let ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?;
-                let old_size = self.value_to_primval(args[1], usize)?.to_u64()?;
-                let align = self.value_to_primval(args[2], usize)?.to_u64()?;
+                let old_size = self.value_to_primval(args[1])?.to_u64()?;
+                let align = self.value_to_primval(args[2])?.to_u64()?;
                 if old_size == 0 {
                     return err!(HeapAllocZeroBytes);
                 }
@@ -607,10 +590,10 @@ fn call_missing_fn(
             }
             "alloc::heap::::__rust_realloc" => {
                 let ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?;
-                let old_size = self.value_to_primval(args[1], usize)?.to_u64()?;
-                let old_align = self.value_to_primval(args[2], usize)?.to_u64()?;
-                let new_size = self.value_to_primval(args[3], usize)?.to_u64()?;
-                let new_align = self.value_to_primval(args[4], usize)?.to_u64()?;
+                let old_size = self.value_to_primval(args[1])?.to_u64()?;
+                let old_align = self.value_to_primval(args[2])?.to_u64()?;
+                let new_size = self.value_to_primval(args[3])?.to_u64()?;
+                let new_align = self.value_to_primval(args[4])?.to_u64()?;
                 if old_size == 0 || new_size == 0 {
                     return err!(HeapAllocZeroBytes);
                 }
index 83c65a427c08221a38bce2bf731f28cce5d4fcde..3e04f8598716414ffd4778cf0bc64f23f0789137 100644 (file)
@@ -4,7 +4,7 @@
 use rustc::ty::{self, Ty};
 
 use rustc_miri::interpret::{EvalResult, Lvalue, LvalueExtra, PrimVal, PrimValKind, Value, Pointer,
-                            HasMemory, EvalContext, PtrAndAlign};
+                            HasMemory, EvalContext, PtrAndAlign, ValTy};
 
 use helpers::EvalContextExt as HelperEvalContextExt;
 
@@ -12,7 +12,7 @@ pub trait EvalContextExt<'tcx> {
     fn call_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         dest: Lvalue,
         dest_ty: Ty<'tcx>,
         dest_layout: &'tcx Layout,
@@ -24,20 +24,12 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
     fn call_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         dest: Lvalue,
         dest_ty: Ty<'tcx>,
         dest_layout: &'tcx Layout,
         target: mir::BasicBlock,
     ) -> EvalResult<'tcx> {
-        let arg_vals: EvalResult<Vec<Value>> =
-            args.iter().map(|arg| self.eval_operand(arg)).collect();
-        let arg_vals = arg_vals?;
-        let i32 = self.tcx.types.i32;
-        let isize = self.tcx.types.isize;
-        let usize = self.tcx.types.usize;
-        let f32 = self.tcx.types.f32;
-        let f64 = self.tcx.types.f64;
         let substs = instance.substs;
 
         let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
@@ -45,8 +37,8 @@ fn call_intrinsic(
             "add_with_overflow" => {
                 self.intrinsic_with_overflow(
                     mir::BinOp::Add,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?
@@ -55,8 +47,8 @@ fn call_intrinsic(
             "sub_with_overflow" => {
                 self.intrinsic_with_overflow(
                     mir::BinOp::Sub,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?
@@ -65,23 +57,22 @@ fn call_intrinsic(
             "mul_with_overflow" => {
                 self.intrinsic_with_overflow(
                     mir::BinOp::Mul,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?
             }
 
             "arith_offset" => {
-                let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64;
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
+                let offset = self.value_to_primval(args[1])?.to_i128()? as i64;
+                let ptr = args[0].into_ptr(&self.memory)?;
                 let result_ptr = self.wrapping_pointer_offset(ptr, substs.type_at(0), offset)?;
                 self.write_ptr(dest, result_ptr, dest_ty)?;
             }
 
             "assume" => {
-                let bool = self.tcx.types.bool;
-                let cond = self.value_to_primval(arg_vals[0], bool)?.to_bool()?;
+                let cond = self.value_to_primval(args[0])?.to_bool()?;
                 if !cond {
                     return err!(AssumptionNotHeld);
                 }
@@ -91,9 +82,12 @@ fn call_intrinsic(
             "atomic_load_relaxed" |
             "atomic_load_acq" |
             "volatile_load" => {
-                let ty = substs.type_at(0);
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
-                self.write_value(Value::by_ref(ptr), dest, ty)?;
+                let ptr = args[0].into_ptr(&self.memory)?;
+                let valty = ValTy {
+                    value: Value::by_ref(ptr),
+                    ty: substs.type_at(0),
+                };
+                self.write_value(valty, dest)?;
             }
 
             "atomic_store" |
@@ -101,8 +95,8 @@ fn call_intrinsic(
             "atomic_store_rel" |
             "volatile_store" => {
                 let ty = substs.type_at(0);
-                let dest = arg_vals[0].into_ptr(&self.memory)?;
-                self.write_value_to_ptr(arg_vals[1], dest, ty)?;
+                let dest = args[0].into_ptr(&self.memory)?;
+                self.write_value_to_ptr(args[1].value, dest, ty)?;
             }
 
             "atomic_fence_acq" => {
@@ -111,8 +105,8 @@ fn call_intrinsic(
 
             _ if intrinsic_name.starts_with("atomic_xchg") => {
                 let ty = substs.type_at(0);
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
-                let change = self.value_to_primval(arg_vals[1], ty)?;
+                let ptr = args[0].into_ptr(&self.memory)?;
+                let change = self.value_to_primval(args[1])?;
                 let old = self.read_value(ptr, ty)?;
                 let old = match old {
                     Value::ByVal(val) => val,
@@ -129,9 +123,9 @@ fn call_intrinsic(
 
             _ if intrinsic_name.starts_with("atomic_cxchg") => {
                 let ty = substs.type_at(0);
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
-                let expect_old = self.value_to_primval(arg_vals[1], ty)?;
-                let change = self.value_to_primval(arg_vals[2], ty)?;
+                let ptr = args[0].into_ptr(&self.memory)?;
+                let expect_old = self.value_to_primval(args[1])?;
+                let change = self.value_to_primval(args[2])?;
                 let old = self.read_value(ptr, ty)?;
                 let old = match old {
                     Value::ByVal(val) => val,
@@ -174,8 +168,8 @@ fn call_intrinsic(
             "atomic_xsub_acqrel" |
             "atomic_xsub_relaxed" => {
                 let ty = substs.type_at(0);
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
-                let change = self.value_to_primval(arg_vals[1], ty)?;
+                let ptr = args[0].into_ptr(&self.memory)?;
+                let change = self.value_to_primval(args[1])?;
                 let old = self.read_value(ptr, ty)?;
                 let old = match old {
                     Value::ByVal(val) => val,
@@ -204,13 +198,13 @@ fn call_intrinsic(
             "copy_nonoverlapping" => {
                 let elem_ty = substs.type_at(0);
                 let elem_size = self.type_size(elem_ty)?.expect("cannot copy unsized value");
-                let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?;
+                let count = self.value_to_primval(args[2])?.to_u64()?;
                 if count * elem_size != 0 {
                     // TODO: We do not even validate alignment for the 0-bytes case.  libstd relies on this in vec::IntoIter::next.
                     // Also see the write_bytes intrinsic.
                     let elem_align = self.type_align(elem_ty)?;
-                    let src = arg_vals[0].into_ptr(&self.memory)?;
-                    let dest = arg_vals[1].into_ptr(&self.memory)?;
+                    let src = args[0].into_ptr(&self.memory)?;
+                    let dest = args[1].into_ptr(&self.memory)?;
                     self.memory.copy(
                         src,
                         dest,
@@ -223,7 +217,7 @@ fn call_intrinsic(
 
             "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => {
                 let ty = substs.type_at(0);
-                let num = self.value_to_primval(arg_vals[0], ty)?.to_bytes()?;
+                let num = self.value_to_primval(args[0])?.to_bytes()?;
                 let kind = self.ty_to_primval_kind(ty)?;
                 let num = if intrinsic_name.ends_with("_nonzero") {
                     if num == 0 {
@@ -238,14 +232,14 @@ fn call_intrinsic(
 
             "discriminant_value" => {
                 let ty = substs.type_at(0);
-                let adt_ptr = arg_vals[0].into_ptr(&self.memory)?.to_ptr()?;
+                let adt_ptr = args[0].into_ptr(&self.memory)?.to_ptr()?;
                 let discr_val = self.read_discriminant_value(adt_ptr, ty)?;
                 self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
             }
 
             "sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" |
             "log10f32" | "log2f32" | "floorf32" | "ceilf32" | "truncf32" => {
-                let f = self.value_to_primval(arg_vals[0], f32)?.to_f32()?;
+                let f = self.value_to_primval(args[0])?.to_f32()?;
                 let f = match intrinsic_name {
                     "sinf32" => f.sin(),
                     "fabsf32" => f.abs(),
@@ -266,7 +260,7 @@ fn call_intrinsic(
 
             "sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" |
             "log10f64" | "log2f64" | "floorf64" | "ceilf64" | "truncf64" => {
-                let f = self.value_to_primval(arg_vals[0], f64)?.to_f64()?;
+                let f = self.value_to_primval(args[0])?.to_f64()?;
                 let f = match intrinsic_name {
                     "sinf64" => f.sin(),
                     "fabsf64" => f.abs(),
@@ -287,8 +281,8 @@ fn call_intrinsic(
 
             "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
                 let ty = substs.type_at(0);
-                let a = self.value_to_primval(arg_vals[0], ty)?;
-                let b = self.value_to_primval(arg_vals[1], ty)?;
+                let a = self.value_to_primval(args[0])?;
+                let b = self.value_to_primval(args[1])?;
                 let op = match intrinsic_name {
                     "fadd_fast" => mir::BinOp::Add,
                     "fsub_fast" => mir::BinOp::Sub,
@@ -360,8 +354,8 @@ fn call_intrinsic(
 
             "move_val_init" => {
                 let ty = substs.type_at(0);
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
-                self.write_value_to_ptr(arg_vals[1], ptr, ty)?;
+                let ptr = args[0].into_ptr(&self.memory)?;
+                self.write_value_to_ptr(args[1].value, ptr, ty)?;
             }
 
             "needs_drop" => {
@@ -376,8 +370,8 @@ fn call_intrinsic(
             }
 
             "offset" => {
-                let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64;
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
+                let offset = self.value_to_primval(args[1])?.to_i128()? as i64;
+                let ptr = args[0].into_ptr(&self.memory)?;
                 let result_ptr = self.pointer_offset(ptr, substs.type_at(0), offset)?;
                 self.write_ptr(dest, result_ptr, dest_ty)?;
             }
@@ -385,8 +379,8 @@ fn call_intrinsic(
             "overflowing_sub" => {
                 self.intrinsic_overflowing(
                     mir::BinOp::Sub,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
@@ -395,8 +389,8 @@ fn call_intrinsic(
             "overflowing_mul" => {
                 self.intrinsic_overflowing(
                     mir::BinOp::Mul,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
@@ -405,16 +399,16 @@ fn call_intrinsic(
             "overflowing_add" => {
                 self.intrinsic_overflowing(
                     mir::BinOp::Add,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
             }
 
             "powf32" => {
-                let f = self.value_to_primval(arg_vals[0], f32)?.to_f32()?;
-                let f2 = self.value_to_primval(arg_vals[1], f32)?.to_f32()?;
+                let f = self.value_to_primval(args[0])?.to_f32()?;
+                let f2 = self.value_to_primval(args[1])?.to_f32()?;
                 self.write_primval(
                     dest,
                     PrimVal::from_f32(f.powf(f2)),
@@ -423,8 +417,8 @@ fn call_intrinsic(
             }
 
             "powf64" => {
-                let f = self.value_to_primval(arg_vals[0], f64)?.to_f64()?;
-                let f2 = self.value_to_primval(arg_vals[1], f64)?.to_f64()?;
+                let f = self.value_to_primval(args[0])?.to_f64()?;
+                let f2 = self.value_to_primval(args[1])?.to_f64()?;
                 self.write_primval(
                     dest,
                     PrimVal::from_f64(f.powf(f2)),
@@ -433,9 +427,9 @@ fn call_intrinsic(
             }
 
             "fmaf32" => {
-                let a = self.value_to_primval(arg_vals[0], f32)?.to_f32()?;
-                let b = self.value_to_primval(arg_vals[1], f32)?.to_f32()?;
-                let c = self.value_to_primval(arg_vals[2], f32)?.to_f32()?;
+                let a = self.value_to_primval(args[0])?.to_f32()?;
+                let b = self.value_to_primval(args[1])?.to_f32()?;
+                let c = self.value_to_primval(args[2])?.to_f32()?;
                 self.write_primval(
                     dest,
                     PrimVal::from_f32(a * b + c),
@@ -444,9 +438,9 @@ fn call_intrinsic(
             }
 
             "fmaf64" => {
-                let a = self.value_to_primval(arg_vals[0], f64)?.to_f64()?;
-                let b = self.value_to_primval(arg_vals[1], f64)?.to_f64()?;
-                let c = self.value_to_primval(arg_vals[2], f64)?.to_f64()?;
+                let a = self.value_to_primval(args[0])?.to_f64()?;
+                let b = self.value_to_primval(args[1])?.to_f64()?;
+                let c = self.value_to_primval(args[2])?.to_f64()?;
                 self.write_primval(
                     dest,
                     PrimVal::from_f64(a * b + c),
@@ -455,8 +449,8 @@ fn call_intrinsic(
             }
 
             "powif32" => {
-                let f = self.value_to_primval(arg_vals[0], f32)?.to_f32()?;
-                let i = self.value_to_primval(arg_vals[1], i32)?.to_i128()?;
+                let f = self.value_to_primval(args[0])?.to_f32()?;
+                let i = self.value_to_primval(args[1])?.to_i128()?;
                 self.write_primval(
                     dest,
                     PrimVal::from_f32(f.powi(i as i32)),
@@ -465,8 +459,8 @@ fn call_intrinsic(
             }
 
             "powif64" => {
-                let f = self.value_to_primval(arg_vals[0], f64)?.to_f64()?;
-                let i = self.value_to_primval(arg_vals[1], i32)?.to_i128()?;
+                let f = self.value_to_primval(args[0])?.to_f64()?;
+                let i = self.value_to_primval(args[1])?.to_i128()?;
                 self.write_primval(
                     dest,
                     PrimVal::from_f64(f.powi(i as i32)),
@@ -484,7 +478,7 @@ fn call_intrinsic(
 
             "size_of_val" => {
                 let ty = substs.type_at(0);
-                let (size, _) = self.size_and_align_of_dst(ty, arg_vals[0])?;
+                let (size, _) = self.size_and_align_of_dst(ty, args[0].value)?;
                 self.write_primval(
                     dest,
                     PrimVal::from_u128(size as u128),
@@ -495,7 +489,7 @@ fn call_intrinsic(
             "min_align_of_val" |
             "align_of_val" => {
                 let ty = substs.type_at(0);
-                let (_, align) = self.size_and_align_of_dst(ty, arg_vals[0])?;
+                let (_, align) = self.size_and_align_of_dst(ty, args[0].value)?;
                 self.write_primval(
                     dest,
                     PrimVal::from_u128(align as u128),
@@ -506,8 +500,8 @@ fn call_intrinsic(
             "type_name" => {
                 let ty = substs.type_at(0);
                 let ty_name = ty.to_string();
-                let s = self.str_to_value(&ty_name)?;
-                self.write_value(s, dest, dest_ty)?;
+                let value = self.str_to_value(&ty_name)?;
+                self.write_value(ValTy { value, ty: dest_ty }, dest)?;
             }
             "type_id" => {
                 let ty = substs.type_at(0);
@@ -522,7 +516,7 @@ fn call_intrinsic(
                     /*aligned*/
                     false,
                     |ectx| {
-                        ectx.write_value_to_ptr(arg_vals[0], ptr.into(), src_ty)
+                        ectx.write_value_to_ptr(args[0].value, ptr.into(), src_ty)
                     },
                 )?;
             }
@@ -531,7 +525,7 @@ fn call_intrinsic(
                 let bits = self.type_size(dest_ty)?.expect(
                     "intrinsic can't be called on unsized type",
                 ) as u128 * 8;
-                let rhs = self.value_to_primval(arg_vals[1], substs.type_at(0))?
+                let rhs = self.value_to_primval(args[1])?
                     .to_bytes()?;
                 if rhs >= bits {
                     return err!(Intrinsic(
@@ -540,8 +534,8 @@ fn call_intrinsic(
                 }
                 self.intrinsic_overflowing(
                     mir::BinOp::Shl,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
@@ -551,7 +545,7 @@ fn call_intrinsic(
                 let bits = self.type_size(dest_ty)?.expect(
                     "intrinsic can't be called on unsized type",
                 ) as u128 * 8;
-                let rhs = self.value_to_primval(arg_vals[1], substs.type_at(0))?
+                let rhs = self.value_to_primval(args[1])?
                     .to_bytes()?;
                 if rhs >= bits {
                     return err!(Intrinsic(
@@ -560,38 +554,38 @@ fn call_intrinsic(
                 }
                 self.intrinsic_overflowing(
                     mir::BinOp::Shr,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
             }
 
             "unchecked_div" => {
-                let rhs = self.value_to_primval(arg_vals[1], substs.type_at(0))?
+                let rhs = self.value_to_primval(args[1])?
                     .to_bytes()?;
                 if rhs == 0 {
                     return err!(Intrinsic(format!("Division by 0 in unchecked_div")));
                 }
                 self.intrinsic_overflowing(
                     mir::BinOp::Div,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
             }
 
             "unchecked_rem" => {
-                let rhs = self.value_to_primval(arg_vals[1], substs.type_at(0))?
+                let rhs = self.value_to_primval(args[1])?
                     .to_bytes()?;
                 if rhs == 0 {
                     return err!(Intrinsic(format!("Division by 0 in unchecked_rem")));
                 }
                 self.intrinsic_overflowing(
                     mir::BinOp::Rem,
-                    &args[0],
-                    &args[1],
+                    args[0],
+                    args[1],
                     dest,
                     dest_ty,
                 )?;
@@ -619,15 +613,14 @@ fn call_intrinsic(
             }
 
             "write_bytes" => {
-                let u8 = self.tcx.types.u8;
                 let ty = substs.type_at(0);
                 let ty_align = self.type_align(ty)?;
-                let val_byte = self.value_to_primval(arg_vals[1], u8)?.to_u128()? as u8;
+                let val_byte = self.value_to_primval(args[1])?.to_u128()? as u8;
                 let size = self.type_size(ty)?.expect(
                     "write_bytes() type must be sized",
                 );
-                let ptr = arg_vals[0].into_ptr(&self.memory)?;
-                let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?;
+                let ptr = args[0].into_ptr(&self.memory)?;
+                let count = self.value_to_primval(args[2])?.to_u64()?;
                 if count > 0 {
                     // HashMap relies on write_bytes on a NULL ptr with count == 0 to work
                     // TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic)
index a26fbd5d3fc0b53924b5479f4a6a80bb3424f973..204746244c888a869497d33111e25ea91127a161 100644 (file)
@@ -94,9 +94,11 @@ fn run_main<'a, 'tcx: 'a>(
             let main_ty = main_instance.def.def_ty(ecx.tcx);
             let main_ptr_ty = ecx.tcx.mk_fn_ptr(main_ty.fn_sig(ecx.tcx));
             ecx.write_value(
-                Value::ByVal(PrimVal::Ptr(main_ptr)),
+                ValTy {
+                    value: Value::ByVal(PrimVal::Ptr(main_ptr)),
+                    ty: main_ptr_ty,
+                },
                 dest,
-                main_ptr_ty,
             )?;
 
             // Second argument (argc): 0
@@ -179,17 +181,17 @@ fn eval_fn_call<'a>(
         ecx: &mut EvalContext<'a, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         span: Span,
         sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx, bool> {
-        ecx.eval_fn_call(instance, destination, arg_operands, span, sig)
+        ecx.eval_fn_call(instance, destination, args, span, sig)
     }
 
     fn call_intrinsic<'a>(
         ecx: &mut rustc_miri::interpret::EvalContext<'a, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         dest: Lvalue,
         dest_ty: ty::Ty<'tcx>,
         dest_layout: &'tcx Layout,
index f66d3f65ff1955ef88ed2b94c86dbeab131ee748..82795340ddaf4519c289fc1988fd4277b448cea8 100644 (file)
@@ -6,7 +6,7 @@
 use syntax::codemap::Span;
 
 use super::{EvalResult, EvalError, EvalErrorKind, GlobalId, Lvalue, Value, PrimVal, EvalContext,
-            StackPopCleanup, PtrAndAlign, MemoryKind};
+            StackPopCleanup, PtrAndAlign, MemoryKind, ValTy};
 
 use rustc_const_math::ConstInt;
 
@@ -69,7 +69,11 @@ pub fn eval_body_as_primval<'a, 'tcx>(
         while ecx.step()? {}
     }
     let value = Value::ByRef(*ecx.globals.get(&cid).expect("global not cached"));
-    Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
+    let valty = ValTy {
+        value,
+        ty: mir.return_ty,
+    };
+    Ok((ecx.value_to_primval(valty)?, mir.return_ty))
 }
 
 pub fn eval_body_as_integer<'a, 'tcx>(
@@ -162,7 +166,7 @@ fn eval_fn_call<'a>(
         ecx: &mut EvalContext<'a, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        _arg_operands: &[mir::Operand<'tcx>],
+        _args: &[ValTy<'tcx>],
         span: Span,
         _sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx, bool> {
@@ -201,7 +205,7 @@ fn eval_fn_call<'a>(
     fn call_intrinsic<'a>(
         _ecx: &mut EvalContext<'a, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
-        _args: &[mir::Operand<'tcx>],
+        _args: &[ValTy<'tcx>],
         _dest: Lvalue,
         _dest_ty: Ty<'tcx>,
         _dest_layout: &'tcx layout::Layout,
index d4b7761567de7577e95f5a74817158a002174162..b516fab4afadbeb808bc924aaba32a776cd8643a 100644 (file)
@@ -133,6 +133,19 @@ pub struct TyAndPacked<'tcx> {
     pub packed: bool,
 }
 
+#[derive(Copy, Clone, Debug)]
+pub struct ValTy<'tcx> {
+    pub value: Value,
+    pub ty: Ty<'tcx>,
+}
+
+impl<'tcx> ::std::ops::Deref for ValTy<'tcx> {
+    type Target = Value;
+    fn deref(&self) -> &Value {
+        &self.value
+    }
+}
+
 #[derive(Copy, Clone, Debug)]
 pub struct PtrAndAlign {
     pub ptr: Pointer,
@@ -597,14 +610,12 @@ pub fn assign_fields(
         if self.ty_to_primval_kind(dest_ty).is_ok() {
             assert_eq!(operands.len(), 1);
             let value = self.eval_operand(&operands[0])?;
-            let value_ty = self.operand_ty(&operands[0]);
-            return self.write_value(value, dest, value_ty);
+            return self.write_value(value, dest);
         }
         for (field_index, operand) in operands.iter().enumerate() {
             let value = self.eval_operand(operand)?;
-            let value_ty = self.operand_ty(operand);
-            let field_dest = self.lvalue_field(dest, field_index, dest_ty, value_ty)?;
-            self.write_value(value, field_dest, value_ty)?;
+            let field_dest = self.lvalue_field(dest, field_index, dest_ty, value.ty)?;
+            self.write_value(value, field_dest)?;
         }
         Ok(())
     }
@@ -625,11 +636,17 @@ pub(super) fn eval_rvalue_into_lvalue(
         use rustc::mir::Rvalue::*;
         match *rvalue {
             Use(ref operand) => {
-                let value = self.eval_operand(operand)?;
-                self.write_value(value, dest, dest_ty)?;
+                let value = self.eval_operand(operand)?.value;
+                let valty = ValTy {
+                    value,
+                    ty: dest_ty,
+                };
+                self.write_value(valty, dest)?;
             }
 
             BinaryOp(bin_op, ref left, ref right) => {
+                let left = self.eval_operand(left)?;
+                let right = self.eval_operand(right)?;
                 if self.intrinsic_overflowing(
                     bin_op,
                     left,
@@ -648,6 +665,8 @@ pub(super) fn eval_rvalue_into_lvalue(
             }
 
             CheckedBinaryOp(bin_op, ref left, ref right) => {
+                let left = self.eval_operand(left)?;
+                let right = self.eval_operand(right)?;
                 self.intrinsic_with_overflow(
                     bin_op,
                     left,
@@ -717,8 +736,7 @@ pub(super) fn eval_rvalue_into_lvalue(
                                 assert_eq!(operands.len(), 1);
                                 let operand = &operands[0];
                                 let value = self.eval_operand(operand)?;
-                                let value_ty = self.operand_ty(operand);
-                                self.write_value(value, dest, value_ty)?;
+                                self.write_value(value, dest)?;
                             } else {
                                 if let Some(operand) = operands.get(0) {
                                     assert_eq!(operands.len(), 1);
@@ -796,9 +814,8 @@ pub(super) fn eval_rvalue_into_lvalue(
                         assert_eq!(operands.len(), 1);
                         let operand = &operands[0];
                         let value = self.eval_operand(operand)?;
-                        let value_ty = self.operand_ty(operand);
                         self.write_maybe_aligned_mut(!variants.packed, |ecx| {
-                            ecx.write_value(value, dest, value_ty)
+                            ecx.write_value(value, dest)
                         })?;
                     }
 
@@ -826,7 +843,7 @@ pub(super) fn eval_rvalue_into_lvalue(
                 let elem_size = self.type_size(elem_ty)?.expect(
                     "repeat element type must be sized",
                 );
-                let value = self.eval_operand(operand)?;
+                let value = self.eval_operand(operand)?.value;
 
                 // FIXME(solson)
                 let dest = Pointer::from(self.force_allocation(dest)?.to_ptr()?);
@@ -863,7 +880,11 @@ pub(super) fn eval_rvalue_into_lvalue(
                         bug!("attempted to take a reference to an enum downcast lvalue")
                     }
                 };
-                self.write_value(val, dest, dest_ty)?;
+                let valty = ValTy {
+                    value: val,
+                    ty: dest_ty,
+                };
+                self.write_value(valty, dest)?;
             }
 
             NullaryOp(mir::NullOp::Box, ty) => {
@@ -888,28 +909,38 @@ pub(super) fn eval_rvalue_into_lvalue(
                 match kind {
                     Unsize => {
                         let src = self.eval_operand(operand)?;
-                        let src_ty = self.operand_ty(operand);
-                        self.unsize_into(src, src_ty, dest, dest_ty)?;
+                        self.unsize_into(src.value, src.ty, dest, dest_ty)?;
                     }
 
                     Misc => {
                         let src = self.eval_operand(operand)?;
-                        let src_ty = self.operand_ty(operand);
-                        if self.type_is_fat_ptr(src_ty) {
-                            match (src, self.type_is_fat_ptr(dest_ty)) {
+                        if self.type_is_fat_ptr(src.ty) {
+                            match (src.value, self.type_is_fat_ptr(dest_ty)) {
                                 (Value::ByRef { .. }, _) |
                                 (Value::ByValPair(..), true) => {
-                                    self.write_value(src, dest, dest_ty)?;
+                                    let valty = ValTy {
+                                        value: src.value,
+                                        ty: dest_ty,
+                                    };
+                                    self.write_value(valty, dest)?;
                                 }
                                 (Value::ByValPair(data, _), false) => {
-                                    self.write_value(Value::ByVal(data), dest, dest_ty)?;
+                                    let valty = ValTy {
+                                        value: Value::ByVal(data),
+                                        ty: dest_ty,
+                                    };
+                                    self.write_value(valty, dest)?;
                                 }
                                 (Value::ByVal(_), _) => bug!("expected fat ptr"),
                             }
                         } else {
-                            let src_val = self.value_to_primval(src, src_ty)?;
-                            let dest_val = self.cast_primval(src_val, src_ty, dest_ty)?;
-                            self.write_value(Value::ByVal(dest_val), dest, dest_ty)?;
+                            let src_val = self.value_to_primval(src)?;
+                            let dest_val = self.cast_primval(src_val, src.ty, dest_ty)?;
+                            let valty = ValTy {
+                                value: Value::ByVal(dest_val),
+                                ty: dest_ty,
+                            };
+                            self.write_value(valty, dest)?;
                         }
                     }
 
@@ -918,11 +949,11 @@ pub(super) fn eval_rvalue_into_lvalue(
                             ty::TyFnDef(def_id, substs) => {
                                 let instance = resolve(self.tcx, def_id, substs);
                                 let fn_ptr = self.memory.create_fn_alloc(instance);
-                                self.write_value(
-                                    Value::ByVal(PrimVal::Ptr(fn_ptr)),
-                                    dest,
-                                    dest_ty,
-                                )?;
+                                let valty = ValTy {
+                                    value: Value::ByVal(PrimVal::Ptr(fn_ptr)),
+                                    ty: dest_ty,
+                                };
+                                self.write_value(valty, dest)?;
                             }
                             ref other => bug!("reify fn pointer on {:?}", other),
                         }
@@ -931,8 +962,9 @@ pub(super) fn eval_rvalue_into_lvalue(
                     UnsafeFnPointer => {
                         match dest_ty.sty {
                             ty::TyFnPtr(_) => {
-                                let src = self.eval_operand(operand)?;
-                                self.write_value(src, dest, dest_ty)?;
+                                let mut src = self.eval_operand(operand)?;
+                                src.ty = dest_ty;
+                                self.write_value(src, dest)?;
                             }
                             ref other => bug!("fn to unsafe fn cast on {:?}", other),
                         }
@@ -948,11 +980,11 @@ pub(super) fn eval_rvalue_into_lvalue(
                                     ty::ClosureKind::FnOnce,
                                 );
                                 let fn_ptr = self.memory.create_fn_alloc(instance);
-                                self.write_value(
-                                    Value::ByVal(PrimVal::Ptr(fn_ptr)),
-                                    dest,
-                                    dest_ty,
-                                )?;
+                                let valty = ValTy {
+                                    value: Value::ByVal(PrimVal::Ptr(fn_ptr)),
+                                    ty: dest_ty,
+                                };
+                                self.write_value(valty, dest)?;
                             }
                             ref other => bug!("closure fn pointer on {:?}", other),
                         }
@@ -1203,15 +1235,28 @@ pub(super) fn eval_operand_to_primval(
         &mut self,
         op: &mir::Operand<'tcx>,
     ) -> EvalResult<'tcx, PrimVal> {
-        let value = self.eval_operand(op)?;
-        let ty = self.operand_ty(op);
-        self.value_to_primval(value, ty)
+        let valty = self.eval_operand(op)?;
+        self.value_to_primval(valty)
+    }
+
+    pub(crate) fn operands_to_args(
+        &mut self,
+        ops: &[mir::Operand<'tcx>],
+    ) -> EvalResult<'tcx, Vec<ValTy<'tcx>>> {
+        ops.into_iter()
+            .map(|op| self.eval_operand(op))
+            .collect()
     }
 
-    pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, Value> {
+    pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValTy<'tcx>> {
         use rustc::mir::Operand::*;
         match *op {
-            Consume(ref lvalue) => self.eval_and_read_lvalue(lvalue),
+            Consume(ref lvalue) => {
+                Ok(ValTy {
+                    value: self.eval_and_read_lvalue(lvalue)?,
+                    ty: self.operand_ty(op),
+                })
+            },
 
             Constant(ref constant) => {
                 use rustc::mir::Literal;
@@ -1237,7 +1282,10 @@ pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, Valu
                     }
                 };
 
-                Ok(value)
+                Ok(ValTy {
+                    value,
+                    ty: self.operand_ty(op),
+                })
             }
         }
     }
@@ -1317,7 +1365,10 @@ pub(super) fn follow_by_ref_value(
         }
     }
 
-    pub fn value_to_primval(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
+    pub fn value_to_primval(
+        &mut self,
+        ValTy { value, ty } : ValTy<'tcx>,
+    ) -> EvalResult<'tcx, PrimVal> {
         match self.follow_by_ref_value(value, ty)? {
             Value::ByRef { .. } => bug!("follow_by_ref_value can't result in `ByRef`"),
 
@@ -1335,7 +1386,11 @@ pub fn write_null(&mut self, dest: Lvalue, dest_ty: Ty<'tcx>) -> EvalResult<'tcx
     }
 
     pub fn write_ptr(&mut self, dest: Lvalue, val: Pointer, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> {
-        self.write_value(val.to_value(), dest, dest_ty)
+        let valty = ValTy {
+            value: val.to_value(),
+            ty: dest_ty,
+        };
+        self.write_value(valty, dest)
     }
 
     pub fn write_primval(
@@ -1344,14 +1399,17 @@ pub fn write_primval(
         val: PrimVal,
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
-        self.write_value(Value::ByVal(val), dest, dest_ty)
+        let valty = ValTy {
+            value: Value::ByVal(val),
+            ty: dest_ty,
+        };
+        self.write_value(valty, dest)
     }
 
     pub fn write_value(
         &mut self,
-        src_val: Value,
+        ValTy { value: src_val, ty: dest_ty } : ValTy<'tcx>,
         dest: Lvalue,
-        dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
         //trace!("Writing {:?} to {:?} at type {:?}", src_val, dest, dest_ty);
         // Note that it is really important that the type here is the right one, and matches the type things are read at.
@@ -1748,13 +1806,21 @@ fn unsize_into_ptr(
             (&ty::TyArray(_, length), &ty::TySlice(_)) => {
                 let ptr = src.into_ptr(&self.memory)?;
                 // u64 cast is from usize to u64, which is always good
-                self.write_value(ptr.to_value_with_len(length as u64), dest, dest_ty)
+                let valty = ValTy {
+                    value: ptr.to_value_with_len(length as u64),
+                    ty: dest_ty,
+                };
+                self.write_value(valty, dest)
             }
             (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
                 // For now, upcasts are limited to changes in marker
                 // traits, and hence never actually require an actual
                 // change to the vtable.
-                self.write_value(src, dest, dest_ty)
+                let valty = ValTy {
+                    value: src,
+                    ty: dest_ty,
+                };
+                self.write_value(valty, dest)
             }
             (_, &ty::TyDynamic(ref data, _)) => {
                 let trait_ref = data.principal().unwrap().with_self_ty(
@@ -1764,7 +1830,11 @@ fn unsize_into_ptr(
                 let trait_ref = self.tcx.erase_regions(&trait_ref);
                 let vtable = self.get_vtable(src_pointee_ty, trait_ref)?;
                 let ptr = src.into_ptr(&self.memory)?;
-                self.write_value(ptr.to_value_with_vtable(vtable), dest, dest_ty)
+                let valty = ValTy {
+                    value: ptr.to_value_with_vtable(vtable),
+                    ty: dest_ty,
+                };
+                self.write_value(valty, dest)
             }
 
             _ => bug!("invalid unsizing {:?} -> {:?}", src_ty, dest_ty),
index 86479acd2a4cd83745beff1ce688ee240ec5f3f1..2bb0b88a356f6ca5a7a12ef68218f468cdeb5697 100644 (file)
@@ -435,10 +435,8 @@ pub(super) fn eval_lvalue_projection(
             }
 
             Index(ref operand) => {
-                // FIXME(solson)
                 let n_ptr = self.eval_operand(operand)?;
-                let usize = self.tcx.types.usize;
-                let n = self.value_to_primval(n_ptr, usize)?.to_u64()?;
+                let n = self.value_to_primval(n_ptr)?.to_u64()?;
                 return self.lvalue_index(base, base_ty, n);
             }
 
index dbe9f97dc1dc92aa374274b7bf059e46f353ceda..2d607005fe7d7091f8c31790fd6d146d7aa3afb1 100644 (file)
@@ -2,7 +2,7 @@
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
-use super::{EvalResult, EvalContext, Lvalue, PrimVal};
+use super::{EvalResult, EvalContext, Lvalue, PrimVal, ValTy};
 
 use rustc::{mir, ty};
 use syntax::codemap::Span;
@@ -29,7 +29,7 @@ fn eval_fn_call<'a>(
         ecx: &mut EvalContext<'a, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         span: Span,
         sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx, bool>;
@@ -38,7 +38,7 @@ fn eval_fn_call<'a>(
     fn call_intrinsic<'a>(
         ecx: &mut EvalContext<'a, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
-        args: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         dest: Lvalue,
         dest_ty: ty::Ty<'tcx>,
         dest_layout: &'tcx ty::layout::Layout,
index e3931444e6fc9979472f31a67a6fd4b6822f3961..3a5fdf273a4841eb6f066c7e9a1f8e6ecd113f6f 100644 (file)
@@ -23,7 +23,7 @@ macro_rules! err {
 pub use self::error::{EvalError, EvalResult, EvalErrorKind};
 
 pub use self::eval_context::{EvalContext, Frame, ResourceLimits, StackPopCleanup, DynamicLifetime,
-                             TyAndPacked, PtrAndAlign};
+                             TyAndPacked, PtrAndAlign, ValTy};
 
 pub use self::lvalue::{Lvalue, LvalueExtra, GlobalId};
 
index 42d4538e9503eacd59cc6c31b4fd669e60276e31..69a8882631a517d37a80ee3f43e1484aa9003097 100644 (file)
@@ -1,7 +1,7 @@
 use rustc::mir;
 use rustc::ty::Ty;
 
-use super::{EvalResult, EvalContext, Lvalue, Machine};
+use super::{EvalResult, EvalContext, Lvalue, Machine, ValTy};
 
 use super::value::{PrimVal, PrimValKind, Value, bytes_to_f32, bytes_to_f64, f32_to_bytes,
                    f64_to_bytes};
@@ -10,14 +10,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     fn binop_with_overflow(
         &mut self,
         op: mir::BinOp,
-        left: &mir::Operand<'tcx>,
-        right: &mir::Operand<'tcx>,
+        left: ValTy<'tcx>,
+        right: ValTy<'tcx>,
     ) -> EvalResult<'tcx, (PrimVal, bool)> {
-        let left_ty = self.operand_ty(left);
-        let right_ty = self.operand_ty(right);
-        let left_val = self.eval_operand_to_primval(left)?;
-        let right_val = self.eval_operand_to_primval(right)?;
-        self.binary_op(op, left_val, left_ty, right_val, right_ty)
+        let left_val = self.value_to_primval(left)?;
+        let right_val = self.value_to_primval(right)?;
+        self.binary_op(op, left_val, left.ty, right_val, right.ty)
     }
 
     /// Applies the binary operation `op` to the two operands and writes a tuple of the result
@@ -25,14 +23,18 @@ fn binop_with_overflow(
     pub fn intrinsic_with_overflow(
         &mut self,
         op: mir::BinOp,
-        left: &mir::Operand<'tcx>,
-        right: &mir::Operand<'tcx>,
+        left: ValTy<'tcx>,
+        right: ValTy<'tcx>,
         dest: Lvalue,
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
         let (val, overflowed) = self.binop_with_overflow(op, left, right)?;
         let val = Value::ByValPair(val, PrimVal::from_bool(overflowed));
-        self.write_value(val, dest, dest_ty)
+        let valty = ValTy {
+            value: val,
+            ty: dest_ty,
+        };
+        self.write_value(valty, dest)
     }
 
     /// Applies the binary operation `op` to the arguments and writes the result to the
@@ -40,8 +42,8 @@ pub fn intrinsic_with_overflow(
     pub fn intrinsic_overflowing(
         &mut self,
         op: mir::BinOp,
-        left: &mir::Operand<'tcx>,
-        right: &mir::Operand<'tcx>,
+        left: ValTy<'tcx>,
+        right: ValTy<'tcx>,
         dest: Lvalue,
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, bool> {
index 334d23ef369fb130c9c238b2bc111261ce4e31bd..32a4c66df2a807a290db0fd7cba52941c594eabb 100644 (file)
@@ -3,7 +3,7 @@
 use syntax::codemap::Span;
 
 use interpret::{EvalResult, EvalContext, StackPopCleanup, Lvalue, LvalueExtra, PrimVal, Value,
-                Machine};
+                Machine, ValTy};
 
 impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     pub(crate) fn drop_lvalue(
@@ -79,6 +79,10 @@ pub(crate) fn drop(
         let arg_local = arg_locals.next().unwrap();
         let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
         let arg_ty = self.tcx.mk_mut_ptr(ty);
-        self.write_value(arg, dest, arg_ty)
+        let valty = ValTy {
+            value: arg,
+            ty: arg_ty,
+        };
+        self.write_value(valty, dest)
     }
 }
index d8a432cfa482b5b3b2834abca3eb8dd007dbe4de..b2f19fe8bcdb11cf4aca871a8741d6453fcf5da6 100644 (file)
@@ -5,7 +5,7 @@
 use syntax::abi::Abi;
 
 use super::{EvalError, EvalResult, EvalErrorKind, EvalContext, eval_context, TyAndPacked,
-            PtrAndAlign, Lvalue, MemoryPointer, PrimVal, Value, Machine, HasMemory};
+            PtrAndAlign, Lvalue, MemoryPointer, PrimVal, Value, Machine, HasMemory, ValTy};
 use super::eval_context::IntegerExt;
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -39,8 +39,7 @@ pub(super) fn eval_terminator(
             } => {
                 // FIXME(CTFE): forbid branching
                 let discr_val = self.eval_operand(discr)?;
-                let discr_ty = self.operand_ty(discr);
-                let discr_prim = self.value_to_primval(discr_val, discr_ty)?;
+                let discr_prim = self.value_to_primval(discr_val)?;
 
                 // Branch to the `otherwise` case by default, if no match is found.
                 let mut target_block = targets[targets.len() - 1];
@@ -97,11 +96,12 @@ pub(super) fn eval_terminator(
                         return err!(Unimplemented(msg));
                     }
                 };
+                let args = self.operands_to_args(args)?;
                 let sig = self.erase_lifetimes(&sig);
                 self.eval_fn_call(
                     fn_def,
                     destination,
-                    args,
+                    &args,
                     terminator.source_info.span,
                     sig,
                 )?;
@@ -236,7 +236,7 @@ fn eval_fn_call(
         &mut self,
         instance: ty::Instance<'tcx>,
         destination: Option<(Lvalue, mir::BasicBlock)>,
-        arg_operands: &[mir::Operand<'tcx>],
+        args: &[ValTy<'tcx>],
         span: Span,
         sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx> {
@@ -252,28 +252,22 @@ fn eval_fn_call(
                     return err!(Unreachable);
                 }
                 let layout = self.type_layout(ty)?;
-                M::call_intrinsic(self, instance, arg_operands, ret, ty, layout, target)?;
+                M::call_intrinsic(self, instance, args, ret, ty, layout, target)?;
                 self.dump_local(ret);
                 Ok(())
             }
             // FIXME: figure out why we can't just go through the shim
             ty::InstanceDef::ClosureOnceShim { .. } => {
-                let mut args = Vec::new();
-                for arg in arg_operands {
-                    let arg_val = self.eval_operand(arg)?;
-                    let arg_ty = self.operand_ty(arg);
-                    args.push((arg_val, arg_ty));
-                }
-                if M::eval_fn_call(self, instance, destination, arg_operands, span, sig)? {
+                if M::eval_fn_call(self, instance, destination, args, span, sig)? {
                     return Ok(());
                 }
                 let mut arg_locals = self.frame().mir.args_iter();
                 match sig.abi {
                     // closure as closure once
                     Abi::RustCall => {
-                        for (arg_local, (arg_val, arg_ty)) in arg_locals.zip(args) {
+                        for (arg_local, &valty) in arg_locals.zip(args) {
                             let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
-                            self.write_value(arg_val, dest, arg_ty)?;
+                            self.write_value(valty, dest)?;
                         }
                     }
                     // non capture closure as fn ptr
@@ -284,14 +278,14 @@ fn eval_fn_call(
                             "arg_locals: {:?}",
                             self.frame().mir.args_iter().collect::<Vec<_>>()
                         );
-                        trace!("arg_operands: {:?}", arg_operands);
+                        trace!("args: {:?}", args);
                         let local = arg_locals.nth(1).unwrap();
-                        for (i, (arg_val, arg_ty)) in args.into_iter().enumerate() {
+                        for (i, &valty) in args.into_iter().enumerate() {
                             let dest = self.eval_lvalue(&mir::Lvalue::Local(local).field(
                                 mir::Field::new(i),
-                                arg_ty,
+                                valty.ty,
                             ))?;
-                            self.write_value(arg_val, dest, arg_ty)?;
+                            self.write_value(valty, dest)?;
                         }
                     }
                     _ => bug!("bad ABI for ClosureOnceShim: {:?}", sig.abi),
@@ -302,15 +296,8 @@ fn eval_fn_call(
             ty::InstanceDef::DropGlue(..) |
             ty::InstanceDef::CloneShim(..) |
             ty::InstanceDef::Item(_) => {
-                let mut args = Vec::new();
-                for arg in arg_operands {
-                    let arg_val = self.eval_operand(arg)?;
-                    let arg_ty = self.operand_ty(arg);
-                    args.push((arg_val, arg_ty));
-                }
-
                 // Push the stack frame, and potentially be entirely done if the call got hooked
-                if M::eval_fn_call(self, instance, destination, arg_operands, span, sig)? {
+                if M::eval_fn_call(self, instance, destination, args, span, sig)? {
                     return Ok(());
                 }
 
@@ -321,7 +308,7 @@ fn eval_fn_call(
                     "arg_locals: {:?}",
                     self.frame().mir.args_iter().collect::<Vec<_>>()
                 );
-                trace!("arg_operands: {:?}", arg_operands);
+                trace!("args: {:?}", args);
                 match sig.abi {
                     Abi::RustCall => {
                         assert_eq!(args.len(), 2);
@@ -330,20 +317,18 @@ fn eval_fn_call(
                             // write first argument
                             let first_local = arg_locals.next().unwrap();
                             let dest = self.eval_lvalue(&mir::Lvalue::Local(first_local))?;
-                            let (arg_val, arg_ty) = args.remove(0);
-                            self.write_value(arg_val, dest, arg_ty)?;
+                            self.write_value(args[0], dest)?;
                         }
 
                         // unpack and write all other args
-                        let (arg_val, arg_ty) = args.remove(0);
-                        let layout = self.type_layout(arg_ty)?;
+                        let layout = self.type_layout(args[1].ty)?;
                         if let (&ty::TyTuple(fields, _),
-                                &Layout::Univariant { ref variant, .. }) = (&arg_ty.sty, layout)
+                                &Layout::Univariant { ref variant, .. }) = (&args[1].ty.sty, layout)
                         {
                             trace!("fields: {:?}", fields);
                             if self.frame().mir.args_iter().count() == fields.len() + 1 {
                                 let offsets = variant.offsets.iter().map(|s| s.bytes());
-                                match arg_val {
+                                match args[1].value {
                                     Value::ByRef(PtrAndAlign { ptr, aligned }) => {
                                         assert!(
                                             aligned,
@@ -361,7 +346,11 @@ fn eval_fn_call(
                                                 dest,
                                                 ty
                                             );
-                                            self.write_value(arg, dest, ty)?;
+                                            let valty = ValTy {
+                                                value: arg,
+                                                ty,
+                                            };
+                                            self.write_value(valty, dest)?;
                                         }
                                     }
                                     Value::ByVal(PrimVal::Undef) => {}
@@ -370,7 +359,11 @@ fn eval_fn_call(
                                         let dest = self.eval_lvalue(&mir::Lvalue::Local(
                                             arg_locals.next().unwrap(),
                                         ))?;
-                                        self.write_value(other, dest, fields[0])?;
+                                        let valty = ValTy {
+                                            value: other,
+                                            ty: fields[0],
+                                        };
+                                        self.write_value(valty, dest)?;
                                     }
                                 }
                             } else {
@@ -379,20 +372,20 @@ fn eval_fn_call(
                                 let dest = self.eval_lvalue(
                                     &mir::Lvalue::Local(arg_locals.next().unwrap()),
                                 )?;
-                                self.write_value(arg_val, dest, arg_ty)?;
+                                self.write_value(args[1], dest)?;
                             }
                         } else {
                             bug!(
-                                "rust-call ABI tuple argument was {:?}, {:?}",
-                                arg_ty,
+                                "rust-call ABI tuple argument was {:#?}, {:#?}",
+                                args[1].ty,
                                 layout
                             );
                         }
                     }
                     _ => {
-                        for (arg_local, (arg_val, arg_ty)) in arg_locals.zip(args) {
+                        for (arg_local, &valty) in arg_locals.zip(args) {
                             let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
-                            self.write_value(arg_val, dest, arg_ty)?;
+                            self.write_value(valty, dest)?;
                         }
                     }
                 }
@@ -401,24 +394,17 @@ fn eval_fn_call(
             // cannot use the shim here, because that will only result in infinite recursion
             ty::InstanceDef::Virtual(_, idx) => {
                 let ptr_size = self.memory.pointer_size();
-                let (_, vtable) = self.eval_operand(&arg_operands[0])?.into_ptr_vtable_pair(
-                    &self.memory,
-                )?;
+                let (ptr, vtable) = args[0].into_ptr_vtable_pair(&self.memory)?;
                 let fn_ptr = self.memory.read_ptr(
                     vtable.offset(ptr_size * (idx as u64 + 3), &self)?,
                 )?;
                 let instance = self.memory.get_fn(fn_ptr.to_ptr()?)?;
-                let mut arg_operands = arg_operands.to_vec();
-                let ty = self.operand_ty(&arg_operands[0]);
-                let ty = self.get_field_ty(ty, 0)?.ty; // TODO: packed flag is ignored
-                match arg_operands[0] {
-                    mir::Operand::Consume(ref mut lval) => {
-                        *lval = lval.clone().field(mir::Field::new(0), ty)
-                    }
-                    _ => bug!("virtual call first arg cannot be a constant"),
-                }
+                let mut args = args.to_vec();
+                let ty = self.get_field_ty(args[0].ty, 0)?.ty; // TODO: packed flag is ignored
+                args[0].ty = ty;
+                args[0].value = ptr.to_value();
                 // recurse with concrete function
-                self.eval_fn_call(instance, destination, &arg_operands, span, sig)
+                self.eval_fn_call(instance, destination, &args, span, sig)
             }
         }
     }