From b78ca5f7e1e07d1f6e6980a1af0d7f4315978362 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 30 May 2016 15:27:52 +0200 Subject: [PATCH] replace `panic!`s with `Result` --- src/error.rs | 6 ++++++ src/interpreter.rs | 51 +++++++++++++++++++++++----------------------- src/memory.rs | 6 +++--- src/primval.rs | 37 ++++++++++++++++----------------- 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/error.rs b/src/error.rs index 65dd187fa0b..ec75ab44526 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,6 @@ 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 = Result; @@ -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, } } diff --git a/src/interpreter.rs b/src/interpreter.rs index 8e8565b50c5..8734427f07f 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -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 { // 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>(&self, mut ty: Ty<'tcx>, path: I) -> Size { + fn field_path_offset>(&self, mut ty: Ty<'tcx>, path: I) -> EvalResult { 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> { 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 { 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 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))); } } diff --git a/src/memory.rs b/src/memory.rs index a42fd54669b..d69e07ae2a2 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -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() { diff --git a/src/primval.rs b/src/primval.rs index 19faadc962e..0b1658739d9 100644 --- a/src/primval.rs +++ b/src/primval.rs @@ -74,8 +74,7 @@ fn unrelated_ptr_ops(bin_op: mir::BinOp) -> EvalResult { 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 { 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 { 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))), } } -- 2.44.0