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

Refactor PrimVal::bits() out of existence.

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