refactor casting code to more clearly handle pointers
This commit is contained in:
parent
f960f4c537
commit
b174b786b6
1 changed files with 28 additions and 31 deletions
|
|
@ -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))),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue