]> git.lizzy.rs Git - rust.git/commitdiff
make ptr_op finally reponsible for all ops involving pointers; make ValTy constructor...
authorRalf Jung <post@ralfj.de>
Mon, 27 Aug 2018 23:14:29 +0000 (01:14 +0200)
committerRalf Jung <post@ralfj.de>
Wed, 29 Aug 2018 06:44:37 +0000 (08:44 +0200)
Also remove public OpTy constructors, but a pub(crate) constructor remains

src/librustc_mir/const_eval.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/transform/const_prop.rs

index 295fca839c812bd43c11ec858749a84eb863a999..70addf2c907e65ebeabff542e3a6c7b1735b013c 100644 (file)
@@ -288,21 +288,17 @@ fn call_intrinsic<'a>(
         )
     }
 
-    fn try_ptr_op<'a>(
+    fn ptr_op<'a>(
         _ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         _bin_op: mir::BinOp,
-        left: Scalar,
+        _left: Scalar,
         _left_layout: TyLayout<'tcx>,
-        right: Scalar,
+        _right: Scalar,
         _right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Scalar, bool)>> {
-        if left.is_bits() && right.is_bits() {
-            Ok(None)
-        } else {
-            Err(
-                ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
-            )
-        }
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        Err(
+            ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
+        )
     }
 
     fn find_foreign_static<'a>(
index 9bbaa0e7ef699007e06424acec28ff8dd608ece9..83264acf76a31809d7d4047713c592be56c72700 100644 (file)
@@ -48,13 +48,13 @@ pub fn cast(
             Misc => {
                 let src = self.read_value(src)?;
                 if self.type_is_fat_ptr(src_layout.ty) {
-                    match (src.value, self.type_is_fat_ptr(dest.layout.ty)) {
+                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
                         // pointers to extern types
                         (Value::Scalar(_),_) |
                         // slices and trait objects to other slices/trait objects
                         (Value::ScalarPair(..), true) => {
                             // No change to value
-                            self.write_value(src.value, dest)?;
+                            self.write_value(*src, dest)?;
                         }
                         // slices and trait objects to thin pointers (dropping the metadata)
                         (Value::ScalarPair(data, _), false) => {
index a8fae2b4871ed7a13d07666fbca0197e3a798516..57af63d63d9c47d074d9572b4c642b588c97345d 100644 (file)
@@ -69,20 +69,18 @@ fn find_foreign_static<'a>(
         def_id: DefId,
     ) -> EvalResult<'tcx, &'tcx Allocation>;
 
-    /// Called for all binary operations except on float types.
-    ///
-    /// Returns `None` if the operation should be handled by the integer
-    /// op code in order to share more code between machines
+    /// Called for all binary operations on integer(-like) types when one operand is a pointer
+    /// value, and for the `Offset` operation that is inherently about pointers.
     ///
     /// Returns a (value, overflowed) pair if the operation succeeded
-    fn try_ptr_op<'a>(
+    fn ptr_op<'a>(
         ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
         left: Scalar,
         left_layout: TyLayout<'tcx>,
         right: Scalar,
         right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Scalar, bool)>>;
+    ) -> EvalResult<'tcx, (Scalar, bool)>;
 
     /// Heap allocations via the `box` keyword
     ///
index b2a668b961f16e90b317a8de3f9c4477d197cb9a..6f9e0cf3e37b60f8d4e0ac636121d23c5c554ed2 100644 (file)
@@ -15,7 +15,7 @@
 use std::convert::TryInto;
 
 use rustc::{mir, ty};
-use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
+use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
 use rustc_data_structures::indexed_vec::Idx;
 
 use rustc::mir::interpret::{
@@ -85,7 +85,7 @@ pub fn to_scalar_ptr(self) -> EvalResult<'tcx, Scalar> {
 // as input for binary and cast operations.
 #[derive(Copy, Clone, Debug)]
 pub struct ValTy<'tcx> {
-    pub value: Value,
+    value: Value,
     pub layout: TyLayout<'tcx>,
 }
 
@@ -107,16 +107,6 @@ pub enum Operand {
 }
 
 impl Operand {
-    #[inline]
-    pub fn from_ptr(ptr: Pointer, align: Align) -> Self {
-        Operand::Indirect(MemPlace::from_ptr(ptr, align))
-    }
-
-    #[inline]
-    pub fn from_scalar_value(val: Scalar) -> Self {
-        Operand::Immediate(Value::Scalar(val.into()))
-    }
-
     #[inline]
     pub fn to_mem_place(self) -> MemPlace {
         match self {
@@ -138,7 +128,7 @@ pub fn to_immediate(self) -> Value {
 
 #[derive(Copy, Clone, Debug)]
 pub struct OpTy<'tcx> {
-    crate op: Operand, // ideally we'd make this private, but we are not there yet
+    crate op: Operand, // ideally we'd make this private, but const_prop needs this
     pub layout: TyLayout<'tcx>,
 }
 
@@ -184,23 +174,6 @@ fn eq(&self, other: &Self) -> bool {
 }
 impl<'tcx> Eq for OpTy<'tcx> {}
 
-impl<'tcx> OpTy<'tcx> {
-    #[inline]
-    pub fn from_ptr(ptr: Pointer, align: Align, layout: TyLayout<'tcx>) -> Self {
-        OpTy { op: Operand::from_ptr(ptr, align), layout }
-    }
-
-    #[inline]
-    pub fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
-        OpTy { op: Operand::from_ptr(ptr, layout.align), layout }
-    }
-
-    #[inline]
-    pub fn from_scalar_value(val: Scalar, layout: TyLayout<'tcx>) -> Self {
-        OpTy { op: Operand::Immediate(Value::Scalar(val.into())), layout }
-    }
-}
-
 // Use the existing layout if given (but sanity check in debug mode),
 // or compute the layout.
 #[inline(always)]
@@ -507,7 +480,7 @@ pub(super) fn const_value_to_op(
             ConstValue::ByRef(id, alloc, offset) => {
                 // We rely on mutability being set correctly in that allocation to prevent writes
                 // where none should happen -- and for `static mut`, we copy on demand anyway.
-                Ok(Operand::from_ptr(Pointer::new(id, offset), alloc.align))
+                Ok(Operand::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)))
             },
             ConstValue::ScalarPair(a, b) =>
                 Ok(Operand::Immediate(Value::ScalarPair(a.into(), b))),
index 4f4f00e320a9614e2ac83e67bb58dee7eedd955b..d07d37d43b13e64a7eaa958bacae83018b10e185 100644 (file)
@@ -28,7 +28,7 @@ pub fn binop_with_overflow(
         right: ValTy<'tcx>,
         dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
-        let (val, overflowed) = self.binary_op(op, left, right)?;
+        let (val, overflowed) = self.binary_op_val(op, left, right)?;
         let val = Value::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
         self.write_value(val, dest)
     }
@@ -42,7 +42,7 @@ pub fn binop_ignore_overflow(
         right: ValTy<'tcx>,
         dest: PlaceTy<'tcx>,
     ) -> EvalResult<'tcx> {
-        let (val, _overflowed) = self.binary_op(op, left, right)?;
+        let (val, _overflowed) = self.binary_op_val(op, left, right)?;
         self.write_scalar(val, dest)
     }
 }
@@ -282,16 +282,31 @@ fn binary_int_op(
         Ok((val, false))
     }
 
+    /// Convenience wrapper that's useful when keeping the layout together with the
+    /// value.
+    #[inline]
+    pub fn binary_op_val(
+        &self,
+        bin_op: mir::BinOp,
+        left: ValTy<'tcx>,
+        right: ValTy<'tcx>,
+    ) -> EvalResult<'tcx, (Scalar, bool)> {
+        self.binary_op(
+            bin_op,
+            left.to_scalar()?, left.layout,
+            right.to_scalar()?, right.layout,
+        )
+    }
+
     /// Returns the result of the specified operation and whether it overflowed.
     pub fn binary_op(
         &self,
         bin_op: mir::BinOp,
-        ValTy { value: left, layout: left_layout }: ValTy<'tcx>,
-        ValTy { value: right, layout: right_layout }: ValTy<'tcx>,
+        left: Scalar,
+        left_layout: TyLayout<'tcx>,
+        right: Scalar,
+        right_layout: TyLayout<'tcx>,
     ) -> EvalResult<'tcx, (Scalar, bool)> {
-        let left = left.to_scalar()?;
-        let right = right.to_scalar()?;
-
         trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})",
             bin_op, left, left_layout.ty, right, right_layout.ty);
 
@@ -322,15 +337,13 @@ pub fn binary_op(
                     right_layout.ty.is_fn());
 
                 // Handle operations that support pointer values
-                if let Some(handled) =
-                    M::try_ptr_op(self, bin_op, left, left_layout, right, right_layout)?
-                {
-                    return Ok(handled);
+                if left.is_ptr() || right.is_ptr() || bin_op == mir::BinOp::Offset {
+                    return M::ptr_op(self, bin_op, left, left_layout, right, right_layout);
                 }
 
                 // Everything else only works with "proper" bits
-                let left = left.to_bits(left_layout.size)?;
-                let right = right.to_bits(right_layout.size)?;
+                let left = left.to_bits(left_layout.size).expect("we checked is_ptr");
+                let right = right.to_bits(right_layout.size).expect("we checked is_ptr");
                 self.binary_int_op(bin_op, left, left_layout, right, right_layout)
             }
         }
index 08ee30e5948a68bdb5ea6a735e2a9e74990db58a..de8681062740938f62df21db9c279c3b17cfd5d3 100644 (file)
@@ -17,7 +17,7 @@
 
 use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar};
 use super::{
-    EvalContext, Machine, Value, OpTy, Place, PlaceTy, ValTy, Operand, StackPopCleanup
+    EvalContext, Machine, Value, OpTy, Place, PlaceTy, Operand, StackPopCleanup
 };
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -61,8 +61,8 @@ pub(super) fn eval_terminator(
                     // Compare using binary_op, to also support pointer values
                     let const_int = Scalar::from_uint(const_int, discr.layout.size);
                     let (res, _) = self.binary_op(mir::BinOp::Eq,
-                        discr,
-                        ValTy { value: Value::Scalar(const_int.into()), layout: discr.layout }
+                        discr.to_scalar()?, discr.layout,
+                        const_int, discr.layout,
                     )?;
                     if res.to_bool()? {
                         target_block = targets[index];
index 8d4e67b96e5b7a6a0cbf55a230ed237a236f40f8..e2b1a255eaca29fba90b48c664c84f5b27b2e5c0 100644 (file)
@@ -22,7 +22,7 @@
 };
 use rustc::ty::{TyCtxt, self, Instance};
 use interpret::{EvalContext, CompileTimeEvaluator, eval_promoted, mk_borrowck_eval_cx};
-use interpret::{Value, OpTy, MemoryKind};
+use interpret::{self, Value, OpTy, MemoryKind};
 use transform::{MirPass, MirSource};
 use syntax::source_map::{Span, DUMMY_SP};
 use rustc::ty::subst::Substs;
@@ -358,13 +358,15 @@ fn const_prop(
             Rvalue::Len(_) => None,
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
                 type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
-                    OpTy::from_scalar_value(
-                        Scalar::Bits {
-                            bits: n as u128,
-                            size: self.tcx.data_layout.pointer_size.bytes() as u8,
-                        },
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ),
+                    OpTy {
+                        op: interpret::Operand::Immediate(Value::Scalar(
+                            Scalar::Bits {
+                                bits: n as u128,
+                                size: self.tcx.data_layout.pointer_size.bytes() as u8,
+                            }.into()
+                        )),
+                        layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+                    },
                     span,
                 )))
             }
@@ -399,7 +401,11 @@ fn const_prop(
                     // Now run the actual operation.
                     this.ecx.unary_op(op, prim, arg.layout)
                 })?;
-                Some((OpTy::from_scalar_value(val, place_layout), span))
+                let res = OpTy {
+                    op: interpret::Operand::Immediate(Value::Scalar(val.into())),
+                    layout: place_layout,
+                };
+                Some((res, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -454,7 +460,7 @@ fn const_prop(
                 })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
                 let (val, overflow) = self.use_ecx(source_info, |this| {
-                    this.ecx.binary_op(op, l, r)
+                    this.ecx.binary_op_val(op, l, r)
                 })?;
                 let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
                     Value::ScalarPair(
@@ -470,7 +476,7 @@ fn const_prop(
                     Value::Scalar(val.into())
                 };
                 let res = OpTy {
-                    op: ::interpret::Operand::Immediate(val),
+                    op: interpret::Operand::Immediate(val),
                     layout: place_layout,
                 };
                 Some((res, span))