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);
}
}
}
/// 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> {
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;
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>,
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))
// 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;
);
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));
},
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);
(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> {
_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)),
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);
}
--- /dev/null
+// 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() {}