From b174b786b6a0a0ad38101ead656a6fd02e086a05 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 20 Jul 2017 14:03:02 -0700 Subject: [PATCH] refactor casting code to more clearly handle pointers --- src/librustc_mir/interpret/cast.rs | 59 ++++++++++++++---------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 9789c1f0b2ac..7db8cb79f5d7 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -4,6 +4,7 @@ use syntax::ast::{FloatTy, IntTy, UintTy}; use error::{EvalResult, EvalError}; use eval_context::EvalContext; use value::PrimVal; +use memory::MemoryPointer; impl<'a, 'tcx> EvalContext<'a, 'tcx> { pub(super) fn cast_primval( @@ -14,36 +15,32 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ) -> EvalResult<'tcx, PrimVal> { let src_kind = self.ty_to_primval_kind(src_ty)?; - use value::PrimValKind::*; - match src_kind { - F32 => self.cast_float(val.to_f32()? as f64, dest_ty), - F64 => self.cast_float(val.to_f64()?, dest_ty), + match val { + PrimVal::Undef => Ok(PrimVal::Undef), + PrimVal::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty), + val @ PrimVal::Bytes(_) => { + use value::PrimValKind::*; + match src_kind { + F32 => self.cast_from_float(val.to_f32()? as f64, dest_ty), + F64 => self.cast_from_float(val.to_f64()?, dest_ty), - I8 | I16 | I32 | I64 | I128 => { - if val.is_ptr() { - self.cast_ptr(val, dest_ty) - } else { - self.cast_signed_int(val.to_i128()?, dest_ty) + I8 | I16 | I32 | I64 | I128 => { + self.cast_from_signed_int(val.to_i128()?, dest_ty) + }, + + Bool | Char | U8 | U16 | U32 | U64 | U128 | FnPtr | Ptr => { + self.cast_from_int(val.to_u128()?, dest_ty, false) + }, } - }, - - Bool | Char | U8 | U16 | U32 | U64 | U128 => { - if val.is_ptr() { - self.cast_ptr(val, dest_ty) - } else { - self.cast_int(val.to_u128()?, dest_ty, false) - } - }, - - FnPtr | Ptr => self.cast_ptr(val, dest_ty), + } } } - fn cast_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { - self.cast_int(val as u128, ty, val < 0) + fn cast_from_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { + self.cast_from_int(val as u128, ty, val < 0) } - fn cast_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> { + fn cast_from_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> { use rustc::ty::TypeVariants::*; match ty.sty { // Casts to bool are not permitted by rustc, no need to handle them here. @@ -63,13 +60,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { TyInt(IntTy::Is) => { let int_ty = self.tcx.sess.target.int_type; let ty = self.tcx.mk_mach_int(int_ty); - self.cast_int(v, ty, negative) + self.cast_from_int(v, ty, negative) } TyUint(UintTy::Us) => { let uint_ty = self.tcx.sess.target.uint_type; let ty = self.tcx.mk_mach_uint(uint_ty); - self.cast_int(v, ty, negative) + self.cast_from_int(v, ty, negative) } TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i128 as f64)), @@ -87,14 +84,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - fn cast_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { + fn cast_from_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { use rustc::ty::TypeVariants::*; match ty.sty { // Casting negative floats to unsigned integers yields zero. - TyUint(_) if val < 0.0 => self.cast_int(0, ty, false), - TyInt(_) if val < 0.0 => self.cast_int(val as i128 as u128, ty, true), + TyUint(_) if val < 0.0 => self.cast_from_int(0, ty, false), + TyInt(_) if val < 0.0 => self.cast_from_int(val as i128 as u128, ty, true), - TyInt(_) | ty::TyUint(_) => self.cast_int(val as u128, ty, false), + TyInt(_) | ty::TyUint(_) => self.cast_from_int(val as u128, ty, false), TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(val)), TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(val as f32)), @@ -102,12 +99,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - fn cast_ptr(&self, ptr: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { + fn cast_from_ptr(&self, ptr: MemoryPointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { use rustc::ty::TypeVariants::*; match ty.sty { // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here. TyRawPtr(_) | TyInt(IntTy::Is) | TyUint(UintTy::Us) => - Ok(ptr), + Ok(PrimVal::Ptr(ptr)), TyInt(_) | TyUint(_) => Err(EvalError::ReadPointerAsBytes), _ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))), }