about summary refs log tree commit diff
path: root/src/librustc_mir/interpret
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2019-02-08 14:00:52 +0100
committerRalf Jung <post@ralfj.de>2019-02-13 10:14:56 +0100
commitb376ae6671a20914d63691fdd4b543b2e6341d5b (patch)
treeda1699972ad56cb1acdcd123da33a9334d20004e /src/librustc_mir/interpret
parente73f96abe7cc3a76223e5d0b50592c287c517750 (diff)
downloadrust-b376ae6671a20914d63691fdd4b543b2e6341d5b.tar.gz
rust-b376ae6671a20914d63691fdd4b543b2e6341d5b.zip
make bin_op and unary_op APIs consistently work on ImmTy
Diffstat (limited to 'src/librustc_mir/interpret')
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs2
-rw-r--r--src/librustc_mir/interpret/machine.rs10
-rw-r--r--src/librustc_mir/interpret/operand.rs20
-rw-r--r--src/librustc_mir/interpret/operator.rs73
-rw-r--r--src/librustc_mir/interpret/step.rs2
-rw-r--r--src/librustc_mir/interpret/terminator.rs4
6 files changed, 57 insertions, 54 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 78c5c0a6d75..6466dd4098a 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -173,7 +173,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     "unchecked_shr" => BinOp::Shr,
                     _ => bug!("Already checked for int ops")
                 };
-                let (val, overflowed) = self.binary_op_imm(bin_op, l, r)?;
+                let (val, overflowed) = self.binary_op(bin_op, l, r)?;
                 if overflowed {
                     let layout = self.layout_of(substs.type_at(0))?;
                     let r_val =  r.to_scalar()?.to_bits(layout.size)?;
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 8f34b832f0b..7fb4c47d92a 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -7,11 +7,11 @@ use std::hash::Hash;
 
 use rustc::hir::{self, def_id::DefId};
 use rustc::mir;
-use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
+use rustc::ty::{self, query::TyCtxtAt};
 
 use super::{
     Allocation, AllocId, EvalResult, Scalar, AllocationExtra,
-    EvalContext, PlaceTy, MPlaceTy, OpTy, Pointer, MemoryKind,
+    EvalContext, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind,
 };
 
 /// Whether this kind of memory is allowed to leak
@@ -158,10 +158,8 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     fn ptr_op(
         ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
-        left: Scalar<Self::PointerTag>,
-        left_layout: TyLayout<'tcx>,
-        right: Scalar<Self::PointerTag>,
-        right_layout: TyLayout<'tcx>,
+        left: ImmTy<'tcx, Self::PointerTag>,
+        right: ImmTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx, (Scalar<Self::PointerTag>, bool)>;
 
     /// Heap allocations via the `box` keyword.
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 4d0da5e6ece..7da907028ee 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -45,6 +45,11 @@ impl Immediate {
 
 impl<'tcx, Tag> Immediate<Tag> {
     #[inline]
+    pub fn from_scalar(val: Scalar<Tag>) -> Self {
+        Immediate::Scalar(ScalarMaybeUndef::Scalar(val))
+    }
+
+    #[inline]
     pub fn erase_tag(self) -> Immediate
     {
         match self {
@@ -115,7 +120,7 @@ impl<'tcx, Tag> Immediate<Tag> {
 // as input for binary and cast operations.
 #[derive(Copy, Clone, Debug)]
 pub struct ImmTy<'tcx, Tag=()> {
-    crate imm: Immediate<Tag>, // ideally we'd make this private, but const_prop needs this
+    pub imm: Immediate<Tag>,
     pub layout: TyLayout<'tcx>,
 }
 
@@ -215,6 +220,19 @@ impl<'tcx, Tag> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
     }
 }
 
+impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag>
+{
+    #[inline]
+    pub fn from_scalar(val: Scalar<Tag>, layout: TyLayout<'tcx>) -> Self {
+        ImmTy { imm: Immediate::from_scalar(val), layout }
+    }
+
+    #[inline]
+    pub fn to_bits(self) -> EvalResult<'tcx, u128> {
+        self.to_scalar()?.to_bits(self.layout.size)
+    }
+}
+
 impl<'tcx, Tag> OpTy<'tcx, Tag>
 {
     #[inline]
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index 5e3335f4c72..b3b9c742d6c 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -18,7 +18,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         right: ImmTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
-        let (val, overflowed) = self.binary_op_imm(op, left, right)?;
+        let (val, overflowed) = self.binary_op(op, left, right)?;
         let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
         self.write_immediate(val, dest)
     }
@@ -32,7 +32,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         right: ImmTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
-        let (val, _overflowed) = self.binary_op_imm(op, left, right)?;
+        let (val, _overflowed) = self.binary_op(op, left, right)?;
         self.write_scalar(val, dest)
     }
 }
@@ -272,69 +272,55 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         Ok((val, false))
     }
 
-    /// Convenience wrapper that's useful when keeping the layout together with the
-    /// immediate value.
+    /// Returns the result of the specified operation and whether it overflowed.
     #[inline]
-    pub fn binary_op_imm(
+    pub fn binary_op(
         &self,
         bin_op: mir::BinOp,
         left: ImmTy<'tcx, M::PointerTag>,
         right: ImmTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, 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,
-        left: Scalar<M::PointerTag>,
-        left_layout: TyLayout<'tcx>,
-        right: Scalar<M::PointerTag>,
-        right_layout: TyLayout<'tcx>,
-    ) -> EvalResult<'tcx, (Scalar<M::PointerTag>, bool)> {
         trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})",
-            bin_op, left, left_layout.ty, right, right_layout.ty);
+            bin_op, *left, left.layout.ty, *right, right.layout.ty);
 
-        match left_layout.ty.sty {
+        match left.layout.ty.sty {
             ty::Char => {
-                assert_eq!(left_layout.ty, right_layout.ty);
-                let left = left.to_char()?;
-                let right = right.to_char()?;
+                assert_eq!(left.layout.ty, right.layout.ty);
+                let left = left.to_scalar()?.to_char()?;
+                let right = right.to_scalar()?.to_char()?;
                 self.binary_char_op(bin_op, left, right)
             }
             ty::Bool => {
-                assert_eq!(left_layout.ty, right_layout.ty);
-                let left = left.to_bool()?;
-                let right = right.to_bool()?;
+                assert_eq!(left.layout.ty, right.layout.ty);
+                let left = left.to_scalar()?.to_bool()?;
+                let right = right.to_scalar()?.to_bool()?;
                 self.binary_bool_op(bin_op, left, right)
             }
             ty::Float(fty) => {
-                assert_eq!(left_layout.ty, right_layout.ty);
-                let left = left.to_bits(left_layout.size)?;
-                let right = right.to_bits(right_layout.size)?;
+                assert_eq!(left.layout.ty, right.layout.ty);
+                let left = left.to_bits()?;
+                let right = right.to_bits()?;
                 self.binary_float_op(bin_op, fty, left, right)
             }
             _ => {
                 // Must be integer(-like) types.  Don't forget about == on fn pointers.
-                assert!(left_layout.ty.is_integral() || left_layout.ty.is_unsafe_ptr() ||
-                    left_layout.ty.is_fn());
-                assert!(right_layout.ty.is_integral() || right_layout.ty.is_unsafe_ptr() ||
-                    right_layout.ty.is_fn());
+                assert!(left.layout.ty.is_integral() || left.layout.ty.is_unsafe_ptr() ||
+                    left.layout.ty.is_fn());
+                assert!(right.layout.ty.is_integral() || right.layout.ty.is_unsafe_ptr() ||
+                    right.layout.ty.is_fn());
 
                 // Handle operations that support pointer values
-                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);
+                if left.to_scalar_ptr()?.is_ptr() ||
+                    right.to_scalar_ptr()?.is_ptr() ||
+                    bin_op == mir::BinOp::Offset
+                {
+                    return M::ptr_op(self, bin_op, left, right);
                 }
 
                 // Everything else only works with "proper" bits
-                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)
+                let l = left.to_bits().expect("we checked is_ptr");
+                let r = right.to_bits().expect("we checked is_ptr");
+                self.binary_int_op(bin_op, l, left.layout, r, right.layout)
             }
         }
     }
@@ -342,13 +328,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     pub fn unary_op(
         &self,
         un_op: mir::UnOp,
-        val: Scalar<M::PointerTag>,
-        layout: TyLayout<'tcx>,
+        val: ImmTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::mir::UnOp::*;
         use rustc_apfloat::ieee::{Single, Double};
         use rustc_apfloat::Float;
 
+        let layout = val.layout;
+        let val = val.to_scalar()?;
         trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty.sty);
 
         match layout.ty.sty {
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 0c988eb6810..97ef2b5fa34 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -176,7 +176,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             UnaryOp(un_op, ref operand) => {
                 // The operand always has the same type as the result.
                 let val = self.read_immediate(self.eval_operand(operand, Some(dest.layout))?)?;
-                let val = self.unary_op(un_op, val.to_scalar()?, dest.layout)?;
+                let val = self.unary_op(un_op, val)?;
                 self.write_scalar(val, dest)?;
             }
 
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 72d60f259e7..c2ee3f5715b 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -51,8 +51,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // 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.to_scalar()?, discr.layout,
-                        const_int, discr.layout,
+                        discr,
+                        ImmTy::from_scalar(const_int, discr.layout),
                     )?;
                     if res.to_bool()? {
                         target_block = targets[index];