提交 4fe41ad8 编写于 作者: S Scott Olson

Refactor PrimVal::bits() out of existence.

上级 9e244251
...@@ -20,9 +20,9 @@ pub(super) fn cast_primval( ...@@ -20,9 +20,9 @@ pub(super) fn cast_primval(
F32 => self.cast_float(val.to_f32()? as f64, dest_ty), F32 => self.cast_float(val.to_f32()? as f64, dest_ty),
F64 => self.cast_float(val.to_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), I8 | I16 | I32 | I64 => self.cast_signed_int(val.to_i64()?, dest_ty),
Bool | Char | U8 | U16 | U32 | U64 => self.cast_int(val.bits(), dest_ty, false), Bool | Char | U8 | U16 | U32 | U64 => self.cast_int(val.to_u64()?, dest_ty, false),
FnPtr | Ptr => self.cast_ptr(val.to_ptr()?, dest_ty), FnPtr | Ptr => self.cast_ptr(val.to_ptr()?, dest_ty),
} }
......
...@@ -1093,10 +1093,10 @@ pub(super) fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVa ...@@ -1093,10 +1093,10 @@ pub(super) fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVa
fn ensure_valid_value(&self, val: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, ()> { fn ensure_valid_value(&self, val: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, ()> {
match ty.sty { match ty.sty {
ty::TyBool if val.bits() > 1 => Err(EvalError::InvalidBool), ty::TyBool if val.to_bytes()? > 1 => Err(EvalError::InvalidBool),
ty::TyChar if ::std::char::from_u32(val.bits() as u32).is_none() ty::TyChar if ::std::char::from_u32(val.to_bytes()? as u32).is_none()
=> Err(EvalError::InvalidChar(val.bits() as u32 as u64)), => Err(EvalError::InvalidChar(val.to_bytes()? as u32 as u64)),
_ => Ok(()), _ => Ok(()),
} }
......
...@@ -77,8 +77,7 @@ pub fn points_to_zst(&self) -> bool { ...@@ -77,8 +77,7 @@ pub fn points_to_zst(&self) -> bool {
pub fn to_int<'tcx>(&self) -> EvalResult<'tcx, u64> { pub fn to_int<'tcx>(&self) -> EvalResult<'tcx, u64> {
match self.alloc_id { match self.alloc_id {
NEVER_ALLOC_ID | NEVER_ALLOC_ID => Ok(self.offset),
ZST_ALLOC_ID => Ok(self.offset),
_ => Err(EvalError::ReadPointerAsBytes), _ => Err(EvalError::ReadPointerAsBytes),
} }
} }
......
...@@ -139,16 +139,38 @@ pub fn binary_op<'tcx>( ...@@ -139,16 +139,38 @@ pub fn binary_op<'tcx>(
use rustc::mir::BinOp::*; use rustc::mir::BinOp::*;
use value::PrimValKind::*; use value::PrimValKind::*;
// If the pointers are into the same allocation, fall through to the more general match // FIXME(solson): Temporary hack. It will go away when we get rid of Pointer's ability to store
// later, which will do comparisons on the `bits` fields, which are the pointer offsets // plain bytes, and leave that to PrimVal::Bytes.
// in this case. fn normalize(val: PrimVal) -> PrimVal {
let left_ptr = left.to_ptr()?; if let PrimVal::Ptr(ptr) = val {
let right_ptr = right.to_ptr()?; if let Ok(bytes) = ptr.to_int() {
if left_ptr.alloc_id != right_ptr.alloc_id { return PrimVal::Bytes(bytes);
return Ok((unrelated_ptr_ops(bin_op, left_ptr, right_ptr)?, false)); }
}
val
} }
let (left, right) = (normalize(left), normalize(right));
let (l, r) = match (left, right) {
(PrimVal::Bytes(left_bytes), PrimVal::Bytes(right_bytes)) => (left_bytes, right_bytes),
(PrimVal::Ptr(left_ptr), PrimVal::Ptr(right_ptr)) => {
if left_ptr.alloc_id == right_ptr.alloc_id {
// If the pointers are into the same allocation, fall through to the more general
// match later, which will do comparisons on the pointer offsets.
(left_ptr.offset, right_ptr.offset)
} else {
return Ok((unrelated_ptr_ops(bin_op, left_ptr, right_ptr)?, false));
}
}
(PrimVal::Ptr(ptr), PrimVal::Bytes(bytes)) |
(PrimVal::Bytes(bytes), PrimVal::Ptr(ptr)) => {
return Ok((unrelated_ptr_ops(bin_op, ptr, Pointer::from_int(bytes))?, false));
}
let (l, r) = (left.bits(), right.bits()); (PrimVal::Undef, _) | (_, PrimVal::Undef) => return Err(EvalError::ReadUndefBytes),
};
// These ops can have an RHS with a different numeric type. // These ops can have an RHS with a different numeric type.
if bin_op == Shl || bin_op == Shr { if bin_op == Shl || bin_op == Shr {
...@@ -165,11 +187,11 @@ pub fn binary_op<'tcx>( ...@@ -165,11 +187,11 @@ pub fn binary_op<'tcx>(
// Cast to `u32` because `overflowing_sh{l,r}` only take `u32`, then apply the bitmask // Cast to `u32` because `overflowing_sh{l,r}` only take `u32`, then apply the bitmask
// to ensure it's within the valid shift value range. // to ensure it's within the valid shift value range.
let r = (right.bits() as u32) & (type_bits - 1); let masked_shift_width = (r as u32) & (type_bits - 1);
return match bin_op { return match bin_op {
Shl => int_shift!(left_kind, overflowing_shl, l, r), Shl => int_shift!(left_kind, overflowing_shl, l, masked_shift_width),
Shr => int_shift!(left_kind, overflowing_shr, l, r), Shr => int_shift!(left_kind, overflowing_shr, l, masked_shift_width),
_ => bug!("it has already been checked that this is a shift op"), _ => bug!("it has already been checked that this is a shift op"),
}; };
} }
...@@ -253,26 +275,28 @@ pub fn unary_op<'tcx>( ...@@ -253,26 +275,28 @@ pub fn unary_op<'tcx>(
use rustc::mir::UnOp::*; use rustc::mir::UnOp::*;
use value::PrimValKind::*; use value::PrimValKind::*;
let bits = match (un_op, val_kind) { let bytes = val.to_bytes()?;
(Not, Bool) => !bits_to_bool(val.bits()) as u64,
let result_bytes = match (un_op, val_kind) {
(Not, Bool) => !bits_to_bool(bytes) as u64,
(Not, U8) => !(val.bits() as u8) as u64, (Not, U8) => !(bytes as u8) as u64,
(Not, U16) => !(val.bits() as u16) as u64, (Not, U16) => !(bytes as u16) as u64,
(Not, U32) => !(val.bits() as u32) as u64, (Not, U32) => !(bytes as u32) as u64,
(Not, U64) => !val.bits(), (Not, U64) => !bytes,
(Not, I8) => !(val.bits() as i8) as u64, (Not, I8) => !(bytes as i8) as u64,
(Not, I16) => !(val.bits() as i16) as u64, (Not, I16) => !(bytes as i16) as u64,
(Not, I32) => !(val.bits() as i32) as u64, (Not, I32) => !(bytes as i32) as u64,
(Not, I64) => !(val.bits() as i64) as u64, (Not, I64) => !(bytes as i64) as u64,
(Neg, I8) => -(val.bits() as i8) as u64, (Neg, I8) => -(bytes as i8) as u64,
(Neg, I16) => -(val.bits() as i16) as u64, (Neg, I16) => -(bytes as i16) as u64,
(Neg, I32) => -(val.bits() as i32) as u64, (Neg, I32) => -(bytes as i32) as u64,
(Neg, I64) => -(val.bits() as i64) as u64, (Neg, I64) => -(bytes as i64) as u64,
(Neg, F32) => f32_to_bits(-bits_to_f32(val.bits())), (Neg, F32) => f32_to_bits(-bits_to_f32(bytes)),
(Neg, F64) => f64_to_bits(-bits_to_f64(val.bits())), (Neg, F64) => f64_to_bits(-bits_to_f64(bytes)),
_ => { _ => {
let msg = format!("unimplemented unary op: {:?}, {:?}", un_op, val); let msg = format!("unimplemented unary op: {:?}, {:?}", un_op, val);
...@@ -280,5 +304,5 @@ pub fn unary_op<'tcx>( ...@@ -280,5 +304,5 @@ pub fn unary_op<'tcx>(
} }
}; };
Ok(PrimVal::Bytes(bits)) Ok(PrimVal::Bytes(result_bytes))
} }
...@@ -163,7 +163,7 @@ pub(super) fn call_intrinsic( ...@@ -163,7 +163,7 @@ pub(super) fn call_intrinsic(
let ty = substs.type_at(0); let ty = substs.type_at(0);
let num = self.value_to_primval(arg_vals[0], ty)?; let num = self.value_to_primval(arg_vals[0], ty)?;
let kind = self.ty_to_primval_kind(ty)?; let kind = self.ty_to_primval_kind(ty)?;
let num = numeric_intrinsic(intrinsic_name, num, kind); let num = numeric_intrinsic(intrinsic_name, num, kind)?;
self.write_primval(dest, num, ty)?; self.write_primval(dest, num, ty)?;
} }
...@@ -501,33 +501,40 @@ fn field_ty( ...@@ -501,33 +501,40 @@ fn field_ty(
} }
} }
macro_rules! integer_intrinsic { fn numeric_intrinsic<'tcx>(
($name:expr, $val:expr, $kind:expr, $method:ident) => ({ name: &str,
let val = $val; val: PrimVal,
kind: PrimValKind
use value::PrimValKind::*; ) -> EvalResult<'tcx, PrimVal> {
let bits = match $kind { macro_rules! integer_intrinsic {
I8 => (val.bits() as i8).$method() as u64, ($name:expr, $val:expr, $kind:expr, $method:ident) => ({
U8 => (val.bits() as u8).$method() as u64, let val = $val;
I16 => (val.bits() as i16).$method() as u64, let bytes = val.to_bytes()?;
U16 => (val.bits() as u16).$method() as u64,
I32 => (val.bits() as i32).$method() as u64, use value::PrimValKind::*;
U32 => (val.bits() as u32).$method() as u64, let result_bytes = match $kind {
I64 => (val.bits() as i64).$method() as u64, I8 => (bytes as i8).$method() as u64,
U64 => (val.bits() as u64).$method() as u64, U8 => (bytes as u8).$method() as u64,
_ => bug!("invalid `{}` argument: {:?}", $name, val), I16 => (bytes as i16).$method() as u64,
}; U16 => (bytes as u16).$method() as u64,
I32 => (bytes as i32).$method() as u64,
PrimVal::Bytes(bits) U32 => (bytes as u32).$method() as u64,
}); I64 => (bytes as i64).$method() as u64,
} U64 => bytes.$method() as u64,
_ => bug!("invalid `{}` argument: {:?}", $name, val),
};
PrimVal::Bytes(result_bytes)
});
}
fn numeric_intrinsic(name: &str, val: PrimVal, kind: PrimValKind) -> PrimVal { let result_val = match name {
match name {
"bswap" => integer_intrinsic!("bswap", val, kind, swap_bytes), "bswap" => integer_intrinsic!("bswap", val, kind, swap_bytes),
"ctlz" => integer_intrinsic!("ctlz", val, kind, leading_zeros), "ctlz" => integer_intrinsic!("ctlz", val, kind, leading_zeros),
"ctpop" => integer_intrinsic!("ctpop", val, kind, count_ones), "ctpop" => integer_intrinsic!("ctpop", val, kind, count_ones),
"cttz" => integer_intrinsic!("cttz", val, kind, trailing_zeros), "cttz" => integer_intrinsic!("cttz", val, kind, trailing_zeros),
_ => bug!("not a numeric intrinsic: {}", name), _ => bug!("not a numeric intrinsic: {}", name),
} };
Ok(result_val)
} }
...@@ -53,7 +53,7 @@ pub(super) fn eval_terminator( ...@@ -53,7 +53,7 @@ pub(super) fn eval_terminator(
for (index, const_val) in values.iter().enumerate() { for (index, const_val) in values.iter().enumerate() {
let val = self.const_to_value(const_val)?; let val = self.const_to_value(const_val)?;
let prim = self.value_to_primval(val, discr_ty)?; let prim = self.value_to_primval(val, discr_ty)?;
if discr_prim.bits() == prim.bits() { if discr_prim.to_bytes()? == prim.to_bytes()? {
target_block = targets[index]; target_block = targets[index];
break; break;
} }
......
...@@ -117,16 +117,6 @@ pub(super) fn expect_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (P ...@@ -117,16 +117,6 @@ pub(super) fn expect_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (P
} }
impl<'tcx> 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 {
PrimVal::Bytes(b) => b,
PrimVal::Ptr(p) => p.offset,
PrimVal::Undef => panic!(".bits()() on PrimVal::Undef"),
}
}
pub fn from_u64(n: u64) -> Self { pub fn from_u64(n: u64) -> Self {
PrimVal::Bytes(n) PrimVal::Bytes(n)
} }
...@@ -151,7 +141,7 @@ pub fn from_char(c: char) -> Self { ...@@ -151,7 +141,7 @@ pub fn from_char(c: char) -> Self {
PrimVal::Bytes(c as u64) PrimVal::Bytes(c as u64)
} }
fn to_bytes(self) -> EvalResult<'tcx, u64> { pub fn to_bytes(self) -> EvalResult<'tcx, u64> {
match self { match self {
PrimVal::Bytes(b) => Ok(b), PrimVal::Bytes(b) => Ok(b),
PrimVal::Ptr(p) => p.to_int(), PrimVal::Ptr(p) => p.to_int(),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册