]> git.lizzy.rs Git - rust.git/commitdiff
Go through an allocation when accessing fields of constants
authorOliver Schneider <git-no-reply-9879165716479413131@oli-obk.de>
Mon, 14 May 2018 16:54:24 +0000 (18:54 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Sat, 19 May 2018 12:24:24 +0000 (14:24 +0200)
src/librustc/ich/impls_ty.rs
src/librustc/mir/interpret/value.rs
src/librustc/ty/sty.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/monomorphize/collector.rs
src/test/ui/const-eval/issue-50706.rs [new file with mode: 0644]

index 31dce2a14c2b783869720488634fb89ed4a7ac5a..74b8b816848ac2a1c562504064d8aa1f20ce6a51 100644 (file)
@@ -401,8 +401,9 @@ fn hash_stable<W: StableHasherResult>(&self,
                 a.hash_stable(hcx, hasher);
                 b.hash_stable(hcx, hasher);
             }
-            ByRef(alloc) => {
+            ByRef(alloc, offset) => {
                 alloc.hash_stable(hcx, hasher);
+                offset.hash_stable(hcx, hasher);
             }
         }
     }
index 7bd84a607e714d96bd6c6ab6842f09be8d9b9100..ad076fe681bee3ce93be156424d3ed638faac5f1 100644 (file)
@@ -9,12 +9,12 @@
 /// matches Value's optimizations for easy conversions between these two types
 #[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
 pub enum ConstValue<'tcx> {
-    // Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
+    /// Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
     ByVal(PrimVal),
-    // Used only for types with layout::abi::ScalarPair
+    /// Used only for types with layout::abi::ScalarPair
     ByValPair(PrimVal, PrimVal),
-    // Used only for the remaining cases
-    ByRef(&'tcx Allocation),
+    /// Used only for the remaining cases. An allocation + offset into the allocation
+    ByRef(&'tcx Allocation, u64),
 }
 
 impl<'tcx> ConstValue<'tcx> {
index 4493c668593148614a0ec3f1f9dfca0f7896dacd..0b8f10d311d54af777e8bb62bdae854d7dc74157 100644 (file)
@@ -19,7 +19,7 @@
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
 use util::captures::Captures;
-use mir::interpret::{Allocation, PrimVal, MemoryPointer, Value, ConstValue};
+use mir::interpret::{PrimVal, MemoryPointer, Value, ConstValue};
 
 use std::iter;
 use std::cmp::Ordering;
@@ -1767,15 +1767,6 @@ pub fn from_const_value(
         Self::from_const_val(tcx, ConstVal::Value(val), ty)
     }
 
-    #[inline]
-    pub fn from_alloc(
-        tcx: TyCtxt<'_, '_, 'tcx>,
-        alloc: &'tcx Allocation,
-        ty: Ty<'tcx>,
-    ) -> &'tcx Self {
-        Self::from_const_value(tcx, ConstValue::ByRef(alloc), ty)
-    }
-
     #[inline]
     pub fn from_byval_value(
         tcx: TyCtxt<'_, '_, 'tcx>,
index 66a8b3ca36fb0f1109079c64546912ac1ed46a71..9fd2f1bdd7a33bcade7946ad216fc82481c6e287 100644 (file)
@@ -129,7 +129,7 @@ pub fn codegen_static_initializer<'a, 'tcx>(
     let static_ = cx.tcx.const_eval(param_env.and(cid))?;
 
     let alloc = match static_.val {
-        ConstVal::Value(ConstValue::ByRef(alloc)) => alloc,
+        ConstVal::Value(ConstValue::ByRef(alloc, 0)) => alloc,
         _ => bug!("static const eval returned {:#?}", static_),
     };
     Ok(const_alloc_to_llvm(cx, alloc))
index 62ef58f825504765243bb0d8c59789e628efabb2..f6dc81a4706c0351a453861923f50cd531e4c1ef 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::ValueRef;
+use llvm::{ValueRef, LLVMConstInBoundsGEP};
 use rustc::middle::const_val::ConstEvalErr;
 use rustc::mir;
 use rustc::mir::interpret::ConstValue;
@@ -137,9 +137,15 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
                 );
                 OperandValue::Pair(a_llval, b_llval)
             },
-            ConstValue::ByRef(alloc) => {
+            ConstValue::ByRef(alloc, offset) => {
                 let init = const_alloc_to_llvm(bx.cx, alloc);
-                let llval = consts::addr_of(bx.cx, init, layout.align, "byte_str");
+                let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");
+
+                let llval = unsafe { LLVMConstInBoundsGEP(
+                    consts::bitcast(base_addr, Type::i8p(bx.cx)),
+                    &C_usize(bx.cx, offset),
+                    1,
+                )};
                 let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
                 return Ok(PlaceRef::new_sized(llval, layout, alloc.align).load(bx));
             },
index 239d9a051c6b7026b1278530a82623b7c64b7499..48ab9c8e5dbcdbb285e7c2286a3a79c1283dde54 100644 (file)
@@ -422,22 +422,23 @@ pub fn const_val_field<'a, 'tcx>(
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let result = (|| {
         let value = ecx.const_value_to_value(value, ty)?;
-        let (field, ty) = match value {
-            Value::ByValPair(..) | Value::ByVal(_) => 
-                ecx.read_field(value, variant, field, ty)?.expect("const_val_field on non-field"),
-            Value::ByRef(ptr, align) => {
-                let place = Place::Ptr {
-                    ptr,
-                    align,
-                    extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant),
-                };
-                let layout = ecx.layout_of(ty)?;
-                let (place, layout) = ecx.place_field(place, field, layout)?;
-                let (ptr, align) = place.to_ptr_align();
-                (Value::ByRef(ptr, align), layout.ty)
-            }
+        let layout = ecx.layout_of(ty)?;
+        let (ptr, align) = match value {
+            Value::ByRef(ptr, align) => (ptr, align),
+            Value::ByValPair(..) | Value::ByVal(_) => {
+                let ptr = ecx.alloc_ptr(ty)?.into();
+                ecx.write_value_to_ptr(value, ptr, ty)?;
+                (ptr, layout.align)
+            },
         };
-        Ok(value_to_const_value(&ecx, field, ty))
+        let place = Place::Ptr {
+            ptr,
+            align,
+            extra: variant.map_or(PlaceExtra::None, PlaceExtra::DowncastVariant),
+        };
+        let (place, layout) = ecx.place_field(place, field, layout)?;
+        let (ptr, align) = place.to_ptr_align();
+        Ok((Value::ByRef(ptr, align), layout.ty))
     })();
     result.map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
@@ -478,7 +479,10 @@ pub fn const_value_to_allocation_provider<'a, 'tcx>(
     (val, ty): (ConstValue<'tcx>, Ty<'tcx>),
 ) -> &'tcx Allocation {
     match val {
-        ConstValue::ByRef(alloc) => return alloc,
+        ConstValue::ByRef(alloc, offset) => {
+            assert_eq!(offset, 0);
+            return alloc;
+        },
         _ => ()
     }
     let result = || -> EvalResult<'tcx, &'tcx Allocation> {
index b91a4ba864adeaba18f03c8bd0e492b979976641..1c32c1a9404317428d8bcee33eb1486019d93a3a 100644 (file)
@@ -243,10 +243,10 @@ pub fn const_value_to_value(
         _ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, Value> {
         match val {
-            ConstValue::ByRef(alloc) => {
+            ConstValue::ByRef(alloc, offset) => {
                 // FIXME: Allocate new AllocId for all constants inside
                 let id = self.memory.allocate_value(alloc.clone(), Some(MemoryKind::Stack))?;
-                Ok(Value::ByRef(MemoryPointer::new(id, 0).into(), alloc.align))
+                Ok(Value::ByRef(MemoryPointer::new(id, offset).into(), alloc.align))
             },
             ConstValue::ByValPair(a, b) => Ok(Value::ByValPair(a, b)),
             ConstValue::ByVal(val) => Ok(Value::ByVal(val)),
index c62eb1cf1855fa6e62587f0588b60a8d8e408c8e..100edd6b4ffe5c4b54d763c5d515ce74697dc5c2 100644 (file)
@@ -1249,7 +1249,7 @@ fn collect_const<'a, 'tcx>(
         ConstVal::Value(ConstValue::ByValPair(PrimVal::Ptr(ptr), _)) |
         ConstVal::Value(ConstValue::ByVal(PrimVal::Ptr(ptr))) =>
             collect_miri(tcx, ptr.alloc_id, output),
-        ConstVal::Value(ConstValue::ByRef(alloc)) => {
+        ConstVal::Value(ConstValue::ByRef(alloc, _offset)) => {
             for &id in alloc.relocations.values() {
                 collect_miri(tcx, id, output);
             }
diff --git a/src/test/ui/const-eval/issue-50706.rs b/src/test/ui/const-eval/issue-50706.rs
new file mode 100644 (file)
index 0000000..2b0082d
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+pub struct Stats;
+
+#[derive(PartialEq, Eq)]
+pub struct StatVariant {
+    pub id: u8,
+    _priv: (),
+}
+
+#[derive(PartialEq, Eq)]
+pub struct Stat {
+    pub variant: StatVariant,
+    pub index: usize,
+    _priv: (),
+}
+
+impl Stats {
+    pub const TEST: StatVariant = StatVariant{id: 0, _priv: (),};
+    #[allow(non_upper_case_globals)]
+    pub const A: Stat = Stat{
+         variant: Self::TEST,
+         index: 0,
+         _priv: (),};
+}
+
+impl Stat {
+    pub fn from_index(variant: StatVariant, index: usize) -> Option<Stat> {
+        let stat = Stat{variant, index, _priv: (),};
+        match stat {
+            Stats::A => Some(Stats::A),
+            _ => None,
+        }
+    }
+}
+
+fn main() {}