about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2019-01-08 13:49:37 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-01-27 21:41:35 +0100
commitfe50b4eb1d6f7a31c53798bca3d0fa2b0670fa3d (patch)
tree5dd322e06bb9bcabcde61868a91d01c326127f72 /src
parent2a1748834e80b2461be4e18d420503d60e687312 (diff)
downloadrust-fe50b4eb1d6f7a31c53798bca3d0fa2b0670fa3d.tar.gz
rust-fe50b4eb1d6f7a31c53798bca3d0fa2b0670fa3d.zip
`ConstValue::ScalarPair` only needs to represent slices
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/impls_ty.rs2
-rw-r--r--src/librustc/mir/interpret/value.rs24
-rw-r--r--src/librustc/mir/mod.rs30
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc/ty/sty.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs12
-rw-r--r--src/librustc_mir/const_eval.rs9
-rw-r--r--src/librustc_mir/hair/constant.rs4
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs23
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs20
-rw-r--r--src/librustc_mir/interpret/operand.rs4
-rw-r--r--src/librustc_mir/monomorphize/collector.rs7
12 files changed, 59 insertions, 82 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 79c2b89522d..bd2349161f7 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -302,7 +302,7 @@ impl_stable_hash_for!(struct ty::FieldDef {
 impl_stable_hash_for!(
     impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
         Scalar(val),
-        ScalarPair(a, b),
+        Slice(a, b),
         ByRef(id, alloc, offset),
     }
 );
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 896e2ab960c..4ac84bcfd19 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -22,10 +22,13 @@ pub enum ConstValue<'tcx> {
     /// Not using the enum `Value` to encode that this must not be `Undef`
     Scalar(Scalar),
 
-    /// Used only for *fat pointers* with layout::abi::ScalarPair
+    /// Used only for slices and strings (`&[T]`, `&str`, `*const [T]`, `*mut str`, `Box<str>`, ...)
     ///
-    /// Needed for pattern matching code related to slices and strings.
-    ScalarPair(Scalar, Scalar),
+    /// Empty slices don't necessarily have an address backed by an `AllocId`, thus we also need to
+    /// enable integer pointers. The `Scalar` type covers exactly those two cases. While we could
+    /// create dummy-`AllocId`s, the additional code effort for the conversions doesn't seem worth
+    /// it.
+    Slice(Scalar, u64),
 
     /// An allocation + offset into the allocation.
     /// Invariant: The AllocId matches the allocation.
@@ -33,14 +36,14 @@ pub enum ConstValue<'tcx> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue<'static>>() == 56);
+static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue<'static>>() == 40);
 
 impl<'tcx> ConstValue<'tcx> {
     #[inline]
     pub fn try_to_scalar(&self) -> Option<Scalar> {
         match *self {
             ConstValue::ByRef(..) |
-            ConstValue::ScalarPair(..) => None,
+            ConstValue::Slice(..) => None,
             ConstValue::Scalar(val) => Some(val),
         }
     }
@@ -59,17 +62,8 @@ impl<'tcx> ConstValue<'tcx> {
     pub fn new_slice(
         val: Scalar,
         len: u64,
-        cx: &impl HasDataLayout
     ) -> Self {
-        ConstValue::ScalarPair(val, Scalar::Bits {
-            bits: len as u128,
-            size: cx.data_layout().pointer_size.bytes() as u8,
-        })
-    }
-
-    #[inline]
-    pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
-        ConstValue::ScalarPair(val, Scalar::Ptr(vtable))
+        ConstValue::Slice(val, len)
     }
 }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index f824ab7e5b3..82083b4f699 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2702,23 +2702,21 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul
         return write!(f, "{}", item_path_str(did));
     }
     // print string literals
-    if let ConstValue::ScalarPair(ptr, len) = value {
+    if let ConstValue::Slice(ptr, len) = value {
         if let Scalar::Ptr(ptr) = ptr {
-            if let Scalar::Bits { bits: len, .. } = len {
-                if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
-                    return ty::tls::with(|tcx| {
-                        let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
-                        if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
-                            assert_eq!(len as usize as u128, len);
-                            let slice =
-                                &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
-                            let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
-                            write!(f, "{:?}", s)
-                        } else {
-                            write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
-                        }
-                    });
-                }
+            if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
+                return ty::tls::with(|tcx| {
+                    let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
+                    if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
+                        assert_eq!(len as usize as u64, len);
+                        let slice =
+                            &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
+                        let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
+                        write!(f, "{:?}", s)
+                    } else {
+                        write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
+                    }
+                });
             }
         }
     }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 258470bf6f8..28f5a65374d 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -498,7 +498,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         match *self {
             ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
-            ConstValue::ScalarPair(x, y) => Some(ConstValue::ScalarPair(x, y)),
+            ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
             ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef(
                 x, alloc.lift_to_tcx(tcx)?, z,
             )),
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index a42b80e594c..671a0fc2d5d 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -2064,7 +2064,7 @@ pub enum LazyConst<'tcx> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 72);
+static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
 
 impl<'tcx> LazyConst<'tcx> {
     pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
@@ -2093,7 +2093,7 @@ pub struct Const<'tcx> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 64);
+static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 48);
 
 impl<'tcx> Const<'tcx> {
     #[inline]
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 2026e042ef0..8aad4c1f6e1 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -88,9 +88,9 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
                 );
                 OperandValue::Immediate(llval)
             },
-            ConstValue::ScalarPair(a, b) => {
-                let (a_scalar, b_scalar) = match layout.abi {
-                    layout::Abi::ScalarPair(ref a, ref b) => (a, b),
+            ConstValue::Slice(a, b) => {
+                let a_scalar = match layout.abi {
+                    layout::Abi::ScalarPair(ref a, _) => a,
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
                 };
                 let a_llval = bx.cx().scalar_to_backend(
@@ -98,11 +98,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
                     a_scalar,
                     bx.cx().scalar_pair_element_backend_type(layout, 0, true),
                 );
-                let b_llval = bx.cx().scalar_to_backend(
-                    b,
-                    b_scalar,
-                    bx.cx().scalar_pair_element_backend_type(layout, 1, true),
-                );
+                let b_llval = bx.cx().const_usize(b);
                 OperandValue::Pair(a_llval, b_llval)
             },
             ConstValue::ByRef(_, alloc, offset) => {
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 9ed480a9af5..f83a930353b 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -67,14 +67,11 @@ pub fn op_to_const<'tcx>(
     op: OpTy<'tcx>,
     may_normalize: bool,
 ) -> EvalResult<'tcx, ty::Const<'tcx>> {
-    // We do not normalize just any data.  Only scalar layout and fat pointers.
+    // We do not normalize just any data.  Only scalar layout and slices.
     let normalize = may_normalize
         && match op.layout.abi {
             layout::Abi::Scalar(..) => true,
-            layout::Abi::ScalarPair(..) => {
-                // Must be a fat pointer
-                op.layout.ty.builtin_deref(true).is_some()
-            },
+            layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
             _ => false,
         };
     let normalized_op = if normalize {
@@ -103,7 +100,7 @@ pub fn op_to_const<'tcx>(
         Ok(Immediate::Scalar(x)) =>
             ConstValue::Scalar(x.not_undef()?),
         Ok(Immediate::ScalarPair(a, b)) =>
-            ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?),
+            ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
     };
     Ok(ty::Const { val, ty: op.layout.ty })
 }
diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs
index f63c3e2ff61..21c471d49ee 100644
--- a/src/librustc_mir/hair/constant.rs
+++ b/src/librustc_mir/hair/constant.rs
@@ -35,13 +35,13 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
         LitKind::Str(ref s, _) => {
             let s = s.as_str();
             let id = tcx.allocate_bytes(s.as_bytes());
-            ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
+            ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64)
         },
         LitKind::Err(ref s) => {
             let s = s.as_str();
             let id = tcx.allocate_bytes(s.as_bytes());
             return Ok(ty::Const {
-                val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx),
+                val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64),
                 ty: tcx.types.err,
             });
         },
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 9cc5c93de41..7f5b1a761d2 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -221,13 +221,16 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
             // unsize array to slice if pattern is array but match value or other patterns are slice
             (ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
                 assert_eq!(t, u);
-                ConstValue::ScalarPair(
+                ConstValue::Slice(
                     Scalar::Ptr(p),
-                    n.map_evaluated(|val| val.val.try_to_scalar()).unwrap(),
+                    n.map_evaluated(|val| val.val.try_to_scalar())
+                        .unwrap()
+                        .to_usize(&self.tcx)
+                        .unwrap(),
                 )
             },
             // fat pointers stay the same
-            (ConstValue::ScalarPair(..), _, _) => val,
+            (ConstValue::Slice(..), _, _) => val,
             // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used
             _ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
         }
@@ -788,9 +791,9 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
                         max_fixed_len,
                         n.unwrap_usize(cx.tcx),
                     ),
-                    (ConstValue::ScalarPair(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
+                    (ConstValue::Slice(_, n), ty::Slice(_)) => max_fixed_len = cmp::max(
                         max_fixed_len,
-                        n.to_usize(&cx.tcx).unwrap(),
+                        n,
                     ),
                     _ => {},
                 }
@@ -1432,7 +1435,7 @@ fn slice_pat_covered_by_const<'tcx>(
             alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
         },
         // a slice fat pointer to a zero length slice
-        (ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(t)) => {
+        (ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => {
             if *t != tcx.types.u8 {
                 // FIXME(oli-obk): can't mix const patterns with slice patterns and get
                 // any sort of exhaustiveness/unreachable check yet
@@ -1440,11 +1443,10 @@ fn slice_pat_covered_by_const<'tcx>(
                 // are definitely unreachable.
                 return Ok(false);
             }
-            assert_eq!(n.to_usize(&tcx).unwrap(), 0);
             &[]
         },
         //
-        (ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
+        (ConstValue::Slice(Scalar::Ptr(ptr), n), ty::Slice(t)) => {
             if *t != tcx.types.u8 {
                 // FIXME(oli-obk): can't mix const patterns with slice patterns and get
                 // any sort of exhaustiveness/unreachable check yet
@@ -1452,7 +1454,6 @@ fn slice_pat_covered_by_const<'tcx>(
                 // are definitely unreachable.
                 return Ok(false);
             }
-            let n = n.to_usize(&tcx).unwrap();
             tcx.alloc_map
                 .lock()
                 .unwrap_memory(ptr.alloc_id)
@@ -1784,12 +1785,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                         },
                         ty::TyKind::Slice(t) => {
                             match value.val {
-                                ConstValue::ScalarPair(ptr, n) => (
+                                ConstValue::Slice(ptr, n) => (
                                     ptr.to_ptr().ok().map(|ptr| (
                                         ptr,
                                         cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
                                     )),
-                                    n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64,
+                                    n,
                                     t,
                                 ),
                                 _ => span_bug!(
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 06a50f35be1..7d48cdc1d8a 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -1218,25 +1218,21 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
     if let ty::Str = ty.value.sty {
         match (a.val, b.val) {
             (
-                ConstValue::ScalarPair(
+                ConstValue::Slice(
                     Scalar::Ptr(ptr_a),
                     len_a,
                 ),
-                ConstValue::ScalarPair(
+                ConstValue::Slice(
                     Scalar::Ptr(ptr_b),
                     len_b,
                 ),
             ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
-                if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
-                    if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
-                        if len_a == len_b {
-                            let map = tcx.alloc_map.lock();
-                            let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
-                            let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
-                            if alloc_a.bytes.len() as u128 == len_a {
-                                return from_bool(alloc_a == alloc_b);
-                            }
-                        }
+                if len_a == len_b {
+                    let map = tcx.alloc_map.lock();
+                    let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
+                    let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
+                    if alloc_a.bytes.len() as u64 == len_a {
+                        return from_bool(alloc_a == alloc_b);
                     }
                 }
             }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 8741571342f..e4bee24c88c 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -555,10 +555,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)
                 ).with_default_tag())
             },
-            ConstValue::ScalarPair(a, b) =>
+            ConstValue::Slice(a, b) =>
                 Ok(Operand::Immediate(Immediate::ScalarPair(
                     a.into(),
-                    b.into(),
+                    Scalar::from_uint(b, self.tcx.data_layout.pointer_size).into(),
                 )).with_default_tag()),
             ConstValue::Scalar(x) =>
                 Ok(Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag()),
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index bc63f8b6ac8..e713ab17c3a 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -1254,12 +1254,7 @@ fn collect_const<'a, 'tcx>(
     debug!("visiting const {:?}", constant);
 
     match constant.val {
-        ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
-            collect_miri(tcx, a.alloc_id, output);
-            collect_miri(tcx, b.alloc_id, output);
-        }
-        ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
-        ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
+        ConstValue::Slice(Scalar::Ptr(ptr), _) |
         ConstValue::Scalar(Scalar::Ptr(ptr)) =>
             collect_miri(tcx, ptr.alloc_id, output),
         ConstValue::ByRef(_id, alloc, _offset) => {