Use a wrapper type to differentiate between PrimVal and pointers
This commit is contained in:
parent
a8b957a0f8
commit
03f0a88002
@ -19,7 +19,7 @@ use error::{EvalError, EvalResult};
|
||||
use lvalue::{Global, GlobalId, Lvalue, LvalueExtra};
|
||||
use memory::{Memory, MemoryPointer, TlsKey};
|
||||
use operator;
|
||||
use value::{PrimVal, PrimValKind, Value};
|
||||
use value::{PrimVal, PrimValKind, Value, Pointer};
|
||||
|
||||
pub struct EvalContext<'a, 'tcx: 'a> {
|
||||
/// The results of the type checker, from rustc.
|
||||
@ -395,7 +395,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let arg_local = self.frame().mir.args_iter().next().ok_or(EvalError::AbiViolation("TLS dtor does not take enough arguments.".to_owned()))?;
|
||||
let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
|
||||
let ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
|
||||
self.write_primval(dest, ptr, ty)?;
|
||||
self.write_ptr(dest, ptr, ty)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,7 +444,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
self.memory.write_uint(discr_dest, discr_val, discr_size)?;
|
||||
|
||||
let dest = Lvalue::Ptr {
|
||||
ptr: PrimVal::Ptr(dest_ptr),
|
||||
ptr: dest_ptr.into(),
|
||||
extra: LvalueExtra::DowncastVariant(variant_idx),
|
||||
};
|
||||
|
||||
@ -580,7 +580,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let operand_ty = self.operand_ty(operand);
|
||||
assert_eq!(self.type_size(operand_ty)?, Some(0));
|
||||
}
|
||||
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
|
||||
self.write_null(dest, dest_ty)?;
|
||||
}
|
||||
} else {
|
||||
bug!("tried to assign {:?} to Layout::RawNullablePointer", kind);
|
||||
@ -662,7 +662,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let value = self.eval_operand(operand)?;
|
||||
|
||||
// FIXME(solson)
|
||||
let dest = PrimVal::Ptr(self.force_allocation(dest)?.to_ptr()?);
|
||||
let dest = Pointer::from(self.force_allocation(dest)?.to_ptr()?);
|
||||
|
||||
for i in 0..length {
|
||||
let elem_dest = dest.offset(i * elem_size, self.memory.layout)?;
|
||||
@ -686,9 +686,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let ty = self.lvalue_ty(lvalue);
|
||||
|
||||
let val = match extra {
|
||||
LvalueExtra::None => Value::ByVal(ptr),
|
||||
LvalueExtra::Length(len) => Value::ByValPair(ptr, PrimVal::from_u128(len as u128)),
|
||||
LvalueExtra::Vtable(vtable) => Value::ByValPair(ptr, PrimVal::Ptr(vtable)),
|
||||
LvalueExtra::None => ptr.to_value(),
|
||||
LvalueExtra::Length(len) => ptr.with_extra(PrimVal::from_u128(len as u128)),
|
||||
LvalueExtra::Vtable(vtable) => ptr.with_extra(PrimVal::Ptr(vtable)),
|
||||
LvalueExtra::DowncastVariant(..) =>
|
||||
bug!("attempted to take a reference to an enum downcast lvalue"),
|
||||
};
|
||||
@ -928,14 +928,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn wrapping_pointer_offset(&self, ptr: PrimVal, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, PrimVal> {
|
||||
pub(super) fn wrapping_pointer_offset(&self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, Pointer> {
|
||||
// FIXME: assuming here that type size is < i64::max_value()
|
||||
let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as i64;
|
||||
let offset = offset.overflowing_mul(pointee_size).0;
|
||||
ptr.wrapping_signed_offset(offset, self.memory.layout)
|
||||
}
|
||||
|
||||
pub(super) fn pointer_offset(&self, ptr: PrimVal, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, PrimVal> {
|
||||
pub(super) fn pointer_offset(&self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, Pointer> {
|
||||
// This function raises an error if the offset moves the pointer outside of its allocation. We consider
|
||||
// ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0).
|
||||
// We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own
|
||||
@ -949,7 +949,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
return if let Some(offset) = offset.checked_mul(pointee_size) {
|
||||
let ptr = ptr.signed_offset(offset, self.memory.layout)?;
|
||||
// Do not do bounds-checking for integers; they can never alias a normal pointer anyway.
|
||||
if let PrimVal::Ptr(ptr) = ptr {
|
||||
if let PrimVal::Ptr(ptr) = ptr.into_inner_primval() {
|
||||
self.memory.check_bounds(ptr, false)?;
|
||||
} else if ptr.is_null()? {
|
||||
// We moved *to* a NULL pointer. That seems wrong, LLVM considers the NULL pointer its own small allocation. Reject this, for now.
|
||||
@ -1002,7 +1002,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
self.monomorphize(operand.ty(self.mir(), self.tcx), self.substs())
|
||||
}
|
||||
|
||||
fn copy(&mut self, src: PrimVal, dest: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx> {
|
||||
fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx> {
|
||||
let size = self.type_size(ty)?.expect("cannot copy from an unsized type");
|
||||
let align = self.type_align(ty)?;
|
||||
self.memory.copy(src, dest, size, align, false)?;
|
||||
@ -1026,8 +1026,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let ty = self.monomorphize(ty, self.stack[frame].instance.substs);
|
||||
let substs = self.stack[frame].instance.substs;
|
||||
let ptr = self.alloc_ptr_with_substs(ty, substs)?;
|
||||
self.stack[frame].locals[local.index() - 1] = Some(Value::ByRef(PrimVal::Ptr(ptr))); // it stays live
|
||||
self.write_value_to_ptr(val, PrimVal::Ptr(ptr), ty)?;
|
||||
self.stack[frame].locals[local.index() - 1] = Some(Value::ByRef(ptr.into())); // it stays live
|
||||
self.write_value_to_ptr(val, ptr.into(), ty)?;
|
||||
Lvalue::from_ptr(ptr)
|
||||
}
|
||||
}
|
||||
@ -1040,14 +1040,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
_ => {
|
||||
let ptr = self.alloc_ptr_with_substs(global_val.ty, cid.instance.substs)?;
|
||||
self.memory.mark_static(ptr.alloc_id);
|
||||
self.write_value_to_ptr(global_val.value, PrimVal::Ptr(ptr), global_val.ty)?;
|
||||
self.write_value_to_ptr(global_val.value, ptr.into(), global_val.ty)?;
|
||||
// see comment on `initialized` field
|
||||
if global_val.initialized {
|
||||
self.memory.mark_static_initalized(ptr.alloc_id, global_val.mutable)?;
|
||||
}
|
||||
let lval = self.globals.get_mut(&cid).expect("already checked");
|
||||
*lval = Global {
|
||||
value: Value::ByRef(PrimVal::Ptr(ptr)),
|
||||
value: Value::ByRef(ptr.into()),
|
||||
.. global_val
|
||||
};
|
||||
Lvalue::from_ptr(ptr)
|
||||
@ -1087,6 +1087,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)
|
||||
}
|
||||
|
||||
pub(super) fn write_ptr(
|
||||
&mut self,
|
||||
dest: Lvalue<'tcx>,
|
||||
val: Pointer,
|
||||
dest_ty: Ty<'tcx>,
|
||||
) -> EvalResult<'tcx> {
|
||||
self.write_value(val.to_value(), dest, dest_ty)
|
||||
}
|
||||
|
||||
pub(super) fn write_primval(
|
||||
&mut self,
|
||||
dest: Lvalue<'tcx>,
|
||||
@ -1172,9 +1181,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
if let Ok(Some(src_val)) = self.try_read_value(src_ptr, dest_ty) {
|
||||
write_dest(self, src_val)?;
|
||||
} else {
|
||||
let dest_ptr = self.alloc_ptr(dest_ty)?;
|
||||
self.copy(src_ptr, PrimVal::Ptr(dest_ptr), dest_ty)?;
|
||||
write_dest(self, Value::ByRef(PrimVal::Ptr(dest_ptr)))?;
|
||||
let dest_ptr = self.alloc_ptr(dest_ty)?.into();
|
||||
self.copy(src_ptr, dest_ptr, dest_ty)?;
|
||||
write_dest(self, Value::ByRef(dest_ptr))?;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1188,7 +1197,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
pub(super) fn write_value_to_ptr(
|
||||
&mut self,
|
||||
value: Value,
|
||||
dest: PrimVal,
|
||||
dest: Pointer,
|
||||
dest_ty: Ty<'tcx>,
|
||||
) -> EvalResult<'tcx> {
|
||||
match value {
|
||||
@ -1218,8 +1227,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let field_1_ty = self.get_field_ty(ty, 1)?;
|
||||
let field_0_size = self.type_size(field_0_ty)?.expect("pair element type must be sized");
|
||||
let field_1_size = self.type_size(field_1_ty)?.expect("pair element type must be sized");
|
||||
self.memory.write_primval(PrimVal::Ptr(ptr.offset(field_0, self.memory.layout)?), a, field_0_size)?;
|
||||
self.memory.write_primval(PrimVal::Ptr(ptr.offset(field_1, self.memory.layout)?), b, field_1_size)?;
|
||||
self.memory.write_primval(ptr.offset(field_0, self.memory.layout)?.into(), a, field_0_size)?;
|
||||
self.memory.write_primval(ptr.offset(field_1, self.memory.layout)?.into(), b, field_1_size)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1322,7 +1331,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn read_value(&mut self, ptr: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
|
||||
pub(super) fn read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
|
||||
if let Some(val) = self.try_read_value(ptr, ty)? {
|
||||
Ok(val)
|
||||
} else {
|
||||
@ -1333,21 +1342,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
pub(crate) fn read_ptr(&self, ptr: MemoryPointer, pointee_ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
|
||||
let p = self.memory.read_ptr(ptr)?;
|
||||
if self.type_is_sized(pointee_ty) {
|
||||
Ok(Value::ByVal(p))
|
||||
Ok(p.to_value())
|
||||
} else {
|
||||
trace!("reading fat pointer extra of type {}", pointee_ty);
|
||||
let extra = ptr.offset(self.memory.pointer_size(), self.memory.layout)?;
|
||||
let extra = match self.tcx.struct_tail(pointee_ty).sty {
|
||||
ty::TyDynamic(..) => self.memory.read_ptr(extra)?,
|
||||
ty::TyDynamic(..) => self.memory.read_ptr(extra)?.into_inner_primval(),
|
||||
ty::TySlice(..) |
|
||||
ty::TyStr => PrimVal::from_u128(self.memory.read_usize(extra)? as u128),
|
||||
_ => bug!("unsized primval ptr read from {:?}", pointee_ty),
|
||||
};
|
||||
Ok(Value::ByValPair(p, extra))
|
||||
Ok(p.with_extra(extra))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_read_value(&mut self, ptr: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
|
||||
fn try_read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
|
||||
use syntax::ast::FloatTy;
|
||||
|
||||
let val = match ty.sty {
|
||||
@ -1373,7 +1382,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
// if we transmute a ptr to an isize, reading it back into a primval shouldn't panic
|
||||
// Due to read_ptr ignoring the sign, we need to jump around some hoops
|
||||
match self.memory.read_int(ptr.to_ptr()?, size) {
|
||||
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?,
|
||||
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
|
||||
other => PrimVal::from_i128(other?),
|
||||
}
|
||||
}
|
||||
@ -1390,7 +1399,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
};
|
||||
if size == self.memory.pointer_size() {
|
||||
// if we transmute a ptr to an usize, reading it back into a primval shouldn't panic
|
||||
self.memory.read_ptr(ptr.to_ptr()?)?
|
||||
self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval()
|
||||
} else {
|
||||
PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?)
|
||||
}
|
||||
@ -1399,7 +1408,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr.to_ptr()?)?),
|
||||
ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr.to_ptr()?)?),
|
||||
|
||||
ty::TyFnPtr(_) => self.memory.read_ptr(ptr.to_ptr()?)?,
|
||||
ty::TyFnPtr(_) => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
|
||||
ty::TyRef(_, ref tam) |
|
||||
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr.to_ptr()?, tam.ty).map(Some),
|
||||
|
||||
@ -1458,7 +1467,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
(&ty::TyArray(_, length), &ty::TySlice(_)) => {
|
||||
let ptr = src.read_ptr(&self.memory)?;
|
||||
let len = PrimVal::from_u128(length as u128);
|
||||
self.write_value(Value::ByValPair(ptr, len), dest, dest_ty)
|
||||
self.write_value(ptr.with_extra(len), dest, dest_ty)
|
||||
}
|
||||
(&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
|
||||
// For now, upcasts are limited to changes in marker
|
||||
@ -1472,7 +1481,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let vtable = self.get_vtable(src_pointee_ty, trait_ref)?;
|
||||
let ptr = src.read_ptr(&self.memory)?;
|
||||
let extra = PrimVal::Ptr(vtable);
|
||||
self.write_value(Value::ByValPair(ptr, extra), dest, dest_ty)
|
||||
self.write_value(ptr.with_extra(extra), dest, dest_ty)
|
||||
},
|
||||
|
||||
_ => bug!("invalid unsizing {:?} -> {:?}", src_ty, dest_ty),
|
||||
@ -1532,7 +1541,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let src_f_ptr = src_ptr.offset(src_field_offset, self.memory.layout)?;
|
||||
let dst_f_ptr = dest.offset(dst_field_offset, self.memory.layout)?;
|
||||
if src_fty == dst_fty {
|
||||
self.copy(src_f_ptr, PrimVal::Ptr(dst_f_ptr), src_fty)?;
|
||||
self.copy(src_f_ptr, dst_f_ptr.into(), src_fty)?;
|
||||
} else {
|
||||
self.unsize_into(Value::ByRef(src_f_ptr), src_fty, Lvalue::from_ptr(dst_f_ptr), dst_fty)?;
|
||||
}
|
||||
@ -1561,13 +1570,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Err(err) => {
|
||||
panic!("Failed to access local: {:?}", err);
|
||||
}
|
||||
Ok(Value::ByRef(PrimVal::Ptr(ptr))) => {
|
||||
write!(msg, " by ref:").unwrap();
|
||||
allocs.push(ptr.alloc_id);
|
||||
}
|
||||
Ok(Value::ByRef(ptr)) => {
|
||||
write!(msg, " integral by ref: {:?}", ptr).unwrap();
|
||||
}
|
||||
Ok(Value::ByRef(ptr)) => match ptr.into_inner_primval() {
|
||||
PrimVal::Ptr(ptr) => {
|
||||
write!(msg, " by ref:").unwrap();
|
||||
allocs.push(ptr.alloc_id);
|
||||
},
|
||||
ptr => write!(msg, " integral by ref: {:?}", ptr).unwrap(),
|
||||
},
|
||||
Ok(Value::ByVal(val)) => {
|
||||
write!(msg, " {:?}", val).unwrap();
|
||||
if let PrimVal::Ptr(ptr) = val { allocs.push(ptr.alloc_id); }
|
||||
|
@ -6,7 +6,7 @@ use rustc_data_structures::indexed_vec::Idx;
|
||||
use error::{EvalError, EvalResult};
|
||||
use eval_context::{EvalContext};
|
||||
use memory::MemoryPointer;
|
||||
use value::{PrimVal, Value};
|
||||
use value::{PrimVal, Value, Pointer};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Lvalue<'tcx> {
|
||||
@ -15,7 +15,7 @@ pub enum Lvalue<'tcx> {
|
||||
/// An lvalue may have an invalid (integral or undef) pointer,
|
||||
/// since it might be turned back into a reference
|
||||
/// before ever being dereferenced.
|
||||
ptr: PrimVal,
|
||||
ptr: Pointer,
|
||||
extra: LvalueExtra,
|
||||
},
|
||||
|
||||
@ -64,18 +64,18 @@ pub struct Global<'tcx> {
|
||||
impl<'tcx> Lvalue<'tcx> {
|
||||
/// Produces an Lvalue that will error if attempted to be read from
|
||||
pub fn undef() -> Self {
|
||||
Self::from_primval_ptr(PrimVal::Undef)
|
||||
Self::from_primval_ptr(PrimVal::Undef.into())
|
||||
}
|
||||
|
||||
pub(crate) fn from_primval_ptr(ptr: PrimVal) -> Self {
|
||||
pub(crate) fn from_primval_ptr(ptr: Pointer) -> Self {
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::None }
|
||||
}
|
||||
|
||||
pub(crate) fn from_ptr(ptr: MemoryPointer) -> Self {
|
||||
Self::from_primval_ptr(PrimVal::Ptr(ptr))
|
||||
Self::from_primval_ptr(ptr.into())
|
||||
}
|
||||
|
||||
pub(super) fn to_ptr_and_extra(self) -> (PrimVal, LvalueExtra) {
|
||||
pub(super) fn to_ptr_and_extra(self) -> (Pointer, LvalueExtra) {
|
||||
match self {
|
||||
Lvalue::Ptr { ptr, extra } => (ptr, extra),
|
||||
_ => bug!("to_ptr_and_extra: expected Lvalue::Ptr, got {:?}", self),
|
||||
@ -315,7 +315,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
let offset = match base_extra {
|
||||
LvalueExtra::Vtable(tab) => {
|
||||
let (_, align) = self.size_and_align_of_dst(base_ty, Value::ByValPair(base_ptr, PrimVal::Ptr(tab)))?;
|
||||
let (_, align) = self.size_and_align_of_dst(base_ty, base_ptr.with_extra(PrimVal::Ptr(tab)))?;
|
||||
offset.abi_align(Align::from_bytes(align, align).unwrap()).bytes()
|
||||
}
|
||||
_ => offset.bytes(),
|
||||
|
@ -6,7 +6,7 @@ use rustc::ty;
|
||||
use rustc::ty::layout::{self, TargetDataLayout};
|
||||
|
||||
use error::{EvalError, EvalResult};
|
||||
use value::{PrimVal, self};
|
||||
use value::{PrimVal, self, Pointer};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocations and pointers
|
||||
@ -87,7 +87,7 @@ pub type TlsKey = usize;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct TlsEntry<'tcx> {
|
||||
data: PrimVal, // Will eventually become a map from thread IDs to `PrimVal`s, if we ever support more than one thread.
|
||||
data: Pointer, // Will eventually become a map from thread IDs to `Pointer`s, if we ever support more than one thread.
|
||||
dtor: Option<ty::Instance<'tcx>>,
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
|
||||
// TODO(solson): Track which allocations were returned from __rust_allocate and report an error
|
||||
// when reallocating/deallocating any others.
|
||||
pub fn reallocate(&mut self, ptr: MemoryPointer, old_size: u64, old_align: u64, new_size: u64, new_align: u64) -> EvalResult<'tcx, Pointer> {
|
||||
pub fn reallocate(&mut self, ptr: MemoryPointer, old_size: u64, old_align: u64, new_size: u64, new_align: u64) -> EvalResult<'tcx, MemoryPointer> {
|
||||
use std::cmp::min;
|
||||
|
||||
// TODO(solson): Report error about non-__rust_allocate'd pointer.
|
||||
@ -236,7 +236,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
|
||||
// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc"
|
||||
let new_ptr = self.allocate(new_size, new_align)?;
|
||||
self.copy(PrimVal::Ptr(ptr), PrimVal::Ptr(new_ptr), min(old_size, new_size), min(old_align, new_align), /*nonoverlapping*/true)?;
|
||||
self.copy(ptr.into(), new_ptr.into(), min(old_size, new_size), min(old_align, new_align), /*nonoverlapping*/true)?;
|
||||
self.deallocate(ptr, Some((old_size, old_align)))?;
|
||||
|
||||
Ok(new_ptr)
|
||||
@ -278,8 +278,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
self.layout.endian
|
||||
}
|
||||
|
||||
pub fn check_align(&self, ptr: PrimVal, align: u64, len: u64) -> EvalResult<'tcx> {
|
||||
let offset = match ptr {
|
||||
pub fn check_align(&self, ptr: Pointer, align: u64, len: u64) -> EvalResult<'tcx> {
|
||||
let offset = match ptr.into_inner_primval() {
|
||||
PrimVal::Ptr(ptr) => {
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
// check whether the memory was marked as packed
|
||||
@ -353,7 +353,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
pub(crate) fn create_tls_key(&mut self, dtor: Option<ty::Instance<'tcx>>) -> TlsKey {
|
||||
let new_key = self.next_thread_local;
|
||||
self.next_thread_local += 1;
|
||||
self.thread_local.insert(new_key, TlsEntry { data: PrimVal::Bytes(0), dtor });
|
||||
self.thread_local.insert(new_key, TlsEntry { data: Pointer::null(), dtor });
|
||||
trace!("New TLS key allocated: {} with dtor {:?}", new_key, dtor);
|
||||
return new_key;
|
||||
}
|
||||
@ -368,7 +368,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, PrimVal> {
|
||||
pub(crate) fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer> {
|
||||
return match self.thread_local.get(&key) {
|
||||
Some(&TlsEntry { data, .. }) => {
|
||||
trace!("TLS key {} loaded: {:?}", key, data);
|
||||
@ -378,7 +378,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn store_tls(&mut self, key: TlsKey, new_data: PrimVal) -> EvalResult<'tcx> {
|
||||
pub(crate) fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx> {
|
||||
return match self.thread_local.get_mut(&key) {
|
||||
Some(&mut TlsEntry { ref mut data, .. }) => {
|
||||
trace!("TLS key {} stored: {:?}", key, new_data);
|
||||
@ -407,7 +407,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
/// with associated destructors, implementations may stop calling destructors,
|
||||
/// or they may continue calling destructors until no non-NULL values with
|
||||
/// associated destructors exist, even though this might result in an infinite loop.
|
||||
pub(crate) fn fetch_tls_dtor(&mut self, key: Option<TlsKey>) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, PrimVal, TlsKey)>> {
|
||||
pub(crate) fn fetch_tls_dtor(&mut self, key: Option<TlsKey>) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>> {
|
||||
use std::collections::Bound::*;
|
||||
let start = match key {
|
||||
Some(key) => Excluded(key),
|
||||
@ -417,7 +417,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
if !data.is_null()? {
|
||||
if let Some(dtor) = dtor {
|
||||
let ret = Some((dtor, *data, key));
|
||||
*data = PrimVal::Bytes(0);
|
||||
*data = Pointer::null();
|
||||
return Ok(ret);
|
||||
}
|
||||
}
|
||||
@ -575,7 +575,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
if size == 0 {
|
||||
return Ok(&[]);
|
||||
}
|
||||
self.check_align(PrimVal::Ptr(ptr), align, size)?;
|
||||
// FIXME: check alignment for zst memory accesses?
|
||||
self.check_align(ptr.into(), align, size)?;
|
||||
self.check_bounds(ptr.offset(size, self.layout)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
assert_eq!(ptr.offset as usize as u64, ptr.offset);
|
||||
@ -588,7 +589,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
if size == 0 {
|
||||
return Ok(&mut []);
|
||||
}
|
||||
self.check_align(PrimVal::Ptr(ptr), align, size)?;
|
||||
// FIXME: check alignment for zst memory accesses?
|
||||
self.check_align(ptr.into(), align, size)?;
|
||||
self.check_bounds(ptr.offset(size, self.layout)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
let alloc = self.get_mut(ptr.alloc_id)?;
|
||||
assert_eq!(ptr.offset as usize as u64, ptr.offset);
|
||||
@ -609,7 +611,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
fn get_bytes_mut(&mut self, ptr: MemoryPointer, size: u64, align: u64) -> EvalResult<'tcx, &mut [u8]> {
|
||||
assert_ne!(size, 0);
|
||||
self.clear_relocations(ptr, size)?;
|
||||
self.mark_definedness(PrimVal::Ptr(ptr), size, true)?;
|
||||
self.mark_definedness(ptr.into(), size, true)?;
|
||||
self.get_bytes_unchecked_mut(ptr, size, align)
|
||||
}
|
||||
}
|
||||
@ -661,7 +663,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy(&mut self, src: PrimVal, dest: PrimVal, size: u64, align: u64, nonoverlapping: bool) -> EvalResult<'tcx> {
|
||||
pub fn copy(&mut self, src: Pointer, dest: Pointer, size: u64, align: u64, nonoverlapping: bool) -> EvalResult<'tcx> {
|
||||
if size == 0 {
|
||||
// TODO: Should we check for alignment here? (Also see write_bytes intrinsic)
|
||||
return Ok(());
|
||||
@ -713,7 +715,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_bytes(&self, ptr: PrimVal, size: u64) -> EvalResult<'tcx, &[u8]> {
|
||||
pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> {
|
||||
if size == 0 {
|
||||
return Ok(&[]);
|
||||
}
|
||||
@ -729,7 +731,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_repeat(&mut self, ptr: PrimVal, val: u8, count: u64) -> EvalResult<'tcx> {
|
||||
pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> {
|
||||
if count == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
@ -738,10 +740,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_ptr(&self, ptr: MemoryPointer) -> EvalResult<'tcx, PrimVal> {
|
||||
pub fn read_ptr(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Pointer> {
|
||||
let size = self.pointer_size();
|
||||
if self.check_defined(ptr, size).is_err() {
|
||||
return Ok(PrimVal::Undef);
|
||||
return Ok(PrimVal::Undef.into());
|
||||
}
|
||||
let endianess = self.endianess();
|
||||
let bytes = self.get_bytes_unchecked(ptr, size, size)?;
|
||||
@ -750,8 +752,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
let offset = offset as u64;
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
match alloc.relocations.get(&ptr.offset) {
|
||||
Some(&alloc_id) => Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, offset))),
|
||||
None => Ok(PrimVal::Bytes(offset as u128)),
|
||||
Some(&alloc_id) => Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, offset)).into()),
|
||||
None => Ok(PrimVal::Bytes(offset as u128).into()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -763,7 +765,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
|
||||
pub fn write_primval(
|
||||
&mut self,
|
||||
dest: PrimVal,
|
||||
dest: Pointer,
|
||||
val: PrimVal,
|
||||
size: u64,
|
||||
) -> EvalResult<'tcx> {
|
||||
@ -970,7 +972,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
|
||||
pub fn mark_definedness(
|
||||
&mut self,
|
||||
ptr: PrimVal,
|
||||
ptr: Pointer,
|
||||
size: u64,
|
||||
new_state: bool
|
||||
) -> EvalResult<'tcx> {
|
||||
|
@ -158,8 +158,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
match bin_op {
|
||||
Offset if left_kind == Ptr && right_kind == usize => {
|
||||
let pointee_ty = left_ty.builtin_deref(true, ty::LvaluePreference::NoPreference).expect("Offset called on non-ptr type").ty;
|
||||
let ptr = self.pointer_offset(left, pointee_ty, right.to_bytes()? as i64)?;
|
||||
return Ok((ptr, false));
|
||||
let ptr = self.pointer_offset(left.into(), pointee_ty, right.to_bytes()? as i64)?;
|
||||
return Ok((ptr.into_inner_primval(), false));
|
||||
},
|
||||
// These work on anything
|
||||
Eq if left_kind == right_kind => {
|
||||
|
@ -12,9 +12,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
pub(crate) fn drop_lvalue(&mut self, lval: Lvalue<'tcx>, instance: ty::Instance<'tcx>, ty: Ty<'tcx>, span: Span) -> EvalResult<'tcx> {
|
||||
trace!("drop_lvalue: {:#?}", lval);
|
||||
let val = match self.force_allocation(lval)? {
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::Vtable(vtable) } => Value::ByValPair(ptr, PrimVal::Ptr(vtable)),
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => Value::ByValPair(ptr, PrimVal::Bytes(len as u128)),
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::None } => Value::ByVal(ptr),
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::Vtable(vtable) } => ptr.with_extra(PrimVal::Ptr(vtable)),
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => ptr.with_extra(PrimVal::Bytes(len as u128)),
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::None } => ptr.to_value(),
|
||||
_ => bug!("force_allocation broken"),
|
||||
};
|
||||
self.drop(val, instance, ty, span)
|
||||
|
@ -7,7 +7,7 @@ use rustc::ty::{self, Ty};
|
||||
use error::{EvalError, EvalResult};
|
||||
use eval_context::EvalContext;
|
||||
use lvalue::{Lvalue, LvalueExtra};
|
||||
use value::{PrimVal, PrimValKind, Value};
|
||||
use value::{PrimVal, PrimValKind, Value, Pointer};
|
||||
|
||||
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
pub(super) fn call_intrinsic(
|
||||
@ -46,7 +46,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64;
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let result_ptr = self.wrapping_pointer_offset(ptr, substs.type_at(0), offset)?;
|
||||
self.write_primval(dest, result_ptr, dest_ty)?;
|
||||
self.write_ptr(dest, result_ptr, dest_ty)?;
|
||||
}
|
||||
|
||||
"assume" => {
|
||||
@ -257,8 +257,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Ok(_) => Value::ByVal(PrimVal::Bytes(0)),
|
||||
Err(_) => {
|
||||
let ptr = this.alloc_ptr_with_substs(dest_ty, substs)?;
|
||||
this.memory.write_repeat(PrimVal::Ptr(ptr), 0, size)?;
|
||||
Value::ByRef(PrimVal::Ptr(ptr))
|
||||
let ptr = Pointer::from(PrimVal::Ptr(ptr));
|
||||
this.memory.write_repeat(ptr, 0, size)?;
|
||||
Value::ByRef(ptr)
|
||||
}
|
||||
},
|
||||
Value::ByVal(_) => Value::ByVal(PrimVal::Bytes(0)),
|
||||
@ -307,7 +308,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64;
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let result_ptr = self.pointer_offset(ptr, substs.type_at(0), offset)?;
|
||||
self.write_primval(dest, result_ptr, dest_ty)?;
|
||||
self.write_ptr(dest, result_ptr, dest_ty)?;
|
||||
}
|
||||
|
||||
"overflowing_sub" => {
|
||||
@ -397,7 +398,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let size = self.type_size(dest_ty)?.expect("transmute() type must be sized");
|
||||
let ptr = self.force_allocation(dest)?.to_ptr()?;
|
||||
self.memory.mark_packed(ptr, size);
|
||||
self.write_value_to_ptr(arg_vals[0], PrimVal::Ptr(ptr), src_ty)?;
|
||||
self.write_value_to_ptr(arg_vals[0], ptr.into(), src_ty)?;
|
||||
}
|
||||
|
||||
"unchecked_shl" => {
|
||||
|
@ -10,8 +10,7 @@ use error::{EvalError, EvalResult};
|
||||
use eval_context::{EvalContext, IntegerExt, StackPopCleanup, is_inhabited};
|
||||
use lvalue::Lvalue;
|
||||
use memory::{MemoryPointer, TlsKey};
|
||||
use value::PrimVal;
|
||||
use value::Value;
|
||||
use value::{PrimVal, Value};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
||||
mod drop;
|
||||
@ -569,7 +568,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
|
||||
}
|
||||
let ptr = self.memory.allocate(size, align)?;
|
||||
self.memory.write_repeat(PrimVal::Ptr(ptr), 0, size)?;
|
||||
self.memory.write_repeat(ptr.into(), 0, size)?;
|
||||
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
"alloc::heap::::__rust_dealloc" => {
|
||||
@ -705,7 +704,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
let arg_local = self.frame().mir.args_iter().next().ok_or(EvalError::AbiViolation("Argument to __rust_maybe_catch_panic does not take enough arguments.".to_owned()))?;
|
||||
let arg_dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
|
||||
self.write_primval(arg_dest, data, u8_ptr_ty)?;
|
||||
self.write_ptr(arg_dest, data, u8_ptr_ty)?;
|
||||
|
||||
// We ourselves return 0
|
||||
self.write_null(dest, dest_ty)?;
|
||||
@ -744,7 +743,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let num = self.value_to_primval(args[2], usize)?.to_u64()?;
|
||||
if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) {
|
||||
let new_ptr = ptr.offset(num - idx as u64 - 1, self.memory.layout)?;
|
||||
self.write_primval(dest, new_ptr, dest_ty)?;
|
||||
self.write_ptr(dest, new_ptr, dest_ty)?;
|
||||
} else {
|
||||
self.write_null(dest, dest_ty)?;
|
||||
}
|
||||
@ -756,7 +755,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let num = self.value_to_primval(args[2], usize)?.to_u64()?;
|
||||
if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) {
|
||||
let new_ptr = ptr.offset(idx as u64, self.memory.layout)?;
|
||||
self.write_primval(dest, new_ptr, dest_ty)?;
|
||||
self.write_ptr(dest, new_ptr, dest_ty)?;
|
||||
} else {
|
||||
self.write_null(dest, dest_ty)?;
|
||||
}
|
||||
@ -865,7 +864,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
"mmap" => {
|
||||
// This is a horrible hack, but well... the guard page mechanism calls mmap and expects a particular return value, so we give it that value
|
||||
let addr = args[0].read_ptr(&self.memory)?;
|
||||
self.write_primval(dest, addr, dest_ty)?;
|
||||
self.write_ptr(dest, addr, dest_ty)?;
|
||||
}
|
||||
|
||||
// Hook pthread calls that go to the thread-local storage memory subsystem
|
||||
@ -873,7 +872,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let key_ptr = args[0].read_ptr(&self.memory)?;
|
||||
|
||||
// Extract the function type out of the signature (that seems easier than constructing it ourselves...)
|
||||
let dtor = match args[1].read_ptr(&self.memory)? {
|
||||
let dtor = match args[1].read_ptr(&self.memory)?.into_inner_primval() {
|
||||
PrimVal::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?),
|
||||
PrimVal::Bytes(0) => None,
|
||||
PrimVal::Bytes(_) => return Err(EvalError::ReadBytesAsPointer),
|
||||
@ -910,7 +909,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
// The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
|
||||
let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
|
||||
let ptr = self.memory.load_tls(key)?;
|
||||
self.write_primval(dest, ptr, dest_ty)?;
|
||||
self.write_ptr(dest, ptr, dest_ty)?;
|
||||
}
|
||||
"pthread_setspecific" => {
|
||||
// The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
|
||||
|
87
src/value.rs
87
src/value.rs
@ -33,11 +33,70 @@ pub(super) fn f64_to_bytes(f: f64) -> u128 {
|
||||
/// operations and fat pointers. This idea was taken from rustc's trans.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Value {
|
||||
ByRef(PrimVal),
|
||||
ByRef(Pointer),
|
||||
ByVal(PrimVal),
|
||||
ByValPair(PrimVal, PrimVal),
|
||||
}
|
||||
|
||||
/// A wrapper type around `PrimVal` that cannot be turned back into a `PrimVal` accidentally.
|
||||
/// This type clears up a few APIs where having a `PrimVal` argument for something that is
|
||||
/// potentially an integer pointer or a pointer to an allocation was unclear.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Pointer {
|
||||
primval: PrimVal,
|
||||
}
|
||||
|
||||
impl<'tcx> Pointer {
|
||||
pub fn null() -> Self {
|
||||
PrimVal::Bytes(0).into()
|
||||
}
|
||||
pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
|
||||
self.primval.to_ptr()
|
||||
}
|
||||
pub fn into_inner_primval(self) -> PrimVal {
|
||||
self.primval
|
||||
}
|
||||
|
||||
pub(crate) fn signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
self.primval.signed_offset(i, layout).map(Pointer::from)
|
||||
}
|
||||
|
||||
pub(crate) fn offset(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
self.primval.offset(i, layout).map(Pointer::from)
|
||||
}
|
||||
|
||||
pub(crate) fn wrapping_signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
self.primval.wrapping_signed_offset(i, layout).map(Pointer::from)
|
||||
}
|
||||
|
||||
pub fn is_null(self) -> EvalResult<'tcx, bool> {
|
||||
match self.primval {
|
||||
PrimVal::Bytes(b) => Ok(b == 0),
|
||||
PrimVal::Ptr(_) => Ok(false),
|
||||
PrimVal::Undef => Err(EvalError::ReadUndefBytes),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_extra(self, extra: PrimVal) -> Value {
|
||||
Value::ByValPair(self.primval, extra)
|
||||
}
|
||||
pub fn to_value(self) -> Value {
|
||||
Value::ByVal(self.primval)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::From<PrimVal> for Pointer {
|
||||
fn from(primval: PrimVal) -> Self {
|
||||
Pointer { primval }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::From<MemoryPointer> for Pointer {
|
||||
fn from(ptr: MemoryPointer) -> Self {
|
||||
PrimVal::Ptr(ptr).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `PrimVal` represents an immediate, primitive value existing outside of a
|
||||
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
|
||||
/// size. Like a range of bytes in an `Allocation`, a `PrimVal` can either represent the raw bytes
|
||||
@ -69,18 +128,18 @@ pub enum PrimValKind {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a> Value {
|
||||
pub(super) fn read_ptr(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, PrimVal> {
|
||||
pub(super) fn read_ptr(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, Pointer> {
|
||||
use self::Value::*;
|
||||
match *self {
|
||||
ByRef(ptr) => mem.read_ptr(ptr.to_ptr()?),
|
||||
ByVal(ptr) | ByValPair(ptr, _) => Ok(ptr),
|
||||
ByVal(ptr) | ByValPair(ptr, _) => Ok(ptr.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn expect_ptr_vtable_pair(
|
||||
&self,
|
||||
mem: &Memory<'a, 'tcx>
|
||||
) -> EvalResult<'tcx, (PrimVal, MemoryPointer)> {
|
||||
) -> EvalResult<'tcx, (Pointer, MemoryPointer)> {
|
||||
use self::Value::*;
|
||||
match *self {
|
||||
ByRef(ref_ptr) => {
|
||||
@ -89,13 +148,13 @@ impl<'a, 'tcx: 'a> Value {
|
||||
Ok((ptr, vtable.to_ptr()?))
|
||||
}
|
||||
|
||||
ByValPair(ptr, vtable) => Ok((ptr, vtable.to_ptr()?)),
|
||||
ByValPair(ptr, vtable) => Ok((ptr.into(), vtable.to_ptr()?)),
|
||||
|
||||
_ => bug!("expected ptr and vtable, got {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn expect_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (PrimVal, u64)> {
|
||||
pub(super) fn expect_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (Pointer, u64)> {
|
||||
use self::Value::*;
|
||||
match *self {
|
||||
ByRef(ref_ptr) => {
|
||||
@ -106,7 +165,7 @@ impl<'a, 'tcx: 'a> Value {
|
||||
ByValPair(ptr, val) => {
|
||||
let len = val.to_u128()?;
|
||||
assert_eq!(len as u64 as u128, len);
|
||||
Ok((ptr, len as u64))
|
||||
Ok((ptr.into(), len as u64))
|
||||
},
|
||||
ByVal(_) => unimplemented!(),
|
||||
}
|
||||
@ -220,15 +279,7 @@ impl<'tcx> PrimVal {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_null(self) -> EvalResult<'tcx, bool> {
|
||||
match self {
|
||||
PrimVal::Bytes(b) => Ok(b == 0),
|
||||
PrimVal::Ptr(_) => Ok(false),
|
||||
PrimVal::Undef => Err(EvalError::ReadUndefBytes),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
pub(crate) fn signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
match self {
|
||||
PrimVal::Bytes(b) => {
|
||||
assert_eq!(b as u64 as u128, b);
|
||||
@ -239,7 +290,7 @@ impl<'tcx> PrimVal {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
pub(crate) fn offset(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
match self {
|
||||
PrimVal::Bytes(b) => {
|
||||
assert_eq!(b as u64 as u128, b);
|
||||
@ -250,7 +301,7 @@ impl<'tcx> PrimVal {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrapping_signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
pub(crate) fn wrapping_signed_offset(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
match self {
|
||||
PrimVal::Bytes(b) => {
|
||||
assert_eq!(b as u64 as u128, b);
|
||||
|
Loading…
x
Reference in New Issue
Block a user