1
Fork 0

Turn invalid panics into Results and rename fns.

This commit is contained in:
Scott Olson 2016-12-16 22:01:01 -08:00
parent 33f97feafb
commit f83c45e367
6 changed files with 86 additions and 94 deletions

View file

@ -17,14 +17,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
use value::PrimValKind::*;
match kind {
F32 => self.cast_float(val.to_f32() as f64, dest_ty),
F64 => self.cast_float(val.to_f64(), dest_ty),
F32 => self.cast_float(val.to_f32()? as f64, dest_ty),
F64 => self.cast_float(val.to_f64()?, dest_ty),
I8 | I16 | I32 | I64 => self.cast_signed_int(val.bits() as i64, dest_ty),
Bool | Char | U8 | U16 | U32 | U64 => self.cast_int(val.bits(), dest_ty, false),
FnPtr | Ptr => self.cast_ptr(val.to_ptr(), dest_ty),
FnPtr | Ptr => self.cast_ptr(val.to_ptr()?, dest_ty),
}
}

View file

@ -279,7 +279,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized");
let n_ptr = self.eval_operand(operand)?;
let usize = self.tcx.types.usize;
let n = self.value_to_primval(n_ptr, usize)?.to_u64();
let n = self.value_to_primval(n_ptr, usize)?.to_u64()?;
assert!(n < len);
let ptr = base_ptr.offset(n * elem_size);
(ptr, LvalueExtra::None)

View file

@ -142,8 +142,8 @@ pub fn binary_op<'tcx>(
// If the pointers are into the same allocation, fall through to the more general match
// later, which will do comparisons on the `bits` fields, which are the pointer offsets
// in this case.
let left_ptr = left.to_ptr();
let right_ptr = right.to_ptr();
let left_ptr = left.to_ptr()?;
let right_ptr = right.to_ptr()?;
if left_ptr.alloc_id != right_ptr.alloc_id {
return Ok((unrelated_ptr_ops(bin_op, left_ptr, right_ptr)?, false));
}

View file

@ -45,14 +45,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
"arith_offset" => {
let ptr = arg_vals[0].read_ptr(&self.memory)?;
let offset = self.value_to_primval(arg_vals[1], isize)?.to_i64();
let offset = self.value_to_primval(arg_vals[1], isize)?.to_i64()?;
let new_ptr = ptr.signed_offset(offset);
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
}
"assume" => {
let bool = self.tcx.types.bool;
let cond = self.value_to_primval(arg_vals[0], bool)?.try_as_bool()?;
let cond = self.value_to_primval(arg_vals[0], bool)?.to_bool()?;
if !cond { return Err(EvalError::AssumptionNotHeld); }
}
@ -152,7 +152,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let elem_align = self.type_align(elem_ty)?;
let src = arg_vals[0].read_ptr(&self.memory)?;
let dest = arg_vals[1].read_ptr(&self.memory)?;
let count = self.value_to_primval(arg_vals[2], usize)?.to_u64();
let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?;
self.memory.copy(src, dest, count * elem_size, elem_align)?;
}
@ -180,12 +180,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let ptr_ty = self.tcx.mk_mut_ptr(ty);
let lvalue = match self.follow_by_ref_value(arg_vals[0], ptr_ty)? {
Value::ByRef(_) => bug!("follow_by_ref_value returned ByRef"),
Value::ByVal(value) => Lvalue::from_ptr(value.to_ptr()),
Value::ByVal(value) => Lvalue::from_ptr(value.to_ptr()?),
Value::ByValPair(ptr, extra) => Lvalue::Ptr {
ptr: ptr.to_ptr(),
ptr: ptr.to_ptr()?,
extra: match self.tcx.struct_tail(ty).sty {
ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()),
ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.try_as_uint()?),
ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()?),
ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u64()?),
_ => bug!("invalid fat pointer type: {}", ptr_ty),
},
},
@ -204,12 +204,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
"fabsf32" => {
let f = self.value_to_primval(arg_vals[2], f32)?.to_f32();
let f = self.value_to_primval(arg_vals[2], f32)?.to_f32()?;
self.write_primval(dest, PrimVal::from_f32(f.abs()), dest_ty)?;
}
"fabsf64" => {
let f = self.value_to_primval(arg_vals[2], f64)?.to_f64();
let f = self.value_to_primval(arg_vals[2], f64)?.to_f64()?;
self.write_primval(dest, PrimVal::from_f64(f.abs()), dest_ty)?;
}
@ -288,7 +288,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let pointee_ty = substs.type_at(0);
// 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 = self.value_to_primval(arg_vals[1], isize)?.to_i64();
let offset = self.value_to_primval(arg_vals[1], isize)?.to_i64()?;
let ptr = arg_vals[0].read_ptr(&self.memory)?;
let result_ptr = ptr.signed_offset(offset * pointee_size);
@ -308,24 +308,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
"powif32" => {
let f = self.value_to_primval(arg_vals[0], f32)?.to_f32();
let i = self.value_to_primval(arg_vals[1], i32)?.to_i64();
let f = self.value_to_primval(arg_vals[0], f32)?.to_f32()?;
let i = self.value_to_primval(arg_vals[1], i32)?.to_i64()?;
self.write_primval(dest, PrimVal::from_f32(f.powi(i as i32)), dest_ty)?;
}
"powif64" => {
let f = self.value_to_primval(arg_vals[0], f64)?.to_f64();
let i = self.value_to_primval(arg_vals[1], i32)?.to_i64();
let f = self.value_to_primval(arg_vals[0], f64)?.to_f64()?;
let i = self.value_to_primval(arg_vals[1], i32)?.to_i64()?;
self.write_primval(dest, PrimVal::from_f64(f.powi(i as i32)), dest_ty)?;
}
"sqrtf32" => {
let f = self.value_to_primval(arg_vals[0], f32)?.to_f32();
let f = self.value_to_primval(arg_vals[0], f32)?.to_f32()?;
self.write_primval(dest, PrimVal::from_f32(f.sqrt()), dest_ty)?;
}
"sqrtf64" => {
let f = self.value_to_primval(arg_vals[0], f64)?.to_f64();
let f = self.value_to_primval(arg_vals[0], f64)?.to_f64()?;
self.write_primval(dest, PrimVal::from_f64(f.sqrt()), dest_ty)?;
}

View file

@ -38,7 +38,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Goto { target } => self.goto_block(target),
If { ref cond, targets: (then_target, else_target) } => {
let cond_val = self.eval_operand_to_primval(cond)?.try_as_bool()?;
let cond_val = self.eval_operand_to_primval(cond)?.to_bool()?;
self.goto_block(if cond_val { then_target } else { else_target });
}
@ -88,7 +88,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let func_ty = self.operand_ty(func);
match func_ty.sty {
ty::TyFnPtr(bare_fn_ty) => {
let fn_ptr = self.eval_operand_to_primval(func)?.to_ptr();
let fn_ptr = self.eval_operand_to_primval(func)?.to_ptr()?;
let (def_id, substs, abi, sig) = self.memory.get_fn(fn_ptr.alloc_id)?;
let bare_sig = self.tcx.erase_late_bound_regions_and_normalize(&bare_fn_ty.sig);
let bare_sig = self.tcx.erase_regions(&bare_sig);
@ -132,7 +132,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
Assert { ref cond, expected, ref msg, target, .. } => {
let cond_val = self.eval_operand_to_primval(cond)?.try_as_bool()?;
let cond_val = self.eval_operand_to_primval(cond)?.to_bool()?;
if expected == cond_val {
self.goto_block(target);
} else {
@ -141,10 +141,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let span = terminator.source_info.span;
let len = self.eval_operand_to_primval(len)
.expect("can't eval len")
.to_u64();
.to_u64()?;
let index = self.eval_operand_to_primval(index)
.expect("can't eval index")
.to_u64();
.to_u64()?;
Err(EvalError::ArrayIndexOutOfBounds(span, len, index))
},
mir::AssertMessage::Math(ref err) =>
@ -333,8 +333,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
match &link_name[..] {
"__rust_allocate" => {
let size = self.value_to_primval(args[0], usize)?.to_u64();
let align = self.value_to_primval(args[1], usize)?.to_u64();
let size = self.value_to_primval(args[0], usize)?.to_u64()?;
let align = self.value_to_primval(args[1], usize)?.to_u64()?;
let ptr = self.memory.allocate(size, align)?;
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
}
@ -342,15 +342,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
"__rust_deallocate" => {
let ptr = args[0].read_ptr(&self.memory)?;
// FIXME: insert sanity check for size and align?
let _old_size = self.value_to_primval(args[1], usize)?.to_u64();
let _align = self.value_to_primval(args[2], usize)?.to_u64();
let _old_size = self.value_to_primval(args[1], usize)?.to_u64()?;
let _align = self.value_to_primval(args[2], usize)?.to_u64()?;
self.memory.deallocate(ptr)?;
},
"__rust_reallocate" => {
let ptr = args[0].read_ptr(&self.memory)?;
let size = self.value_to_primval(args[2], usize)?.to_u64();
let align = self.value_to_primval(args[3], usize)?.to_u64();
let size = self.value_to_primval(args[2], usize)?.to_u64()?;
let align = self.value_to_primval(args[3], usize)?.to_u64()?;
let new_ptr = self.memory.reallocate(ptr, size, align)?;
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
}
@ -358,7 +358,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
"memcmp" => {
let left = args[0].read_ptr(&self.memory)?;
let right = args[1].read_ptr(&self.memory)?;
let n = self.value_to_primval(args[2], usize)?.to_u64();
let n = self.value_to_primval(args[2], usize)?.to_u64()?;
let result = {
let left_bytes = self.memory.read_bytes(left, n)?;
@ -377,13 +377,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
"memchr" => {
let ptr = args[0].read_ptr(&self.memory)?;
let val = self.value_to_primval(args[1], usize)?.to_u64() as u8;
let num = self.value_to_primval(args[2], usize)?.to_u64();
let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
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.write_value(Value::ByVal(PrimVal::from_ptr(new_ptr)), dest, dest_ty)?;
self.write_value(Value::ByVal(PrimVal::Ptr(new_ptr)), dest, dest_ty)?;
} else {
self.write_value(Value::ByVal(PrimVal::new(0)), dest, dest_ty)?;
self.write_value(Value::ByVal(PrimVal::Bytes(0)), dest, dest_ty)?;
}
}
@ -393,12 +393,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let name = self.memory.read_c_str(name_ptr)?;
info!("ignored env var request for `{:?}`", ::std::str::from_utf8(name));
}
self.write_value(Value::ByVal(PrimVal::new(0)), dest, dest_ty)?;
self.write_value(Value::ByVal(PrimVal::Bytes(0)), dest, dest_ty)?;
}
// unix panic code inside libstd will read the return value of this function
"pthread_rwlock_rdlock" => {
self.write_primval(dest, PrimVal::new(0), dest_ty)?;
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
}
link_name if link_name.starts_with("pthread_") => {
@ -594,14 +594,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Value::ByRef(_) => bug!("follow_by_ref_value can't result in ByRef"),
Value::ByVal(ptr) => {
assert!(self.type_is_sized(contents_ty));
let contents_ptr = ptr.to_ptr();
let contents_ptr = ptr.to_ptr()?;
self.drop(Lvalue::from_ptr(contents_ptr), contents_ty, drop)?;
},
Value::ByValPair(prim_ptr, extra) => {
let ptr = prim_ptr.to_ptr();
let ptr = prim_ptr.to_ptr()?;
let extra = match self.tcx.struct_tail(contents_ty).sty {
ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()),
ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.try_as_uint()?),
ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()?),
ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u64()?),
_ => bug!("invalid fat pointer type: {}", ty),
};
self.drop(

View file

@ -78,7 +78,7 @@ impl<'a, 'tcx: 'a> Value {
use self::Value::*;
match *self {
ByRef(ptr) => mem.read_ptr(ptr),
ByVal(ptr) | ByValPair(ptr, _) => Ok(ptr.to_ptr()),
ByVal(ptr) | ByValPair(ptr, _) => ptr.to_ptr(),
}
}
@ -94,7 +94,7 @@ impl<'a, 'tcx: 'a> Value {
Ok((ptr, vtable))
}
ByValPair(ptr, vtable) => Ok((ptr.to_ptr(), vtable.to_ptr())),
ByValPair(ptr, vtable) => Ok((ptr.to_ptr()?, vtable.to_ptr()?)),
_ => bug!("expected ptr and vtable, got {:?}", self),
}
@ -109,18 +109,18 @@ impl<'a, 'tcx: 'a> Value {
Ok((ptr, len))
},
ByValPair(ptr, val) => {
Ok((ptr.to_ptr(), val.try_as_uint()?))
Ok((ptr.to_ptr()?, val.to_u64()?))
},
_ => unimplemented!(),
}
}
}
impl PrimVal {
impl<'tcx> PrimVal {
// FIXME(solson): Remove this. It's a temporary function to aid refactoring, but it shouldn't
// stick around with this name.
pub fn bits(&self) -> u64 {
match *self {
pub fn bits(self) -> u64 {
match self {
PrimVal::Bytes(b) => b,
PrimVal::Ptr(p) => p.offset,
PrimVal::Undef => panic!(".bits()() on PrimVal::Undef"),
@ -129,30 +129,14 @@ impl PrimVal {
// FIXME(solson): Remove this. It's a temporary function to aid refactoring, but it shouldn't
// stick around with this name.
pub fn relocation(&self) -> Option<AllocId> {
if let PrimVal::Ptr(ref p) = *self {
pub fn relocation(self) -> Option<AllocId> {
if let PrimVal::Ptr(ref p) = self {
Some(p.alloc_id)
} else {
None
}
}
pub fn from_bool(b: bool) -> Self {
PrimVal::Bytes(b as u64)
}
pub fn from_char(c: char) -> Self {
PrimVal::Bytes(c as u64)
}
pub fn from_f32(f: f32) -> Self {
PrimVal::Bytes(f32_to_bits(f))
}
pub fn from_f64(f: f64) -> Self {
PrimVal::Bytes(f64_to_bits(f))
}
pub fn from_uint(n: u64) -> Self {
PrimVal::Bytes(n)
}
@ -161,48 +145,56 @@ impl PrimVal {
PrimVal::Bytes(n as u64)
}
pub fn to_f32(self) -> f32 {
assert!(self.relocation().is_none());
bits_to_f32(self.bits())
pub fn from_f32(f: f32) -> Self {
PrimVal::Bytes(f32_to_bits(f))
}
pub fn to_f64(self) -> f64 {
assert!(self.relocation().is_none());
bits_to_f64(self.bits())
pub fn from_f64(f: f64) -> Self {
PrimVal::Bytes(f64_to_bits(f))
}
pub fn to_ptr(self) -> Pointer {
self.relocation().map(|alloc_id| {
Pointer::new(alloc_id, self.bits())
}).unwrap_or_else(|| Pointer::from_int(self.bits()))
pub fn from_bool(b: bool) -> Self {
PrimVal::Bytes(b as u64)
}
pub fn try_as_uint<'tcx>(self) -> EvalResult<'tcx, u64> {
self.to_ptr().to_int()
pub fn from_char(c: char) -> Self {
PrimVal::Bytes(c as u64)
}
pub fn to_u64(self) -> u64 {
if let Some(ptr) = self.try_as_ptr() {
return ptr.to_int().expect("non abstract ptr") as u64;
fn to_bytes(self) -> EvalResult<'tcx, u64> {
match self {
PrimVal::Bytes(b) => Ok(b),
PrimVal::Ptr(p) => p.to_int(),
PrimVal::Undef => Err(EvalError::ReadUndefBytes),
}
self.bits()
}
pub fn to_i64(self) -> i64 {
if let Some(ptr) = self.try_as_ptr() {
return ptr.to_int().expect("non abstract ptr") as i64;
pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
match self {
PrimVal::Bytes(b) => Ok(Pointer::from_int(b)),
PrimVal::Ptr(p) => Ok(p),
PrimVal::Undef => Err(EvalError::ReadUndefBytes),
}
self.bits() as i64
}
pub fn try_as_ptr(self) -> Option<Pointer> {
self.relocation().map(|alloc_id| {
Pointer::new(alloc_id, self.bits())
})
pub fn to_u64(self) -> EvalResult<'tcx, u64> {
self.to_bytes()
}
pub fn try_as_bool<'tcx>(self) -> EvalResult<'tcx, bool> {
match self.bits() {
pub fn to_i64(self) -> EvalResult<'tcx, i64> {
self.to_bytes().map(|b| b as i64)
}
pub fn to_f32(self) -> EvalResult<'tcx, f32> {
self.to_bytes().map(bits_to_f32)
}
pub fn to_f64(self) -> EvalResult<'tcx, f64> {
self.to_bytes().map(bits_to_f64)
}
pub fn to_bool(self) -> EvalResult<'tcx, bool> {
match self.to_bytes()? {
0 => Ok(false),
1 => Ok(true),
_ => Err(EvalError::InvalidBool),