replace `panic!`s with `Result`

上级 55ce704a
use std::error::Error;
use std::fmt;
use rustc::mir::repr as mir;
#[derive(Clone, Debug)]
pub enum EvalError {
......@@ -11,6 +12,8 @@ pub enum EvalError {
ReadBytesAsPointer,
InvalidPointerMath,
ReadUndefBytes,
InvalidBoolOp(mir::BinOp),
Unimplemented(String),
}
pub type EvalResult<T> = Result<T, EvalError>;
......@@ -34,6 +37,9 @@ fn description(&self) -> &str {
"attempted to do math or a comparison on pointers into different allocations",
EvalError::ReadUndefBytes =>
"attempted to read undefined bytes",
EvalError::InvalidBoolOp(_) =>
"invalid boolean operation",
EvalError::Unimplemented(ref msg) => msg,
}
}
......
......@@ -392,11 +392,11 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
TerminatorTarget::Call
}
abi => panic!("can't handle function with {:?} ABI", abi),
abi => return Err(EvalError::Unimplemented(format!("can't handle function with {:?} ABI", abi))),
}
}
_ => panic!("can't handle callee of type {:?}", func_ty),
_ => return Err(EvalError::Unimplemented(format!("can't handle callee of type {:?}", func_ty))),
}
}
......@@ -470,7 +470,7 @@ fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalRes
}
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
let offset = self.nonnull_offset(adt_ty, nndiscr, discrfield);
let offset = self.nonnull_offset(adt_ty, nndiscr, discrfield)?;
let nonnull = adt_ptr.offset(offset.bytes() as isize);
self.read_nonnull_discriminant_value(nonnull, nndiscr)?
}
......@@ -620,7 +620,7 @@ fn call_intrinsic(
self.memory.write_uint(dest, n * elem_size, dest_size)?;
}
_ => panic!("unimplemented: size_of_val::<{:?}>", ty),
_ => return Err(EvalError::Unimplemented(format!("unimplemented: size_of_val::<{:?}>", ty))),
}
}
}
......@@ -631,7 +631,7 @@ fn call_intrinsic(
}
"uninit" => self.memory.mark_definedness(dest, dest_size, false)?,
name => panic!("can't handle intrinsic: {}", name),
name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))),
}
// Since we pushed no stack frame, the main loop will act
......@@ -693,7 +693,7 @@ fn call_c_abi(
self.memory.write_int(dest, result, dest_size)?;
}
_ => panic!("can't call C ABI function: {}", link_name),
_ => return Err(EvalError::Unimplemented(format!("can't call C ABI function: {}", link_name))),
}
// Since we pushed no stack frame, the main loop will act
......@@ -748,7 +748,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
let ptr = self.eval_operand(operand)?;
let ty = self.operand_ty(operand);
let val = self.read_primval(ptr, ty)?;
self.memory.write_primval(dest, primval::unary_op(un_op, val))?;
self.memory.write_primval(dest, primval::unary_op(un_op, val)?)?;
}
Aggregate(ref kind, ref operands) => {
......@@ -809,7 +809,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
try!(self.assign_fields(dest, offsets, operands));
} else {
assert_eq!(operands.len(), 0);
let offset = self.nonnull_offset(dest_ty, nndiscr, discrfield);
let offset = self.nonnull_offset(dest_ty, nndiscr, discrfield)?;
let dest = dest.offset(offset.bytes() as isize);
try!(self.memory.write_isize(dest, 0));
}
......@@ -834,8 +834,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
}
}
_ => panic!("can't handle destination layout {:?} when assigning {:?}",
dest_layout, kind),
_ => return Err(EvalError::Unimplemented(format!("can't handle destination layout {:?} when assigning {:?}", dest_layout, kind))),
}
}
......@@ -904,7 +903,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
self.memory.write_usize(len_ptr, length as u64)?;
}
_ => panic!("can't handle cast: {:?}", rvalue),
_ => return Err(EvalError::Unimplemented(format!("can't handle cast: {:?}", rvalue))),
}
}
......@@ -914,7 +913,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
self.memory.copy(src, dest, size)?;
}
_ => panic!("can't handle cast: {:?}", rvalue),
_ => return Err(EvalError::Unimplemented(format!("can't handle cast: {:?}", rvalue))),
}
}
......@@ -925,7 +924,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
Ok(())
}
fn nonnull_offset(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> Size {
fn nonnull_offset(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> EvalResult<Size> {
// Skip the constant 0 at the start meant for LLVM GEP.
let mut path = discrfield.iter().skip(1).map(|&i| i as usize);
......@@ -946,49 +945,49 @@ fn nonnull_offset(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> Size
self.field_path_offset(inner_ty, path)
}
fn field_path_offset<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I) -> Size {
fn field_path_offset<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I) -> EvalResult<Size> {
let mut offset = Size::from_bytes(0);
// Skip the initial 0 intended for LLVM GEP.
for field_index in path {
let field_offset = self.get_field_offset(ty, field_index);
ty = self.get_field_ty(ty, field_index);
let field_offset = self.get_field_offset(ty, field_index)?;
ty = self.get_field_ty(ty, field_index)?;
offset = offset.checked_add(field_offset, &self.tcx.data_layout).unwrap();
}
offset
Ok(offset)
}
fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> Ty<'tcx> {
fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<Ty<'tcx>> {
match ty.sty {
ty::TyStruct(adt_def, substs) => {
adt_def.struct_variant().fields[field_index].ty(self.tcx, substs)
Ok(adt_def.struct_variant().fields[field_index].ty(self.tcx, substs))
}
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
ty::TyBox(ty) => {
assert_eq!(field_index, 0);
ty
Ok(ty)
}
_ => panic!("can't handle type: {:?}", ty),
_ => Err(EvalError::Unimplemented(format!("can't handle type: {:?}", ty))),
}
}
fn get_field_offset(&self, ty: Ty<'tcx>, field_index: usize) -> Size {
fn get_field_offset(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<Size> {
let layout = self.type_layout(ty);
use rustc::ty::layout::Layout::*;
match *layout {
Univariant { .. } => {
assert_eq!(field_index, 0);
Size::from_bytes(0)
Ok(Size::from_bytes(0))
}
FatPointer { .. } => {
let bytes = layout::FAT_PTR_ADDR * self.memory.pointer_size;
Size::from_bytes(bytes as u64)
Ok(Size::from_bytes(bytes as u64))
}
_ => panic!("can't handle type: {:?}, with layout: {:?}", ty, layout),
_ => Err(EvalError::Unimplemented(format!("can't handle type: {:?}, with layout: {:?}", ty, layout))),
}
}
......@@ -1223,7 +1222,7 @@ pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<PrimVal
Err(e) => return Err(e),
}
} else {
panic!("unimplemented: primitive read of fat pointer type: {:?}", ty);
return Err(EvalError::Unimplemented(format!("unimplemented: primitive read of fat pointer type: {:?}", ty)));
}
}
......
......@@ -80,7 +80,7 @@ pub fn allocate(&mut self, size: usize) -> Pointer {
pub fn reallocate(&mut self, ptr: Pointer, new_size: usize) -> EvalResult<()> {
if ptr.offset != 0 {
// TODO(solson): Report error about non-__rust_allocate'd pointer.
panic!()
return Err(EvalError::Unimplemented(format!("bad pointer offset: {}", ptr.offset)));
}
let alloc = self.get_mut(ptr.alloc_id)?;
......@@ -90,7 +90,7 @@ pub fn reallocate(&mut self, ptr: Pointer, new_size: usize) -> EvalResult<()> {
alloc.bytes.extend(iter::repeat(0).take(amount));
alloc.undef_mask.grow(amount, false);
} else if size > new_size {
unimplemented!()
return Err(EvalError::Unimplemented(format!("unimplemented allocation relocation")));
// alloc.bytes.truncate(new_size);
// alloc.undef_mask.len = new_size;
// TODO: potentially remove relocations
......@@ -103,7 +103,7 @@ pub fn reallocate(&mut self, ptr: Pointer, new_size: usize) -> EvalResult<()> {
pub fn deallocate(&mut self, ptr: Pointer) -> EvalResult<()> {
if ptr.offset != 0 {
// TODO(solson): Report error about non-__rust_allocate'd pointer.
panic!()
return Err(EvalError::Unimplemented(format!("bad pointer offset: {}", ptr.offset)));
}
if self.alloc_map.remove(&ptr.alloc_id).is_none() {
......
......@@ -74,8 +74,7 @@ fn unrelated_ptr_ops(bin_op: mir::BinOp) -> EvalResult<PrimVal> {
BitOr => l | r,
BitXor => l ^ r,
BitAnd => l & r,
Add | Sub | Mul | Div | Rem | Shl | Shr =>
panic!("invalid binary operation on booleans: {:?}", bin_op),
Add | Sub | Mul | Div | Rem | Shl | Shr => return Err(EvalError::InvalidBoolOp(bin_op)),
})
}
......@@ -99,33 +98,33 @@ fn unrelated_ptr_ops(bin_op: mir::BinOp) -> EvalResult<PrimVal> {
Le => Bool(l <= r),
Gt => Bool(l > r),
Ge => Bool(l >= r),
_ => unimplemented!(),
_ => return Err(EvalError::Unimplemented(format!("unimplemented ptr op: {:?}", bin_op))),
}
}
_ => unimplemented!(),
(l, r) => return Err(EvalError::Unimplemented(format!("unimplemented binary op: {:?}, {:?}, {:?}", l, r, bin_op))),
};
Ok(val)
}
pub fn unary_op(un_op: mir::UnOp, val: PrimVal) -> PrimVal {
pub fn unary_op(un_op: mir::UnOp, val: PrimVal) -> EvalResult<PrimVal> {
use rustc::mir::repr::UnOp::*;
use self::PrimVal::*;
match (un_op, val) {
(Not, Bool(b)) => Bool(!b),
(Not, I8(n)) => I8(!n),
(Neg, I8(n)) => I8(-n),
(Not, I16(n)) => I16(!n),
(Neg, I16(n)) => I16(-n),
(Not, I32(n)) => I32(!n),
(Neg, I32(n)) => I32(-n),
(Not, I64(n)) => I64(!n),
(Neg, I64(n)) => I64(-n),
(Not, U8(n)) => U8(!n),
(Not, U16(n)) => U16(!n),
(Not, U32(n)) => U32(!n),
(Not, U64(n)) => U64(!n),
_ => unimplemented!(),
(Not, Bool(b)) => Ok(Bool(!b)),
(Not, I8(n)) => Ok(I8(!n)),
(Neg, I8(n)) => Ok(I8(-n)),
(Not, I16(n)) => Ok(I16(!n)),
(Neg, I16(n)) => Ok(I16(-n)),
(Not, I32(n)) => Ok(I32(!n)),
(Neg, I32(n)) => Ok(I32(-n)),
(Not, I64(n)) => Ok(I64(!n)),
(Neg, I64(n)) => Ok(I64(-n)),
(Not, U8(n)) => Ok(U8(!n)),
(Not, U16(n)) => Ok(U16(!n)),
(Not, U32(n)) => Ok(U32(!n)),
(Not, U64(n)) => Ok(U64(!n)),
_ => Err(EvalError::Unimplemented(format!("unimplemented unary op: {:?}, {:?}", un_op, val))),
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册