1
Fork 0

Eliminate the Pointer wrapper type

This commit is contained in:
Oliver Schneider 2018-05-21 00:30:00 +02:00
parent 6436de89fe
commit 03a92b61ec
13 changed files with 74 additions and 107 deletions

View file

@ -473,8 +473,6 @@ impl_stable_hash_for!(enum ::syntax::ast::Mutability {
Mutable Mutable
}); });
impl_stable_hash_for!(struct mir::interpret::Pointer{primval});
impl_stable_hash_for!(enum mir::interpret::Scalar { impl_stable_hash_for!(enum mir::interpret::Scalar {
Bytes(b), Bytes(b),
Ptr(p), Ptr(p),

View file

@ -10,7 +10,7 @@ mod value;
pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage}; pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
pub use self::value::{Scalar, ScalarKind, Value, Pointer, ConstValue}; pub use self::value::{Scalar, ScalarKind, Value, ConstValue};
use std::fmt; use std::fmt;
use mir; use mir;

View file

@ -78,7 +78,7 @@ impl<'tcx> ConstValue<'tcx> {
/// operations and fat pointers. This idea was taken from rustc's codegen. /// operations and fat pointers. This idea was taken from rustc's codegen.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
pub enum Value { pub enum Value {
ByRef(Pointer, Align), ByRef(Scalar, Align),
Scalar(Scalar), Scalar(Scalar),
ScalarPair(Scalar, Scalar), ScalarPair(Scalar, Scalar),
} }
@ -92,73 +92,49 @@ impl<'tcx> ty::TypeFoldable<'tcx> for Value {
} }
} }
/// A wrapper type around `Scalar` that cannot be turned back into a `Scalar` accidentally. impl<'tcx> Scalar {
/// This type clears up a few APIs where having a `Scalar` argument for something that is pub fn ptr_null() -> Self {
/// potentially an integer pointer or a pointer to an allocation was unclear. Scalar::Bytes(0)
///
/// I (@oli-obk) believe it is less easy to mix up generic primvals and primvals that are just
/// the representation of pointers. Also all the sites that convert between primvals and pointers
/// are explicit now (and rare!)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
pub struct Pointer {
pub primval: Scalar,
}
impl<'tcx> Pointer {
pub fn null() -> Self {
Scalar::Bytes(0).into()
}
pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
self.primval.to_ptr()
}
pub fn into_inner_primval(self) -> Scalar {
self.primval
} }
pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> { pub fn ptr_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
let layout = cx.data_layout(); let layout = cx.data_layout();
match self.primval { match self {
Scalar::Bytes(b) => { Scalar::Bytes(b) => {
assert_eq!(b as u64 as u128, b); assert_eq!(b as u64 as u128, b);
Ok(Pointer::from( Ok(Scalar::Bytes(layout.signed_offset(b as u64, i)? as u128))
Scalar::Bytes(layout.signed_offset(b as u64, i)? as u128),
))
} }
Scalar::Ptr(ptr) => ptr.signed_offset(i, layout).map(Pointer::from), Scalar::Ptr(ptr) => ptr.signed_offset(i, layout).map(Scalar::Ptr),
Scalar::Undef => err!(ReadUndefBytes), Scalar::Undef => err!(ReadUndefBytes),
} }
} }
pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> { pub fn ptr_offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
let layout = cx.data_layout(); let layout = cx.data_layout();
match self.primval { match self {
Scalar::Bytes(b) => { Scalar::Bytes(b) => {
assert_eq!(b as u64 as u128, b); assert_eq!(b as u64 as u128, b);
Ok(Pointer::from( Ok(Scalar::Bytes(layout.offset(b as u64, i.bytes())? as u128))
Scalar::Bytes(layout.offset(b as u64, i.bytes())? as u128),
))
} }
Scalar::Ptr(ptr) => ptr.offset(i, layout).map(Pointer::from), Scalar::Ptr(ptr) => ptr.offset(i, layout).map(Scalar::Ptr),
Scalar::Undef => err!(ReadUndefBytes), Scalar::Undef => err!(ReadUndefBytes),
} }
} }
pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> { pub fn ptr_wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
let layout = cx.data_layout(); let layout = cx.data_layout();
match self.primval { match self {
Scalar::Bytes(b) => { Scalar::Bytes(b) => {
assert_eq!(b as u64 as u128, b); assert_eq!(b as u64 as u128, b);
Ok(Pointer::from(Scalar::Bytes( Ok(Scalar::Bytes(layout.wrapping_signed_offset(b as u64, i) as u128))
layout.wrapping_signed_offset(b as u64, i) as u128,
)))
} }
Scalar::Ptr(ptr) => Ok(Pointer::from(ptr.wrapping_signed_offset(i, layout))), Scalar::Ptr(ptr) => Ok(Scalar::Ptr(ptr.wrapping_signed_offset(i, layout))),
Scalar::Undef => err!(ReadUndefBytes), Scalar::Undef => err!(ReadUndefBytes),
} }
} }
pub fn is_null(self) -> EvalResult<'tcx, bool> { pub fn is_null(self) -> EvalResult<'tcx, bool> {
match self.primval { match self {
Scalar::Bytes(b) => Ok(b == 0), Scalar::Bytes(b) => Ok(b == 0),
Scalar::Ptr(_) => Ok(false), Scalar::Ptr(_) => Ok(false),
Scalar::Undef => err!(ReadUndefBytes), Scalar::Undef => err!(ReadUndefBytes),
@ -166,27 +142,21 @@ impl<'tcx> Pointer {
} }
pub fn to_value_with_len(self, len: u64) -> Value { pub fn to_value_with_len(self, len: u64) -> Value {
Value::ScalarPair(self.primval, Scalar::from_u128(len as u128)) Value::ScalarPair(self, Scalar::from_u128(len as u128))
} }
pub fn to_value_with_vtable(self, vtable: MemoryPointer) -> Value { pub fn to_value_with_vtable(self, vtable: MemoryPointer) -> Value {
Value::ScalarPair(self.primval, Scalar::Ptr(vtable)) Value::ScalarPair(self, Scalar::Ptr(vtable))
} }
pub fn to_value(self) -> Value { pub fn to_value(self) -> Value {
Value::Scalar(self.primval) Value::Scalar(self)
} }
} }
impl ::std::convert::From<Scalar> for Pointer { impl From<MemoryPointer> for Scalar {
fn from(primval: Scalar) -> Self {
Pointer { primval }
}
}
impl ::std::convert::From<MemoryPointer> for Pointer {
fn from(ptr: MemoryPointer) -> Self { fn from(ptr: MemoryPointer) -> Self {
Scalar::Ptr(ptr).into() Scalar::Ptr(ptr)
} }
} }

View file

@ -96,7 +96,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
).expect("const_alloc_to_llvm: could not read relocation pointer") as u64; ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
llvals.push(primval_to_llvm( llvals.push(primval_to_llvm(
cx, cx,
Scalar::Ptr(MemoryPointer { alloc_id, offset: Size::from_bytes(ptr_offset) }), MemoryPointer { alloc_id, offset: Size::from_bytes(ptr_offset) }.into(),
&layout::Scalar { &layout::Scalar {
value: layout::Primitive::Pointer, value: layout::Primitive::Pointer,
valid_range: 0..=!0 valid_range: 0..=!0

View file

@ -191,7 +191,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
LitKind::ByteStr(ref data) => { LitKind::ByteStr(ref data) => {
let id = self.tcx.allocate_bytes(data); let id = self.tcx.allocate_bytes(data);
let ptr = MemoryPointer::zero(id); let ptr = MemoryPointer::zero(id);
ConstValue::Scalar(Scalar::Ptr(ptr)) ConstValue::Scalar(ptr.into())
}, },
LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bytes(n as u128)), LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bytes(n as u128)),
LitKind::Int(n, _) if neg => { LitKind::Int(n, _) if neg => {

View file

@ -1137,7 +1137,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
LitKind::ByteStr(ref data) => { LitKind::ByteStr(ref data) => {
let id = tcx.allocate_bytes(data); let id = tcx.allocate_bytes(data);
let ptr = MemoryPointer::zero(id); let ptr = MemoryPointer::zero(id);
ConstValue::Scalar(Scalar::Ptr(ptr)) ConstValue::Scalar(ptr.into())
}, },
LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bytes(n as u128)), LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bytes(n as u128)),
LitKind::Int(n, _) => { LitKind::Int(n, _) => {

View file

@ -107,7 +107,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
// Casting to a reference or fn pointer is not permitted by rustc, no need to support it here. // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
TyRawPtr(_) | TyRawPtr(_) |
TyInt(IntTy::Isize) | TyInt(IntTy::Isize) |
TyUint(UintTy::Usize) => Ok(Scalar::Ptr(ptr)), TyUint(UintTy::Usize) => Ok(ptr.into()),
TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes), TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
_ => err!(Unimplemented(format!("ptr to {:?} cast", ty))), _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
} }

View file

@ -12,7 +12,7 @@ use syntax::codemap::DUMMY_SP;
use rustc::mir::interpret::{ use rustc::mir::interpret::{
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalResult, EvalError, EvalErrorKind, GlobalId,
Value, Pointer, Scalar, AllocId, Allocation, ConstValue, Value, Scalar, AllocId, Allocation, ConstValue,
}; };
use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, MemoryKind}; use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, MemoryKind};
@ -65,7 +65,7 @@ pub fn eval_promoted<'a, 'mir, 'tcx>(
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
mir: &'mir mir::Mir<'tcx>, mir: &'mir mir::Mir<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> Option<(Value, Pointer, Ty<'tcx>)> { ) -> Option<(Value, Scalar, Ty<'tcx>)> {
ecx.with_fresh_body(|ecx| { ecx.with_fresh_body(|ecx| {
let res = eval_body_using_ecx(ecx, cid, Some(mir), param_env); let res = eval_body_using_ecx(ecx, cid, Some(mir), param_env);
match res { match res {
@ -82,7 +82,7 @@ pub fn eval_body<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> Option<(Value, Pointer, Ty<'tcx>)> { ) -> Option<(Value, Scalar, Ty<'tcx>)> {
let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env); let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env);
match res { match res {
Ok(val) => Some(val), Ok(val) => Some(val),
@ -111,7 +111,7 @@ pub fn value_to_const_value<'tcx>(
Value::Scalar(val) => Ok(ConstValue::Scalar(val)), Value::Scalar(val) => Ok(ConstValue::Scalar(val)),
Value::ScalarPair(a, b) => Ok(ConstValue::ScalarPair(a, b)), Value::ScalarPair(a, b) => Ok(ConstValue::ScalarPair(a, b)),
Value::ByRef(ptr, align) => { Value::ByRef(ptr, align) => {
let ptr = ptr.primval.to_ptr().unwrap(); let ptr = ptr.to_ptr().unwrap();
let alloc = ecx.memory.get(ptr.alloc_id)?; let alloc = ecx.memory.get(ptr.alloc_id)?;
assert!(alloc.align.abi() >= align.abi()); assert!(alloc.align.abi() >= align.abi());
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes()); assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
@ -136,7 +136,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
mir: Option<&'mir mir::Mir<'tcx>>, mir: Option<&'mir mir::Mir<'tcx>>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) { ) -> (EvalResult<'tcx, (Value, Scalar, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) {
debug!("eval_body_and_ecx: {:?}, {:?}", cid, param_env); debug!("eval_body_and_ecx: {:?}, {:?}", cid, param_env);
// we start out with the best span we have // we start out with the best span we have
// and try improving it down the road when more information is available // and try improving it down the road when more information is available
@ -152,7 +152,7 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>(
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
mir: Option<&'mir mir::Mir<'tcx>>, mir: Option<&'mir mir::Mir<'tcx>>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> { ) -> EvalResult<'tcx, (Value, Scalar, Ty<'tcx>)> {
debug!("eval_body: {:?}, {:?}", cid, param_env); debug!("eval_body: {:?}, {:?}", cid, param_env);
let tcx = ecx.tcx.tcx; let tcx = ecx.tcx.tcx;
let mut mir = match mir { let mut mir = match mir {
@ -471,8 +471,7 @@ pub fn const_variant_index<'a, 'tcx>(
let (ptr, align) = match value { let (ptr, align) = match value {
Value::ScalarPair(..) | Value::Scalar(_) => { Value::ScalarPair(..) | Value::Scalar(_) => {
let layout = ecx.layout_of(ty)?; let layout = ecx.layout_of(ty)?;
let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?; let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?.into();
let ptr: Pointer = ptr.into();
ecx.write_value_to_ptr(value, ptr, layout.align, ty)?; ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
(ptr, layout.align) (ptr, layout.align)
}, },

View file

@ -14,7 +14,7 @@ use rustc::middle::const_val::FrameInfo;
use syntax::codemap::{self, Span}; use syntax::codemap::{self, Span};
use syntax::ast::Mutability; use syntax::ast::Mutability;
use rustc::mir::interpret::{ use rustc::mir::interpret::{
GlobalId, Value, Pointer, Scalar, ScalarKind, GlobalId, Value, Scalar, ScalarKind,
EvalError, EvalResult, EvalErrorKind, MemoryPointer, ConstValue, EvalError, EvalResult, EvalErrorKind, MemoryPointer, ConstValue,
}; };
use std::mem; use std::mem;
@ -596,7 +596,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
// FIXME: speed up repeat filling // FIXME: speed up repeat filling
for i in 0..length { for i in 0..length {
let elem_dest = dest.offset(elem_size * i as u64, &self)?; let elem_dest = dest.ptr_offset(elem_size * i as u64, &self)?;
self.write_value_to_ptr(value, elem_dest, dest_align, elem_ty)?; self.write_value_to_ptr(value, elem_dest, dest_align, elem_ty)?;
} }
} }
@ -729,7 +729,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
).ok_or_else(|| EvalErrorKind::TypeckError.into()); ).ok_or_else(|| EvalErrorKind::TypeckError.into());
let fn_ptr = self.memory.create_fn_alloc(instance?); let fn_ptr = self.memory.create_fn_alloc(instance?);
let valty = ValTy { let valty = ValTy {
value: Value::Scalar(Scalar::Ptr(fn_ptr)), value: Value::Scalar(fn_ptr.into()),
ty: dest_ty, ty: dest_ty,
}; };
self.write_value(valty, dest)?; self.write_value(valty, dest)?;
@ -765,7 +765,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
); );
let fn_ptr = self.memory.create_fn_alloc(instance); let fn_ptr = self.memory.create_fn_alloc(instance);
let valty = ValTy { let valty = ValTy {
value: Value::Scalar(Scalar::Ptr(fn_ptr)), value: Value::Scalar(fn_ptr.into()),
ty: dest_ty, ty: dest_ty,
}; };
self.write_value(valty, dest)?; self.write_value(valty, dest)?;
@ -1104,7 +1104,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
} }
} }
pub fn write_ptr(&mut self, dest: Place, val: Pointer, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> { pub fn write_ptr(&mut self, dest: Place, val: Scalar, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> {
let valty = ValTy { let valty = ValTy {
value: val.to_value(), value: val.to_value(),
ty: dest_ty, ty: dest_ty,
@ -1201,7 +1201,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
pub fn write_value_to_ptr( pub fn write_value_to_ptr(
&mut self, &mut self,
value: Value, value: Value,
dest: Pointer, dest: Scalar,
dest_align: Align, dest_align: Align,
dest_ty: Ty<'tcx>, dest_ty: Ty<'tcx>,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
@ -1231,7 +1231,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
let (a_size, b_size) = (a.size(&self), b.size(&self)); let (a_size, b_size) = (a.size(&self), b.size(&self));
let a_ptr = dest; let a_ptr = dest;
let b_offset = a_size.abi_align(b.align(&self)); let b_offset = a_size.abi_align(b.align(&self));
let b_ptr = dest.offset(b_offset, &self)?.into(); let b_ptr = dest.ptr_offset(b_offset, &self)?.into();
// TODO: What about signedess? // TODO: What about signedess?
self.memory.write_primval(a_ptr, dest_align, a_val, a_size, false)?; self.memory.write_primval(a_ptr, dest_align, a_val, a_size, false)?;
self.memory.write_primval(b_ptr, dest_align, b_val, b_size, false) self.memory.write_primval(b_ptr, dest_align, b_val, b_size, false)
@ -1319,7 +1319,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
} }
} }
pub fn read_value(&self, ptr: Pointer, align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> { pub fn read_value(&self, ptr: Scalar, align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
if let Some(val) = self.try_read_value(ptr, align, ty)? { if let Some(val) = self.try_read_value(ptr, align, ty)? {
Ok(val) Ok(val)
} else { } else {
@ -1334,7 +1334,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
pointee_ty: Ty<'tcx>, pointee_ty: Ty<'tcx>,
) -> EvalResult<'tcx, Value> { ) -> EvalResult<'tcx, Value> {
let ptr_size = self.memory.pointer_size(); let ptr_size = self.memory.pointer_size();
let p: Pointer = self.memory.read_ptr_sized(ptr, ptr_align)?.into(); let p: Scalar = self.memory.read_ptr_sized(ptr, ptr_align)?.into();
if self.type_is_sized(pointee_ty) { if self.type_is_sized(pointee_ty) {
Ok(p.to_value()) Ok(p.to_value())
} else { } else {
@ -1414,7 +1414,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
Ok(val) Ok(val)
} }
pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> { pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
let layout = self.layout_of(ty)?; let layout = self.layout_of(ty)?;
self.memory.check_align(ptr, ptr_align)?; self.memory.check_align(ptr, ptr_align)?;
@ -1614,7 +1614,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
} }
} }
Ok(Value::ByRef(ptr, align)) => { Ok(Value::ByRef(ptr, align)) => {
match ptr.into_inner_primval() { match ptr {
Scalar::Ptr(ptr) => { Scalar::Ptr(ptr) => {
write!(msg, " by align({}) ref:", align.abi()).unwrap(); write!(msg, " by align({}) ref:", align.abi()).unwrap();
allocs.push(ptr.alloc_id); allocs.push(ptr.alloc_id);
@ -1643,7 +1643,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
self.memory.dump_allocs(allocs); self.memory.dump_allocs(allocs);
} }
Place::Ptr { ptr, align, .. } => { Place::Ptr { ptr, align, .. } => {
match ptr.into_inner_primval() { match ptr {
Scalar::Ptr(ptr) => { Scalar::Ptr(ptr) => {
trace!("by align({}) ref:", align.abi()); trace!("by align({}) ref:", align.abi());
self.memory.dump_alloc(ptr.alloc_id); self.memory.dump_alloc(ptr.alloc_id);

View file

@ -10,7 +10,7 @@ use syntax::ast::Mutability;
use rustc::middle::const_val::{ConstVal, ErrKind}; use rustc::middle::const_val::{ConstVal, ErrKind};
use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, Value, Pointer, use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, Value,
EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType}; EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType};
pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint}; pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
@ -228,9 +228,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
} }
/// Check that the pointer is aligned AND non-NULL. /// Check that the pointer is aligned AND non-NULL.
pub fn check_align(&self, ptr: Pointer, required_align: Align) -> EvalResult<'tcx> { pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx> {
// Check non-NULL/Undef, extract offset // Check non-NULL/Undef, extract offset
let (offset, alloc_align) = match ptr.into_inner_primval() { let (offset, alloc_align) = match ptr {
Scalar::Ptr(ptr) => { Scalar::Ptr(ptr) => {
let alloc = self.get(ptr.alloc_id)?; let alloc = self.get(ptr.alloc_id)?;
(ptr.offset.bytes(), alloc.align) (ptr.offset.bytes(), alloc.align)
@ -594,9 +594,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
pub fn copy( pub fn copy(
&mut self, &mut self,
src: Pointer, src: Scalar,
src_align: Align, src_align: Align,
dest: Pointer, dest: Scalar,
dest_align: Align, dest_align: Align,
size: Size, size: Size,
nonoverlapping: bool, nonoverlapping: bool,
@ -671,7 +671,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
} }
} }
pub fn read_bytes(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx, &[u8]> { pub fn read_bytes(&self, ptr: Scalar, size: Size) -> EvalResult<'tcx, &[u8]> {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL // Empty accesses don't need to be valid pointers, but they should still be non-NULL
let align = Align::from_bytes(1, 1).unwrap(); let align = Align::from_bytes(1, 1).unwrap();
self.check_align(ptr, align)?; self.check_align(ptr, align)?;
@ -681,7 +681,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
self.get_bytes(ptr.to_ptr()?, size, align) self.get_bytes(ptr.to_ptr()?, size, align)
} }
pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> { pub fn write_bytes(&mut self, ptr: Scalar, src: &[u8]) -> EvalResult<'tcx> {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL // Empty accesses don't need to be valid pointers, but they should still be non-NULL
let align = Align::from_bytes(1, 1).unwrap(); let align = Align::from_bytes(1, 1).unwrap();
self.check_align(ptr, align)?; self.check_align(ptr, align)?;
@ -693,7 +693,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
Ok(()) Ok(())
} }
pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: Size) -> EvalResult<'tcx> { pub fn write_repeat(&mut self, ptr: Scalar, val: u8, count: Size) -> EvalResult<'tcx> {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL // Empty accesses don't need to be valid pointers, but they should still be non-NULL
let align = Align::from_bytes(1, 1).unwrap(); let align = Align::from_bytes(1, 1).unwrap();
self.check_align(ptr, align)?; self.check_align(ptr, align)?;
@ -726,7 +726,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
} else { } else {
let alloc = self.get(ptr.alloc_id)?; let alloc = self.get(ptr.alloc_id)?;
match alloc.relocations.get(&ptr.offset) { match alloc.relocations.get(&ptr.offset) {
Some(&alloc_id) => return Ok(Scalar::Ptr(MemoryPointer::new(alloc_id, Size::from_bytes(bytes as u64)))), Some(&alloc_id) => return Ok(MemoryPointer::new(alloc_id, Size::from_bytes(bytes as u64)).into()),
None => {}, None => {},
} }
} }
@ -738,7 +738,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
self.read_primval(ptr, ptr_align, self.pointer_size()) self.read_primval(ptr, ptr_align, self.pointer_size())
} }
pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: Scalar, size: Size, signed: bool) -> EvalResult<'tcx> { pub fn write_primval(&mut self, ptr: Scalar, ptr_align: Align, val: Scalar, size: Size, signed: bool) -> EvalResult<'tcx> {
let endianness = self.endianness(); let endianness = self.endianness();
let bytes = match val { let bytes = match val {
@ -896,7 +896,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
pub fn mark_definedness( pub fn mark_definedness(
&mut self, &mut self,
ptr: Pointer, ptr: Scalar,
size: Size, size: Size,
new_state: bool, new_state: bool,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
@ -927,7 +927,7 @@ pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
fn into_ptr( fn into_ptr(
&self, &self,
value: Value, value: Value,
) -> EvalResult<'tcx, Pointer> { ) -> EvalResult<'tcx, Scalar> {
Ok(match value { Ok(match value {
Value::ByRef(ptr, align) => { Value::ByRef(ptr, align) => {
self.memory().read_ptr_sized(ptr.to_ptr()?, align)? self.memory().read_ptr_sized(ptr.to_ptr()?, align)?
@ -940,13 +940,13 @@ pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
fn into_ptr_vtable_pair( fn into_ptr_vtable_pair(
&self, &self,
value: Value, value: Value,
) -> EvalResult<'tcx, (Pointer, MemoryPointer)> { ) -> EvalResult<'tcx, (Scalar, MemoryPointer)> {
match value { match value {
Value::ByRef(ref_ptr, align) => { Value::ByRef(ref_ptr, align) => {
let mem = self.memory(); let mem = self.memory();
let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into(); let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into();
let vtable = mem.read_ptr_sized( let vtable = mem.read_ptr_sized(
ref_ptr.offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?, ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?,
align align
)?.to_ptr()?; )?.to_ptr()?;
Ok((ptr, vtable)) Ok((ptr, vtable))
@ -962,13 +962,13 @@ pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
fn into_slice( fn into_slice(
&self, &self,
value: Value, value: Value,
) -> EvalResult<'tcx, (Pointer, u64)> { ) -> EvalResult<'tcx, (Scalar, u64)> {
match value { match value {
Value::ByRef(ref_ptr, align) => { Value::ByRef(ref_ptr, align) => {
let mem = self.memory(); let mem = self.memory();
let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into(); let ptr = mem.read_ptr_sized(ref_ptr.to_ptr()?, align)?.into();
let len = mem.read_ptr_sized( let len = mem.read_ptr_sized(
ref_ptr.offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?, ref_ptr.ptr_offset(mem.pointer_size(), &mem.tcx.data_layout)?.to_ptr()?,
align align
)?.to_bytes()? as u64; )?.to_bytes()? as u64;
Ok((ptr, len)) Ok((ptr, len))

View file

@ -3,7 +3,7 @@ use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use rustc::mir::interpret::{GlobalId, Value, Scalar, EvalResult, Pointer, MemoryPointer}; use rustc::mir::interpret::{GlobalId, Value, Scalar, EvalResult, MemoryPointer};
use super::{EvalContext, Machine, ValTy}; use super::{EvalContext, Machine, ValTy};
use interpret::memory::HasMemory; use interpret::memory::HasMemory;
@ -14,7 +14,7 @@ pub enum Place {
/// A place may have an invalid (integral or undef) pointer, /// A place may have an invalid (integral or undef) pointer,
/// since it might be turned back into a reference /// since it might be turned back into a reference
/// before ever being dereferenced. /// before ever being dereferenced.
ptr: Pointer, ptr: Scalar,
align: Align, align: Align,
extra: PlaceExtra, extra: PlaceExtra,
}, },
@ -38,7 +38,7 @@ impl<'tcx> Place {
Self::from_primval_ptr(Scalar::Undef.into(), Align::from_bytes(1, 1).unwrap()) Self::from_primval_ptr(Scalar::Undef.into(), Align::from_bytes(1, 1).unwrap())
} }
pub fn from_primval_ptr(ptr: Pointer, align: Align) -> Self { pub fn from_primval_ptr(ptr: Scalar, align: Align) -> Self {
Place::Ptr { Place::Ptr {
ptr, ptr,
align, align,
@ -50,7 +50,7 @@ impl<'tcx> Place {
Self::from_primval_ptr(ptr.into(), align) Self::from_primval_ptr(ptr.into(), align)
} }
pub fn to_ptr_align_extra(self) -> (Pointer, Align, PlaceExtra) { pub fn to_ptr_align_extra(self) -> (Scalar, Align, PlaceExtra) {
match self { match self {
Place::Ptr { ptr, align, extra } => (ptr, align, extra), Place::Ptr { ptr, align, extra } => (ptr, align, extra),
_ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self), _ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self),
@ -58,7 +58,7 @@ impl<'tcx> Place {
} }
} }
pub fn to_ptr_align(self) -> (Pointer, Align) { pub fn to_ptr_align(self) -> (Scalar, Align) {
let (ptr, align, _extra) = self.to_ptr_align_extra(); let (ptr, align, _extra) = self.to_ptr_align_extra();
(ptr, align) (ptr, align)
} }
@ -272,7 +272,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
_ => offset, _ => offset,
}; };
let ptr = base_ptr.offset(offset, &self)?; let ptr = base_ptr.ptr_offset(offset, &self)?;
let align = base_align.min(base_layout.align).min(field.align); let align = base_align.min(base_layout.align).min(field.align);
let extra = if !field.is_unsized() { let extra = if !field.is_unsized() {
PlaceExtra::None PlaceExtra::None
@ -332,7 +332,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
n, n,
len len
); );
let ptr = base_ptr.offset(elem_size * n, &*self)?; let ptr = base_ptr.ptr_offset(elem_size * n, &*self)?;
Ok(Place::Ptr { Ok(Place::Ptr {
ptr, ptr,
align, align,
@ -410,7 +410,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
u64::from(offset) u64::from(offset)
}; };
let ptr = base_ptr.offset(elem_size * index, &self)?; let ptr = base_ptr.ptr_offset(elem_size * index, &self)?;
Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None }) Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None })
} }
@ -422,7 +422,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx); let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
let elem_size = self.layout_of(elem_ty)?.size; let elem_size = self.layout_of(elem_ty)?.size;
assert!(u64::from(from) <= n - u64::from(to)); assert!(u64::from(from) <= n - u64::from(to));
let ptr = base_ptr.offset(elem_size * u64::from(from), &self)?; let ptr = base_ptr.ptr_offset(elem_size * u64::from(from), &self)?;
// sublicing arrays produces arrays // sublicing arrays produces arrays
let extra = if self.type_is_sized(base_ty) { let extra = if self.type_is_sized(base_ty) {
PlaceExtra::None PlaceExtra::None

View file

@ -342,7 +342,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
for (i, arg_local) in arg_locals.enumerate() { for (i, arg_local) in arg_locals.enumerate() {
let field = layout.field(&self, i)?; let field = layout.field(&self, i)?;
let offset = layout.fields.offset(i); let offset = layout.fields.offset(i);
let arg = Value::ByRef(ptr.offset(offset, &self)?, let arg = Value::ByRef(ptr.ptr_offset(offset, &self)?,
align.min(field.align)); align.min(field.align));
let dest = let dest =
self.eval_place(&mir::Place::Local(arg_local))?; self.eval_place(&mir::Place::Local(arg_local))?;

View file

@ -35,7 +35,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
let drop = self.memory.create_fn_alloc(drop); let drop = self.memory.create_fn_alloc(drop);
self.memory.write_ptr_sized_unsigned(vtable, ptr_align, Scalar::Ptr(drop))?; self.memory.write_ptr_sized_unsigned(vtable, ptr_align, drop.into())?;
let size_ptr = vtable.offset(ptr_size, &self)?; let size_ptr = vtable.offset(ptr_size, &self)?;
self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bytes(size as u128))?; self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bytes(size as u128))?;
@ -47,7 +47,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
let instance = self.resolve(def_id, substs)?; let instance = self.resolve(def_id, substs)?;
let fn_ptr = self.memory.create_fn_alloc(instance); let fn_ptr = self.memory.create_fn_alloc(instance);
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?; let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, Scalar::Ptr(fn_ptr))?; self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, fn_ptr.into())?;
} }
} }