miri: use separate Pointer and Align instead of PtrAndAlign.
This commit is contained in:
parent
ff080d389d
commit
08646c6c2c
|
@ -10,7 +10,7 @@ mod value;
|
|||
|
||||
pub use self::error::{EvalError, EvalResult, EvalErrorKind};
|
||||
|
||||
pub use self::value::{PrimVal, PrimValKind, Value, Pointer, PtrAndAlign, bytes_to_f32, bytes_to_f64};
|
||||
pub use self::value::{PrimVal, PrimValKind, Value, Pointer, bytes_to_f32, bytes_to_f64};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use ty::layout::HasDataLayout;
|
||||
|
|
|
@ -6,24 +6,6 @@ use super::{EvalResult, MemoryPointer, PointerArithmetic};
|
|||
use syntax::ast::FloatTy;
|
||||
use rustc_const_math::ConstFloat;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PtrAndAlign {
|
||||
pub ptr: Pointer,
|
||||
pub align: Align,
|
||||
}
|
||||
|
||||
impl PtrAndAlign {
|
||||
pub fn to_ptr<'tcx>(self) -> EvalResult<'tcx, MemoryPointer> {
|
||||
self.ptr.to_ptr()
|
||||
}
|
||||
pub fn offset<'tcx, C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
|
||||
Ok(PtrAndAlign {
|
||||
ptr: self.ptr.offset(i, cx)?,
|
||||
align: self.align,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_to_f32(bits: u128) -> ConstFloat {
|
||||
ConstFloat {
|
||||
bits,
|
||||
|
@ -49,7 +31,7 @@ pub fn bytes_to_f64(bits: u128) -> ConstFloat {
|
|||
/// operations and fat pointers. This idea was taken from rustc's trans.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Value {
|
||||
ByRef(PtrAndAlign),
|
||||
ByRef(Pointer, Align),
|
||||
ByVal(PrimVal),
|
||||
ByValPair(PrimVal, PrimVal),
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ use rustc_data_structures::indexed_vec::Idx;
|
|||
use syntax::ast::Mutability;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal, PtrAndAlign};
|
||||
use super::{Place, PlaceExtra, EvalContext, StackPopCleanup, ValTy, HasMemory};
|
||||
use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal};
|
||||
use super::{Place, EvalContext, StackPopCleanup, ValTy};
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
|
@ -357,11 +357,9 @@ pub fn const_eval_provider<'a, 'tcx>(
|
|||
(_, Err(err)) => Err(err),
|
||||
(Ok((miri_val, miri_ty)), Ok(ctfe)) => {
|
||||
let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
|
||||
let miri_ptr = PtrAndAlign {
|
||||
ptr: miri_val,
|
||||
align: ecx.layout_of(miri_ty).unwrap().align
|
||||
};
|
||||
check_ctfe_against_miri(&mut ecx, miri_ptr, miri_ty, ctfe.val);
|
||||
let layout = ecx.layout_of(miri_ty).unwrap();
|
||||
let miri_place = Place::from_primval_ptr(miri_val, layout.align);
|
||||
check_ctfe_against_miri(&mut ecx, miri_place, miri_ty, ctfe.val);
|
||||
Ok(ctfe)
|
||||
}
|
||||
}
|
||||
|
@ -372,19 +370,20 @@ pub fn const_eval_provider<'a, 'tcx>(
|
|||
|
||||
fn check_ctfe_against_miri<'a, 'tcx>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, CompileTimeEvaluator>,
|
||||
miri_val: PtrAndAlign,
|
||||
miri_place: Place,
|
||||
miri_ty: Ty<'tcx>,
|
||||
ctfe: ConstVal<'tcx>,
|
||||
) {
|
||||
use rustc::middle::const_val::ConstAggregate::*;
|
||||
use rustc_const_math::ConstFloat;
|
||||
use rustc::ty::TypeVariants::*;
|
||||
let miri_val = ValTy {
|
||||
value: ecx.read_place(miri_place).unwrap(),
|
||||
ty: miri_ty
|
||||
};
|
||||
match miri_ty.sty {
|
||||
TyInt(int_ty) => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
let prim = get_prim(ecx, value);
|
||||
let prim = get_prim(ecx, miri_val);
|
||||
let c = ConstInt::new_signed_truncating(prim as i128,
|
||||
int_ty,
|
||||
ecx.tcx.sess.target.isize_ty);
|
||||
|
@ -392,10 +391,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
assert_eq!(c, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", c, ctfe);
|
||||
},
|
||||
TyUint(uint_ty) => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
let prim = get_prim(ecx, value);
|
||||
let prim = get_prim(ecx, miri_val);
|
||||
let c = ConstInt::new_unsigned_truncating(prim,
|
||||
uint_ty,
|
||||
ecx.tcx.sess.target.usize_ty);
|
||||
|
@ -403,18 +399,12 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
assert_eq!(c, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", c, ctfe);
|
||||
},
|
||||
TyFloat(ty) => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
let prim = get_prim(ecx, value);
|
||||
let prim = get_prim(ecx, miri_val);
|
||||
let f = ConstVal::Float(ConstFloat { bits: prim, ty });
|
||||
assert_eq!(f, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", f, ctfe);
|
||||
},
|
||||
TyBool => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
let bits = get_prim(ecx, value);
|
||||
let bits = get_prim(ecx, miri_val);
|
||||
if bits > 1 {
|
||||
bug!("miri evaluated to {}, but expected a bool {:?}", bits, ctfe);
|
||||
}
|
||||
|
@ -422,10 +412,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
assert_eq!(b, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", b, ctfe);
|
||||
},
|
||||
TyChar => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
let bits = get_prim(ecx, value);
|
||||
let bits = get_prim(ecx, miri_val);
|
||||
if let Some(cm) = ::std::char::from_u32(bits as u32) {
|
||||
assert_eq!(
|
||||
ConstVal::Char(cm), ctfe,
|
||||
|
@ -436,10 +423,8 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
}
|
||||
},
|
||||
TyStr => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
if let Ok(Some(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len)))) = value {
|
||||
let value = ecx.follow_by_ref_value(miri_val.value, miri_val.ty);
|
||||
if let Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len))) = value {
|
||||
let bytes = ecx
|
||||
.memory
|
||||
.read_bytes(ptr.into(), len as u64)
|
||||
|
@ -463,7 +448,6 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
},
|
||||
TyArray(elem_ty, n) => {
|
||||
let n = n.val.to_const_int().unwrap().to_u64().unwrap();
|
||||
let size = ecx.layout_of(elem_ty).unwrap().size.bytes();
|
||||
let vec: Vec<(ConstVal, Ty<'tcx>)> = match ctfe {
|
||||
ConstVal::ByteStr(arr) => arr.data.iter().map(|&b| {
|
||||
(ConstVal::Integral(ConstInt::U8(b)), ecx.tcx.types.u8)
|
||||
|
@ -476,10 +460,12 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
},
|
||||
_ => bug!("miri produced {:?}, but ctfe yielded {:?}", miri_ty, ctfe),
|
||||
};
|
||||
let layout = ecx.layout_of(miri_ty).unwrap();
|
||||
for (i, elem) in vec.into_iter().enumerate() {
|
||||
assert!((i as u64) < n);
|
||||
let ptr = miri_val.offset(size * i as u64, &ecx).unwrap();
|
||||
check_ctfe_against_miri(ecx, ptr, elem_ty, elem.0);
|
||||
let (field_place, _) =
|
||||
ecx.place_field(miri_place, Field::new(i), layout).unwrap();
|
||||
check_ctfe_against_miri(ecx, field_place, elem_ty, elem.0);
|
||||
}
|
||||
},
|
||||
TyTuple(..) => {
|
||||
|
@ -489,22 +475,22 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
};
|
||||
let layout = ecx.layout_of(miri_ty).unwrap();
|
||||
for (i, elem) in vec.into_iter().enumerate() {
|
||||
let offset = layout.fields.offset(i);
|
||||
let ptr = miri_val.offset(offset.bytes(), &ecx).unwrap();
|
||||
check_ctfe_against_miri(ecx, ptr, elem.ty, elem.val);
|
||||
let (field_place, _) =
|
||||
ecx.place_field(miri_place, Field::new(i), layout).unwrap();
|
||||
check_ctfe_against_miri(ecx, field_place, elem.ty, elem.val);
|
||||
}
|
||||
},
|
||||
TyAdt(def, _) => {
|
||||
let (struct_variant, extra) = if def.is_enum() {
|
||||
let discr = ecx.read_discriminant_value(
|
||||
Place::Ptr { ptr: miri_val, extra: PlaceExtra::None },
|
||||
miri_ty).unwrap();
|
||||
let mut miri_place = miri_place;
|
||||
let struct_variant = if def.is_enum() {
|
||||
let discr = ecx.read_discriminant_value(miri_place, miri_ty).unwrap();
|
||||
let variant = def.discriminants(ecx.tcx).position(|variant_discr| {
|
||||
variant_discr.to_u128_unchecked() == discr
|
||||
}).expect("miri produced invalid enum discriminant");
|
||||
(&def.variants[variant], PlaceExtra::DowncastVariant(variant))
|
||||
miri_place = ecx.place_downcast(miri_place, variant).unwrap();
|
||||
&def.variants[variant]
|
||||
} else {
|
||||
(def.struct_variant(), PlaceExtra::None)
|
||||
def.struct_variant()
|
||||
};
|
||||
let vec = match ctfe {
|
||||
ConstVal::Aggregate(Struct(v)) => v,
|
||||
|
@ -518,12 +504,9 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
let layout = ecx.layout_of(miri_ty).unwrap();
|
||||
for &(name, elem) in vec.into_iter() {
|
||||
let field = struct_variant.fields.iter().position(|f| f.name == name).unwrap();
|
||||
let (place, _) = ecx.place_field(
|
||||
Place::Ptr { ptr: miri_val, extra },
|
||||
Field::new(field),
|
||||
layout,
|
||||
).unwrap();
|
||||
check_ctfe_against_miri(ecx, place.to_ptr_align(), elem.ty, elem.val);
|
||||
let (field_place, _) =
|
||||
ecx.place_field(miri_place, Field::new(field), layout).unwrap();
|
||||
check_ctfe_against_miri(ecx, field_place, elem.ty, elem.val);
|
||||
}
|
||||
},
|
||||
TySlice(_) => bug!("miri produced a slice?"),
|
||||
|
@ -543,11 +526,9 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
// should be fine
|
||||
TyFnDef(..) => {}
|
||||
TyFnPtr(_) => {
|
||||
let value = ecx.read_with_align(miri_val.align, |ectx| {
|
||||
ectx.try_read_value(miri_val.ptr, miri_ty)
|
||||
});
|
||||
let value = ecx.value_to_primval(miri_val);
|
||||
let ptr = match value {
|
||||
Ok(Some(Value::ByVal(PrimVal::Ptr(ptr)))) => ptr,
|
||||
Ok(PrimVal::Ptr(ptr)) => ptr,
|
||||
value => bug!("expected fn ptr, got {:?}", value),
|
||||
};
|
||||
let inst = ecx.memory.get_fn(ptr).unwrap();
|
||||
|
@ -569,13 +550,10 @@ fn check_ctfe_against_miri<'a, 'tcx>(
|
|||
|
||||
fn get_prim<'a, 'tcx>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, CompileTimeEvaluator>,
|
||||
res: Result<Option<Value>, EvalError<'tcx>>,
|
||||
val: ValTy<'tcx>,
|
||||
) -> u128 {
|
||||
match res {
|
||||
Ok(Some(Value::ByVal(prim))) => unwrap_miri(ecx, prim.to_bytes()),
|
||||
Err(err) => unwrap_miri(ecx, Err(err)),
|
||||
val => bug!("got {:?}", val),
|
||||
}
|
||||
let res = ecx.value_to_primval(val).and_then(|prim| prim.to_bytes());
|
||||
unwrap_miri(ecx, res)
|
||||
}
|
||||
|
||||
fn unwrap_miri<'a, 'tcx, T>(
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_data_structures::indexed_vec::Idx;
|
|||
use syntax::codemap::{self, DUMMY_SP};
|
||||
use syntax::ast::Mutability;
|
||||
use rustc::mir::interpret::{
|
||||
PtrAndAlign, GlobalId, Value, Pointer, PrimVal, PrimValKind,
|
||||
GlobalId, Value, Pointer, PrimVal, PrimValKind,
|
||||
EvalError, EvalResult, EvalErrorKind, MemoryPointer,
|
||||
};
|
||||
|
||||
|
@ -498,7 +498,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
}
|
||||
|
||||
pub fn deallocate_local(&mut self, local: Option<Value>) -> EvalResult<'tcx> {
|
||||
if let Some(Value::ByRef(ptr)) = local {
|
||||
if let Some(Value::ByRef(ptr, _align)) = local {
|
||||
trace!("deallocating local");
|
||||
let ptr = ptr.to_ptr()?;
|
||||
self.memory.dump_alloc(ptr.alloc_id);
|
||||
|
@ -637,12 +637,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
let src = self.eval_place(place)?;
|
||||
// We ignore the alignment of the place here -- special handling for packed structs ends
|
||||
// at the `&` operator.
|
||||
let (ptr, extra) = self.force_allocation(src)?.to_ptr_align_extra();
|
||||
let (ptr, _align, extra) = self.force_allocation(src)?.to_ptr_align_extra();
|
||||
|
||||
let val = match extra {
|
||||
PlaceExtra::None => ptr.ptr.to_value(),
|
||||
PlaceExtra::Length(len) => ptr.ptr.to_value_with_len(len),
|
||||
PlaceExtra::Vtable(vtable) => ptr.ptr.to_value_with_vtable(vtable),
|
||||
PlaceExtra::None => ptr.to_value(),
|
||||
PlaceExtra::Length(len) => ptr.to_value_with_len(len),
|
||||
PlaceExtra::Vtable(vtable) => ptr.to_value_with_vtable(vtable),
|
||||
PlaceExtra::DowncastVariant(..) => {
|
||||
bug!("attempted to take a reference to an enum downcast place")
|
||||
}
|
||||
|
@ -951,10 +951,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
}
|
||||
|
||||
pub fn read_global_as_value(&self, gid: GlobalId, layout: TyLayout) -> Value {
|
||||
Value::ByRef(PtrAndAlign {
|
||||
ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
|
||||
align: layout.align
|
||||
})
|
||||
Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
|
||||
layout.align)
|
||||
}
|
||||
|
||||
fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx> {
|
||||
|
@ -972,9 +970,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
// -1 since we don't store the return value
|
||||
match self.stack[frame].locals[local.index() - 1] {
|
||||
None => return err!(DeadLocal),
|
||||
Some(Value::ByRef(ptr)) => {
|
||||
Some(Value::ByRef(ptr, align)) => {
|
||||
Place::Ptr {
|
||||
ptr,
|
||||
align,
|
||||
extra: PlaceExtra::None,
|
||||
}
|
||||
}
|
||||
|
@ -984,10 +983,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
let layout = self.layout_of(ty)?;
|
||||
let ptr = self.alloc_ptr(ty)?;
|
||||
self.stack[frame].locals[local.index() - 1] =
|
||||
Some(Value::ByRef(PtrAndAlign {
|
||||
ptr: ptr.into(),
|
||||
align: layout.align
|
||||
})); // it stays live
|
||||
Some(Value::ByRef(ptr.into(), layout.align)); // it stays live
|
||||
self.write_value_to_ptr(val, ptr.into(), ty)?;
|
||||
Place::from_ptr(ptr, layout.align)
|
||||
}
|
||||
|
@ -1005,7 +1001,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
ty: Ty<'tcx>,
|
||||
) -> EvalResult<'tcx, Value> {
|
||||
match value {
|
||||
Value::ByRef(PtrAndAlign { ptr, align }) => {
|
||||
Value::ByRef(ptr, align) => {
|
||||
self.read_with_align(align, |ectx| ectx.read_value(ptr, ty))
|
||||
}
|
||||
other => Ok(other),
|
||||
|
@ -1061,10 +1057,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
// correct if we never look at this data with the wrong type.
|
||||
|
||||
match dest {
|
||||
Place::Ptr {
|
||||
ptr: PtrAndAlign { ptr, align },
|
||||
extra,
|
||||
} => {
|
||||
Place::Ptr { ptr, align, extra } => {
|
||||
assert_eq!(extra, PlaceExtra::None);
|
||||
self.write_with_align_mut(align,
|
||||
|ectx| ectx.write_value_to_ptr(src_val, ptr, dest_ty))
|
||||
|
@ -1090,11 +1083,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
old_dest_val: Value,
|
||||
dest_ty: Ty<'tcx>,
|
||||
) -> EvalResult<'tcx> {
|
||||
if let Value::ByRef(PtrAndAlign {
|
||||
ptr: dest_ptr,
|
||||
align,
|
||||
}) = old_dest_val
|
||||
{
|
||||
if let Value::ByRef(dest_ptr, align) = old_dest_val {
|
||||
// If the value is already `ByRef` (that is, backed by an `Allocation`),
|
||||
// then we must write the new value into this allocation, because there may be
|
||||
// other pointers into the allocation. These other pointers are logically
|
||||
|
@ -1106,11 +1095,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
ectx.write_value_to_ptr(src_val, dest_ptr, dest_ty)
|
||||
})?;
|
||||
|
||||
} else if let Value::ByRef(PtrAndAlign {
|
||||
ptr: src_ptr,
|
||||
align,
|
||||
}) = src_val
|
||||
{
|
||||
} else if let Value::ByRef(src_ptr, align) = src_val {
|
||||
// If the value is not `ByRef`, then we know there are no pointers to it
|
||||
// and we can simply overwrite the `Value` in the locals array directly.
|
||||
//
|
||||
|
@ -1129,10 +1114,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
let dest_ptr = ectx.alloc_ptr(dest_ty)?.into();
|
||||
ectx.copy(src_ptr, dest_ptr, dest_ty)?;
|
||||
let layout = ectx.layout_of(dest_ty)?;
|
||||
write_dest(ectx, Value::ByRef(PtrAndAlign {
|
||||
ptr: dest_ptr,
|
||||
align: layout.align
|
||||
}))?;
|
||||
write_dest(ectx, Value::ByRef(dest_ptr, layout.align))?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
@ -1153,7 +1135,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
) -> EvalResult<'tcx> {
|
||||
trace!("write_value_to_ptr: {:#?}", value);
|
||||
match value {
|
||||
Value::ByRef(PtrAndAlign { ptr, align }) => {
|
||||
Value::ByRef(ptr, align) => {
|
||||
self.read_with_align_mut(align, |ectx| ectx.copy(ptr, dest, dest_ty))
|
||||
}
|
||||
Value::ByVal(primval) => {
|
||||
|
@ -1485,7 +1467,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
continue;
|
||||
}
|
||||
let (src_f_value, src_field) = match src {
|
||||
Value::ByRef(PtrAndAlign { ptr, align }) => {
|
||||
Value::ByRef(ptr, align) => {
|
||||
let src_place = Place::from_primval_ptr(ptr, align);
|
||||
let (src_f_place, src_field) =
|
||||
self.place_field(src_place, mir::Field::new(i), src_layout)?;
|
||||
|
@ -1537,7 +1519,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
Err(err) => {
|
||||
panic!("Failed to access local: {:?}", err);
|
||||
}
|
||||
Ok(Value::ByRef(PtrAndAlign { ptr, align })) => {
|
||||
Ok(Value::ByRef(ptr, align)) => {
|
||||
match ptr.into_inner_primval() {
|
||||
PrimVal::Ptr(ptr) => {
|
||||
write!(msg, " by align({}) ref:", align.abi()).unwrap();
|
||||
|
@ -1566,7 +1548,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
trace!("{}", msg);
|
||||
self.memory.dump_allocs(allocs);
|
||||
}
|
||||
Place::Ptr { ptr: PtrAndAlign { ptr, align }, .. } => {
|
||||
Place::Ptr { ptr, align, .. } => {
|
||||
match ptr.into_inner_primval() {
|
||||
PrimVal::Ptr(ptr) => {
|
||||
trace!("by align({}) ref:", align.abi());
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc::ty::{Instance, TyCtxt};
|
|||
use rustc::ty::layout::{self, Align, TargetDataLayout};
|
||||
use syntax::ast::Mutability;
|
||||
|
||||
use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, PtrAndAlign, Value, Pointer,
|
||||
use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, Value, Pointer,
|
||||
EvalResult, PrimVal, EvalErrorKind};
|
||||
|
||||
use super::{EvalContext, Machine};
|
||||
|
@ -1046,7 +1046,7 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
|
|||
value: Value,
|
||||
) -> EvalResult<'tcx, Pointer> {
|
||||
Ok(match value {
|
||||
Value::ByRef(PtrAndAlign { ptr, align }) => {
|
||||
Value::ByRef(ptr, align) => {
|
||||
self.memory().read_with_align(align, |mem| mem.read_ptr_sized_unsigned(ptr.to_ptr()?))?
|
||||
}
|
||||
Value::ByVal(ptr) |
|
||||
|
@ -1059,10 +1059,7 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
|
|||
value: Value,
|
||||
) -> EvalResult<'tcx, (Pointer, MemoryPointer)> {
|
||||
match value {
|
||||
Value::ByRef(PtrAndAlign {
|
||||
ptr: ref_ptr,
|
||||
align,
|
||||
}) => {
|
||||
Value::ByRef(ref_ptr, align) => {
|
||||
self.memory().read_with_align(align, |mem| {
|
||||
let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into();
|
||||
let vtable = mem.read_ptr_sized_unsigned(
|
||||
|
@ -1084,10 +1081,7 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
|
|||
value: Value,
|
||||
) -> EvalResult<'tcx, (Pointer, u64)> {
|
||||
match value {
|
||||
Value::ByRef(PtrAndAlign {
|
||||
ptr: ref_ptr,
|
||||
align,
|
||||
}) => {
|
||||
Value::ByRef(ref_ptr, align) => {
|
||||
self.memory().read_with_align(align, |mem| {
|
||||
let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into();
|
||||
let len = mem.read_ptr_sized_unsigned(
|
||||
|
|
|
@ -2,9 +2,8 @@ use rustc::mir;
|
|||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc::mir::interpret::{GlobalId, PtrAndAlign};
|
||||
|
||||
use rustc::mir::interpret::{Value, PrimVal, EvalResult, Pointer, MemoryPointer};
|
||||
use rustc::mir::interpret::{GlobalId, Value, PrimVal, EvalResult, Pointer, MemoryPointer};
|
||||
use super::{EvalContext, Machine, ValTy};
|
||||
use interpret::memory::HasMemory;
|
||||
|
||||
|
@ -15,7 +14,8 @@ pub enum Place {
|
|||
/// An place may have an invalid (integral or undef) pointer,
|
||||
/// since it might be turned back into a reference
|
||||
/// before ever being dereferenced.
|
||||
ptr: PtrAndAlign,
|
||||
ptr: Pointer,
|
||||
align: Align,
|
||||
extra: PlaceExtra,
|
||||
},
|
||||
|
||||
|
@ -40,7 +40,8 @@ impl<'tcx> Place {
|
|||
|
||||
pub fn from_primval_ptr(ptr: Pointer, align: Align) -> Self {
|
||||
Place::Ptr {
|
||||
ptr: PtrAndAlign { ptr, align },
|
||||
ptr,
|
||||
align,
|
||||
extra: PlaceExtra::None,
|
||||
}
|
||||
}
|
||||
|
@ -49,23 +50,23 @@ impl<'tcx> Place {
|
|||
Self::from_primval_ptr(ptr.into(), align)
|
||||
}
|
||||
|
||||
pub fn to_ptr_align_extra(self) -> (PtrAndAlign, PlaceExtra) {
|
||||
pub fn to_ptr_align_extra(self) -> (Pointer, Align, PlaceExtra) {
|
||||
match self {
|
||||
Place::Ptr { ptr, extra } => (ptr, extra),
|
||||
Place::Ptr { ptr, align, extra } => (ptr, align, extra),
|
||||
_ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_ptr_align(self) -> PtrAndAlign {
|
||||
let (ptr, _extra) = self.to_ptr_align_extra();
|
||||
ptr
|
||||
pub fn to_ptr_align(self) -> (Pointer, Align) {
|
||||
let (ptr, align, _extra) = self.to_ptr_align_extra();
|
||||
(ptr, align)
|
||||
}
|
||||
|
||||
pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
|
||||
// At this point, we forget about the alignment information -- the place has been turned into a reference,
|
||||
// and no matter where it came from, it now must be aligned.
|
||||
self.to_ptr_align().to_ptr()
|
||||
self.to_ptr_align().0.to_ptr()
|
||||
}
|
||||
|
||||
pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
|
||||
|
@ -169,9 +170,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
|
||||
pub fn read_place(&self, place: Place) -> EvalResult<'tcx, Value> {
|
||||
match place {
|
||||
Place::Ptr { ptr, extra } => {
|
||||
Place::Ptr { ptr, align, extra } => {
|
||||
assert_eq!(extra, PlaceExtra::None);
|
||||
Ok(Value::ByRef(ptr))
|
||||
Ok(Value::ByRef(ptr, align))
|
||||
}
|
||||
Place::Local { frame, local } => self.stack[frame].get_local(local),
|
||||
}
|
||||
|
@ -194,10 +195,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
};
|
||||
let layout = self.layout_of(self.place_ty(mir_place))?;
|
||||
Place::Ptr {
|
||||
ptr: PtrAndAlign {
|
||||
ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
|
||||
align: layout.align
|
||||
},
|
||||
align: layout.align,
|
||||
extra: PlaceExtra::None,
|
||||
}
|
||||
}
|
||||
|
@ -233,8 +232,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
let offset = base_layout.fields.offset(field_index);
|
||||
|
||||
// Do not allocate in trivial cases
|
||||
let (base_ptr, base_extra) = match base {
|
||||
Place::Ptr { ptr, extra } => (ptr, extra),
|
||||
let (base_ptr, base_align, base_extra) = match base {
|
||||
Place::Ptr { ptr, align, extra } => (ptr, align, extra),
|
||||
Place::Local { frame, local } => {
|
||||
match (&self.stack[frame].get_local(local)?, &base_layout.abi) {
|
||||
// in case the field covers the entire type, just return the value
|
||||
|
@ -253,16 +252,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
PlaceExtra::Vtable(tab) => {
|
||||
let (_, align) = self.size_and_align_of_dst(
|
||||
base_layout.ty,
|
||||
base_ptr.ptr.to_value_with_vtable(tab),
|
||||
base_ptr.to_value_with_vtable(tab),
|
||||
)?;
|
||||
offset.abi_align(align).bytes()
|
||||
}
|
||||
_ => offset.bytes(),
|
||||
};
|
||||
|
||||
let mut ptr = base_ptr.offset(offset, &self)?;
|
||||
ptr.align = ptr.align.min(base_layout.align).min(field.align);
|
||||
|
||||
let ptr = base_ptr.offset(offset, &self)?;
|
||||
let align = base_align.min(base_layout.align).min(field.align);
|
||||
let extra = if !field.is_unsized() {
|
||||
PlaceExtra::None
|
||||
} else {
|
||||
|
@ -277,7 +275,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
base_extra
|
||||
};
|
||||
|
||||
Ok((Place::Ptr { ptr, extra }, field))
|
||||
Ok((Place::Ptr { ptr, align, extra }, field))
|
||||
}
|
||||
|
||||
pub fn val_to_place(&self, val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Place> {
|
||||
|
@ -286,14 +284,16 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
ty::TyDynamic(..) => {
|
||||
let (ptr, vtable) = self.into_ptr_vtable_pair(val)?;
|
||||
Place::Ptr {
|
||||
ptr: PtrAndAlign { ptr, align: layout.align },
|
||||
ptr,
|
||||
align: layout.align,
|
||||
extra: PlaceExtra::Vtable(vtable),
|
||||
}
|
||||
}
|
||||
ty::TyStr | ty::TySlice(_) => {
|
||||
let (ptr, len) = self.into_slice(val)?;
|
||||
Place::Ptr {
|
||||
ptr: PtrAndAlign { ptr, align: layout.align },
|
||||
ptr,
|
||||
align: layout.align,
|
||||
extra: PlaceExtra::Length(len),
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
) -> EvalResult<'tcx, Place> {
|
||||
// Taking the outer type here may seem odd; it's needed because for array types, the outer type gives away the length.
|
||||
let base = self.force_allocation(base)?;
|
||||
let base_ptr = base.to_ptr_align();
|
||||
let (base_ptr, align) = base.to_ptr_align();
|
||||
|
||||
let (elem_ty, len) = base.elem_ty_and_len(outer_ty);
|
||||
let elem_size = self.layout_of(elem_ty)?.size.bytes();
|
||||
|
@ -322,6 +322,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
let ptr = base_ptr.offset(n * elem_size, &*self)?;
|
||||
Ok(Place::Ptr {
|
||||
ptr,
|
||||
align,
|
||||
extra: PlaceExtra::None,
|
||||
})
|
||||
}
|
||||
|
@ -333,9 +334,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
) -> EvalResult<'tcx, Place> {
|
||||
// FIXME(solson)
|
||||
let base = self.force_allocation(base)?;
|
||||
let ptr = base.to_ptr_align();
|
||||
let (ptr, align) = base.to_ptr_align();
|
||||
let extra = PlaceExtra::DowncastVariant(variant);
|
||||
Ok(Place::Ptr { ptr, extra })
|
||||
Ok(Place::Ptr { ptr, align, extra })
|
||||
}
|
||||
|
||||
pub fn eval_place_projection(
|
||||
|
@ -345,14 +346,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
|
||||
) -> EvalResult<'tcx, Place> {
|
||||
use rustc::mir::ProjectionElem::*;
|
||||
let (ptr, extra) = match *proj_elem {
|
||||
match *proj_elem {
|
||||
Field(field, _) => {
|
||||
let layout = self.layout_of(base_ty)?;
|
||||
return Ok(self.place_field(base, field, layout)?.0);
|
||||
Ok(self.place_field(base, field, layout)?.0)
|
||||
}
|
||||
|
||||
Downcast(_, variant) => {
|
||||
return self.place_downcast(base, variant);
|
||||
self.place_downcast(base, variant)
|
||||
}
|
||||
|
||||
Deref => {
|
||||
|
@ -367,14 +368,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
|
||||
trace!("deref to {} on {:?}", pointee_type, val);
|
||||
|
||||
return self.val_to_place(val, pointee_type);
|
||||
self.val_to_place(val, pointee_type)
|
||||
}
|
||||
|
||||
Index(local) => {
|
||||
let value = self.frame().get_local(local)?;
|
||||
let ty = self.tcx.types.usize;
|
||||
let n = self.value_to_primval(ValTy { value, ty })?.to_u64()?;
|
||||
return self.place_index(base, base_ty, n);
|
||||
self.place_index(base, base_ty, n)
|
||||
}
|
||||
|
||||
ConstantIndex {
|
||||
|
@ -384,7 +385,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
} => {
|
||||
// FIXME(solson)
|
||||
let base = self.force_allocation(base)?;
|
||||
let base_ptr = base.to_ptr_align();
|
||||
let (base_ptr, align) = base.to_ptr_align();
|
||||
|
||||
let (elem_ty, n) = base.elem_ty_and_len(base_ty);
|
||||
let elem_size = self.layout_of(elem_ty)?.size.bytes();
|
||||
|
@ -397,13 +398,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
};
|
||||
|
||||
let ptr = base_ptr.offset(index * elem_size, &self)?;
|
||||
(ptr, PlaceExtra::None)
|
||||
Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None })
|
||||
}
|
||||
|
||||
Subslice { from, to } => {
|
||||
// FIXME(solson)
|
||||
let base = self.force_allocation(base)?;
|
||||
let base_ptr = base.to_ptr_align();
|
||||
let (base_ptr, align) = base.to_ptr_align();
|
||||
|
||||
let (elem_ty, n) = base.elem_ty_and_len(base_ty);
|
||||
let elem_size = self.layout_of(elem_ty)?.size.bytes();
|
||||
|
@ -415,11 +416,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
} else {
|
||||
PlaceExtra::Length(n - u64::from(to) - u64::from(from))
|
||||
};
|
||||
(ptr, extra)
|
||||
Ok(Place::Ptr { ptr, align, extra })
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Place::Ptr { ptr, extra })
|
||||
}
|
||||
|
||||
pub fn place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
|
||||
|
|
|
@ -21,16 +21,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
let val = match self.force_allocation(place)? {
|
||||
Place::Ptr {
|
||||
ptr,
|
||||
align: _,
|
||||
extra: PlaceExtra::Vtable(vtable),
|
||||
} => ptr.ptr.to_value_with_vtable(vtable),
|
||||
} => ptr.to_value_with_vtable(vtable),
|
||||
Place::Ptr {
|
||||
ptr,
|
||||
align: _,
|
||||
extra: PlaceExtra::Length(len),
|
||||
} => ptr.ptr.to_value_with_len(len),
|
||||
} => ptr.to_value_with_len(len),
|
||||
Place::Ptr {
|
||||
ptr,
|
||||
align: _,
|
||||
extra: PlaceExtra::None,
|
||||
} => ptr.ptr.to_value(),
|
||||
} => ptr.to_value(),
|
||||
_ => bug!("force_allocation broken"),
|
||||
};
|
||||
self.drop(val, instance, ty, span, target)
|
||||
|
|
|
@ -4,7 +4,7 @@ use rustc::ty::layout::LayoutOf;
|
|||
use syntax::codemap::Span;
|
||||
use syntax::abi::Abi;
|
||||
|
||||
use rustc::mir::interpret::{PtrAndAlign, EvalResult, PrimVal, Value};
|
||||
use rustc::mir::interpret::{EvalResult, PrimVal, Value};
|
||||
use super::{EvalContext, eval_context,
|
||||
Place, Machine, ValTy};
|
||||
|
||||
|
@ -327,14 +327,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
if let ty::TyTuple(..) = args[1].ty.sty {
|
||||
if self.frame().mir.args_iter().count() == layout.fields.count() + 1 {
|
||||
match args[1].value {
|
||||
Value::ByRef(PtrAndAlign { ptr, align }) => {
|
||||
Value::ByRef(ptr, align) => {
|
||||
for (i, arg_local) in arg_locals.enumerate() {
|
||||
let field = layout.field(&self, i)?;
|
||||
let offset = layout.fields.offset(i).bytes();
|
||||
let arg = Value::ByRef(PtrAndAlign {
|
||||
ptr: ptr.offset(offset, &self)?,
|
||||
align: align.min(field.align)
|
||||
});
|
||||
let arg = Value::ByRef(ptr.offset(offset, &self)?,
|
||||
align.min(field.align));
|
||||
let dest =
|
||||
self.eval_place(&mir::Place::Local(arg_local))?;
|
||||
trace!(
|
||||
|
|
Loading…
Reference in New Issue