mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Refactor PrimVal::bits() out of existence.
This commit is contained in:
parent
9e244251a0
commit
4fe41ad8d5
@ -20,9 +20,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
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 @@ impl Pointer {
|
||||
|
||||
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) = (left.bits(), right.bits());
|
||||
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));
|
||||
}
|
||||
|
||||
(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()?;
|
||||
|
||||
(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(),
|
||||
let result_bytes = match (un_op, val_kind) {
|
||||
(Not, Bool) => !bits_to_bool(bytes) as u64,
|
||||
|
||||
(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, U8) => !(bytes as u8) as u64,
|
||||
(Not, U16) => !(bytes as u16) as u64,
|
||||
(Not, U32) => !(bytes as u32) as u64,
|
||||
(Not, U64) => !bytes,
|
||||
|
||||
(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,
|
||||
(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, F32) => f32_to_bits(-bits_to_f32(val.bits())),
|
||||
(Neg, F64) => f64_to_bits(-bits_to_f64(val.bits())),
|
||||
(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(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 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! integer_intrinsic {
|
||||
($name:expr, $val:expr, $kind:expr, $method:ident) => ({
|
||||
let val = $val;
|
||||
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 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),
|
||||
};
|
||||
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(bits)
|
||||
});
|
||||
}
|
||||
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 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
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;
|
||||
}
|
||||
|
12
src/value.rs
12
src/value.rs
@ -117,16 +117,6 @@ impl<'a, 'tcx: 'a> Value {
|
||||
}
|
||||
|
||||
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 @@ impl<'tcx> PrimVal {
|
||||
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(),
|
||||
|
Loading…
Reference in New Issue
Block a user