From b36a83171bf0de5a1b8d139363b1b469e273c994 Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Thu, 15 Dec 2016 23:40:45 -0800 Subject: [PATCH] Turn PrimVal into an enum including Undefined. This is step 1 of a refactoring to fix #95. The `Undefined` variant is so far unused and the old `bits` and `relocation` fields are emulated with two new temporary methods. There should be no functional change due to this commit. --- src/cast.rs | 26 +++++++------- src/eval_context.rs | 50 +++++++++++++------------- src/memory.rs | 14 ++++---- src/operator.rs | 46 ++++++++++++------------ src/terminator/intrinsic.rs | 32 ++++++++--------- src/terminator/mod.rs | 14 ++++---- src/value.rs | 70 ++++++++++++++++++++++--------------- 7 files changed, 132 insertions(+), 120 deletions(-) diff --git a/src/cast.rs b/src/cast.rs index a49b3b12480..4412bd3d418 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -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.bits() as 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.bits(), dest_ty, false), FnPtr | Ptr => self.cast_ptr(val.to_ptr(), dest_ty), } @@ -39,15 +39,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { TyBool if v == 1 => Ok(PrimVal::from_bool(true)), TyBool => Err(EvalError::InvalidBool), - TyInt(IntTy::I8) => Ok(PrimVal::new(v as i64 as i8 as u64)), - TyInt(IntTy::I16) => Ok(PrimVal::new(v as i64 as i16 as u64)), - TyInt(IntTy::I32) => Ok(PrimVal::new(v as i64 as i32 as u64)), - TyInt(IntTy::I64) => Ok(PrimVal::new(v as i64 as i64 as u64)), + TyInt(IntTy::I8) => Ok(PrimVal::Bytes(v as i64 as i8 as u64)), + TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i64 as i16 as u64)), + TyInt(IntTy::I32) => Ok(PrimVal::Bytes(v as i64 as i32 as u64)), + TyInt(IntTy::I64) => Ok(PrimVal::Bytes(v as i64 as i64 as u64)), - TyUint(UintTy::U8) => Ok(PrimVal::new(v as u8 as u64)), - TyUint(UintTy::U16) => Ok(PrimVal::new(v as u16 as u64)), - TyUint(UintTy::U32) => Ok(PrimVal::new(v as u32 as u64)), - TyUint(UintTy::U64) => Ok(PrimVal::new(v)), + TyUint(UintTy::U8) => Ok(PrimVal::Bytes(v as u8 as u64)), + TyUint(UintTy::U16) => Ok(PrimVal::Bytes(v as u16 as u64)), + TyUint(UintTy::U32) => Ok(PrimVal::Bytes(v as u32 as u64)), + TyUint(UintTy::U64) => Ok(PrimVal::Bytes(v)), TyInt(IntTy::Is) => { let int_ty = self.tcx.sess.target.int_type; @@ -66,10 +66,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i64 as f32)), TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(v as f32)), - TyChar if v as u8 as u64 == v => Ok(PrimVal::new(v)), + TyChar if v as u8 as u64 == v => Ok(PrimVal::Bytes(v)), TyChar => Err(EvalError::InvalidChar(v)), - TyRawPtr(_) => Ok(PrimVal::from_ptr(Pointer::from_int(v))), + TyRawPtr(_) => Ok(PrimVal::Pointer(Pointer::from_int(v))), _ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))), } @@ -94,7 +94,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { use rustc::ty::TypeVariants::*; match ty.sty { TyRef(..) | TyRawPtr(_) | TyFnPtr(_) | TyInt(_) | TyUint(_) => - Ok(PrimVal::from_ptr(ptr)), + Ok(PrimVal::Pointer(ptr)), _ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))), } } diff --git a/src/eval_context.rs b/src/eval_context.rs index 713c01602c7..7ed1a17e44f 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = self.memory.allocate(s.len() as u64, 1)?; self.memory.write_bytes(ptr, s.as_bytes())?; self.memory.freeze(ptr.alloc_id)?; - Ok(Value::ByValPair(PrimVal::from_ptr(ptr), PrimVal::from_uint(s.len() as u64))) + Ok(Value::ByValPair(PrimVal::Pointer(ptr), PrimVal::from_uint(s.len() as u64))) } pub(super) fn const_to_value(&mut self, const_val: &ConstVal) -> EvalResult<'tcx, Value> { @@ -180,7 +180,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { use rustc_const_math::ConstFloat; let primval = match *const_val { - Integral(const_int) => PrimVal::new(const_int.to_u64_unchecked()), + Integral(const_int) => PrimVal::Bytes(const_int.to_u64_unchecked()), Float(ConstFloat::F32(f)) => PrimVal::from_f32(f), Float(ConstFloat::F64(f)) => PrimVal::from_f64(f), @@ -196,7 +196,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = self.memory.allocate(bs.len() as u64, 1)?; self.memory.write_bytes(ptr, bs)?; self.memory.freeze(ptr.alloc_id)?; - PrimVal::from_ptr(ptr) + PrimVal::Pointer(ptr) } Struct(_) => unimplemented!(), @@ -315,14 +315,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { .expect("global should have been cached (freeze)"); match global_value.data.expect("global should have been initialized") { Value::ByRef(ptr) => self.memory.freeze(ptr.alloc_id)?, - Value::ByVal(val) => if let Some(alloc_id) = val.relocation { + Value::ByVal(val) => if let Some(alloc_id) = val.relocation() { self.memory.freeze(alloc_id)?; }, Value::ByValPair(a, b) => { - if let Some(alloc_id) = a.relocation { + if let Some(alloc_id) = a.relocation() { self.memory.freeze(alloc_id)?; } - if let Some(alloc_id) = b.relocation { + if let Some(alloc_id) = b.relocation() { self.memory.freeze(alloc_id)?; } }, @@ -500,7 +500,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { assert_eq!(operands.len(), 0); if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { let n = adt_def.variants[variant].disr_val.to_u64_unchecked(); - self.write_primval(dest, PrimVal::new(n), dest_ty)?; + self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?; } else { bug!("tried to assign {:?} to Layout::CEnum", kind); } @@ -563,12 +563,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ref(_, _, ref lvalue) => { let src = self.eval_lvalue(lvalue)?; let (raw_ptr, extra) = self.force_allocation(src)?.to_ptr_and_extra(); - let ptr = PrimVal::from_ptr(raw_ptr); + let ptr = PrimVal::Pointer(raw_ptr); let val = match extra { LvalueExtra::None => Value::ByVal(ptr), LvalueExtra::Length(len) => Value::ByValPair(ptr, PrimVal::from_uint(len)), - LvalueExtra::Vtable(vtable) => Value::ByValPair(ptr, PrimVal::from_ptr(vtable)), + LvalueExtra::Vtable(vtable) => Value::ByValPair(ptr, PrimVal::Pointer(vtable)), LvalueExtra::DowncastVariant(..) => bug!("attempted to take a reference to an enum downcast lvalue"), }; @@ -578,7 +578,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Box(ty) => { let ptr = self.alloc_ptr(ty)?; - self.write_primval(dest, PrimVal::from_ptr(ptr), dest_ty)?; + self.write_primval(dest, PrimVal::Pointer(ptr), dest_ty)?; } Cast(kind, ref operand, cast_ty) => { @@ -617,7 +617,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyFnDef(def_id, substs, fn_ty) => { let fn_ty = self.tcx.erase_regions(&fn_ty); let fn_ptr = self.memory.create_fn_ptr(self.tcx,def_id, substs, fn_ty); - self.write_value(Value::ByVal(PrimVal::from_ptr(fn_ptr)), dest, dest_ty)?; + self.write_value(Value::ByVal(PrimVal::Pointer(fn_ptr)), dest, dest_ty)?; }, ref other => bug!("reify fn pointer on {:?}", other), }, @@ -629,7 +629,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (def_id, substs, _, _) = self.memory.get_fn(ptr.alloc_id)?; let unsafe_fn_ty = self.tcx.erase_regions(&unsafe_fn_ty); let fn_ptr = self.memory.create_fn_ptr(self.tcx, def_id, substs, unsafe_fn_ty); - self.write_value(Value::ByVal(PrimVal::from_ptr(fn_ptr)), dest, dest_ty)?; + self.write_value(Value::ByVal(PrimVal::Pointer(fn_ptr)), dest, dest_ty)?; }, ref other => bug!("fn to unsafe fn cast on {:?}", other), }, @@ -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.bits() > 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.bits() as u32).is_none() + => Err(EvalError::InvalidChar(val.bits() as u32 as u64)), _ => Ok(()), } @@ -1150,23 +1150,23 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr)?), ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr)?), - ty::TyFnPtr(_) => self.memory.read_ptr(ptr).map(PrimVal::from_ptr)?, + ty::TyFnPtr(_) => self.memory.read_ptr(ptr).map(PrimVal::Pointer)?, ty::TyBox(ty) | ty::TyRef(_, ty::TypeAndMut { ty, .. }) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { let p = self.memory.read_ptr(ptr)?; if self.type_is_sized(ty) { - PrimVal::from_ptr(p) + PrimVal::Pointer(p) } else { trace!("reading fat pointer extra of type {}", ty); let extra = ptr.offset(self.memory.pointer_size()); let extra = match self.tcx.struct_tail(ty).sty { - ty::TyDynamic(..) => PrimVal::from_ptr(self.memory.read_ptr(extra)?), + ty::TyDynamic(..) => PrimVal::Pointer(self.memory.read_ptr(extra)?), ty::TySlice(..) | ty::TyStr => PrimVal::from_uint(self.memory.read_usize(extra)?), _ => bug!("unsized primval ptr read from {:?}", ty), }; - return Ok(Some(Value::ByValPair(PrimVal::from_ptr(p), extra))); + return Ok(Some(Value::ByValPair(PrimVal::Pointer(p), extra))); } } @@ -1225,7 +1225,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { (&ty::TyArray(_, length), &ty::TySlice(_)) => { let ptr = src.read_ptr(&self.memory)?; let len = PrimVal::from_uint(length as u64); - let ptr = PrimVal::from_ptr(ptr); + let ptr = PrimVal::Pointer(ptr); self.write_value(Value::ByValPair(ptr, len), dest, dest_ty)?; } (&ty::TyDynamic(..), &ty::TyDynamic(..)) => { @@ -1239,8 +1239,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let trait_ref = self.tcx.erase_regions(&trait_ref); let vtable = self.get_vtable(trait_ref)?; let ptr = src.read_ptr(&self.memory)?; - let ptr = PrimVal::from_ptr(ptr); - let extra = PrimVal::from_ptr(vtable); + let ptr = PrimVal::Pointer(ptr); + let extra = PrimVal::Pointer(vtable); self.write_value(Value::ByValPair(ptr, extra), dest, dest_ty)?; }, @@ -1301,12 +1301,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } Value::ByVal(val) => { trace!("frame[{}] {:?}: {:?}", frame, local, val); - if let Some(alloc_id) = val.relocation { allocs.push(alloc_id); } + if let Some(alloc_id) = val.relocation() { allocs.push(alloc_id); } } Value::ByValPair(val1, val2) => { trace!("frame[{}] {:?}: ({:?}, {:?})", frame, local, val1, val2); - if let Some(alloc_id) = val1.relocation { allocs.push(alloc_id); } - if let Some(alloc_id) = val2.relocation { allocs.push(alloc_id); } + if let Some(alloc_id) = val1.relocation() { allocs.push(alloc_id); } + if let Some(alloc_id) = val2.relocation() { allocs.push(alloc_id); } } } } diff --git a/src/memory.rs b/src/memory.rs index babd9bcb783..ac457966b31 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -587,18 +587,18 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { val: PrimVal, kind: PrimValKind, ) -> EvalResult<'tcx, ()> { - if let Some(alloc_id) = val.relocation { - return self.write_ptr(dest, Pointer::new(alloc_id, val.bits)); + if let Some(alloc_id) = val.relocation() { + return self.write_ptr(dest, Pointer::new(alloc_id, val.bits())); } use value::PrimValKind::*; let (size, bits) = match kind { - I8 | U8 | Bool => (1, val.bits as u8 as u64), - I16 | U16 => (2, val.bits as u16 as u64), - I32 | U32 | F32 | Char => (4, val.bits as u32 as u64), - I64 | U64 | F64 => (8, val.bits), + I8 | U8 | Bool => (1, val.bits() as u8 as u64), + I16 | U16 => (2, val.bits() as u16 as u64), + I32 | U32 | F32 | Char => (4, val.bits() as u32 as u64), + I64 | U64 | F64 => (8, val.bits()), // int -> ptr transmutes are handled here - FnPtr | Ptr => return self.write_usize(dest, val.bits), + FnPtr | Ptr => return self.write_usize(dest, val.bits()), }; self.write_uint(dest, bits, size) diff --git a/src/operator.rs b/src/operator.rs index 6e656d69f65..9e879eaf980 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { macro_rules! overflow { ($op:ident, $l:expr, $r:expr) => ({ let (val, overflowed) = $l.$op($r); - let primval = PrimVal::new(val as u64); + let primval = PrimVal::Bytes(val as u64); Ok((primval, overflowed)) }) } @@ -112,7 +112,7 @@ macro_rules! float_arithmetic { let l = $from_bits($l); let r = $from_bits($r); let bits = $to_bits(l $float_op r); - PrimVal::new(bits) + PrimVal::Bytes(bits) }) } @@ -148,7 +148,7 @@ pub fn binary_op<'tcx>( return Ok((unrelated_ptr_ops(bin_op, left_ptr, right_ptr)?, false)); } - let (l, r) = (left.bits, right.bits); + let (l, r) = (left.bits(), right.bits()); // These ops can have an RHS with a different numeric type. if bin_op == Shl || bin_op == Shr { @@ -165,7 +165,7 @@ 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 r = (right.bits() as u32) & (type_bits - 1); return match bin_op { Shl => int_shift!(left_kind, overflowing_shl, l, r), @@ -213,9 +213,9 @@ pub fn binary_op<'tcx>( (Gt, _) => PrimVal::from_bool(l > r), (Ge, _) => PrimVal::from_bool(l >= r), - (BitOr, _) => PrimVal::new(l | r), - (BitAnd, _) => PrimVal::new(l & r), - (BitXor, _) => PrimVal::new(l ^ r), + (BitOr, _) => PrimVal::Bytes(l | r), + (BitAnd, _) => PrimVal::Bytes(l & r), + (BitXor, _) => PrimVal::Bytes(l ^ r), (Add, k) if k.is_int() => return int_arithmetic!(k, overflowing_add, l, r), (Sub, k) if k.is_int() => return int_arithmetic!(k, overflowing_sub, l, r), @@ -254,25 +254,25 @@ pub fn unary_op<'tcx>( use value::PrimValKind::*; let bits = match (un_op, val_kind) { - (Not, Bool) => !bits_to_bool(val.bits) as u64, + (Not, Bool) => !bits_to_bool(val.bits()) 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) => !(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, 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) => !(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, - (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) => -(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, 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(val.bits())), + (Neg, F64) => f64_to_bits(-bits_to_f64(val.bits())), _ => { let msg = format!("unimplemented unary op: {:?}, {:?}", un_op, val); @@ -280,5 +280,5 @@ pub fn unary_op<'tcx>( } }; - Ok(PrimVal::new(bits)) + Ok(PrimVal::Bytes(bits)) } diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 443696edb12..de9c972ffd4 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = arg_vals[0].read_ptr(&self.memory)?; let offset = self.value_to_primval(arg_vals[1], isize)?.to_i64(); let new_ptr = ptr.signed_offset(offset); - self.write_primval(dest, PrimVal::from_ptr(new_ptr), dest_ty)?; + self.write_primval(dest, PrimVal::Pointer(new_ptr), dest_ty)?; } "assume" => { @@ -171,7 +171,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ty = substs.type_at(0); let adt_ptr = arg_vals[0].read_ptr(&self.memory)?; let discr_val = self.read_discriminant_value(adt_ptr, ty)?; - self.write_primval(dest, PrimVal::new(discr_val), dest_ty)?; + self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } "drop_in_place" => { @@ -235,16 +235,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Value::ByRef(ptr) }, None => match this.ty_to_primval_kind(dest_ty) { - Ok(_) => Value::ByVal(PrimVal::new(0)), + Ok(_) => Value::ByVal(PrimVal::Bytes(0)), Err(_) => { let ptr = this.alloc_ptr_with_substs(dest_ty, substs)?; this.memory.write_repeat(ptr, 0, size)?; Value::ByRef(ptr) } }, - Some(Value::ByVal(_)) => Value::ByVal(PrimVal::new(0)), + Some(Value::ByVal(_)) => Value::ByVal(PrimVal::Bytes(0)), Some(Value::ByValPair(..)) => - Value::ByValPair(PrimVal::new(0), PrimVal::new(0)), + Value::ByValPair(PrimVal::Bytes(0), PrimVal::Bytes(0)), }; Ok(Some(zero_val)) }; @@ -292,7 +292,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = arg_vals[0].read_ptr(&self.memory)?; let result_ptr = ptr.signed_offset(offset * pointee_size); - self.write_primval(dest, PrimVal::from_ptr(result_ptr), dest_ty)?; + self.write_primval(dest, PrimVal::Pointer(result_ptr), dest_ty)?; } "overflowing_sub" => { @@ -361,7 +361,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "type_id" => { let ty = substs.type_at(0); let n = self.tcx.type_id_hash(ty); - self.write_primval(dest, PrimVal::new(n), dest_ty)?; + self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?; } "transmute" => { @@ -507,18 +507,18 @@ macro_rules! integer_intrinsic { 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, + 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::new(bits) + PrimVal::Bytes(bits) }); } diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 23d59e3fc3e..c48a8a72c3d 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -336,7 +336,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let size = self.value_to_primval(args[0], usize)?.to_u64(); let align = self.value_to_primval(args[1], usize)?.to_u64(); let ptr = self.memory.allocate(size, align)?; - self.write_primval(dest, PrimVal::from_ptr(ptr), dest_ty)?; + self.write_primval(dest, PrimVal::Pointer(ptr), dest_ty)?; } "__rust_deallocate" => { @@ -352,7 +352,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let size = self.value_to_primval(args[2], usize)?.to_u64(); let align = self.value_to_primval(args[3], usize)?.to_u64(); let new_ptr = self.memory.reallocate(ptr, size, align)?; - self.write_primval(dest, PrimVal::from_ptr(new_ptr), dest_ty)?; + self.write_primval(dest, PrimVal::Pointer(new_ptr), dest_ty)?; } "memcmp" => { @@ -372,7 +372,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } }; - self.write_primval(dest, PrimVal::new(result as u64), dest_ty)?; + self.write_primval(dest, PrimVal::Bytes(result as u64), dest_ty)?; } "memchr" => { @@ -527,7 +527,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ptr }, }; - args[0].0 = Value::ByVal(PrimVal::from_ptr(ptr)); + args[0].0 = Value::ByVal(PrimVal::Pointer(ptr)); args[0].1 = self.tcx.mk_mut_ptr(args[0].1); } @@ -550,7 +550,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let idx = self.tcx.get_vtable_index_of_object_method(data, def_id) as u64; if let Some(&mut(ref mut first_arg, ref mut first_ty)) = args.get_mut(0) { let (self_ptr, vtable) = first_arg.expect_ptr_vtable_pair(&self.memory)?; - *first_arg = Value::ByVal(PrimVal::from_ptr(self_ptr)); + *first_arg = Value::ByVal(PrimVal::Pointer(self_ptr)); let idx = idx + 3; let offset = idx * self.memory.pointer_size(); let fn_ptr = self.memory.read_ptr(vtable.offset(offset))?; @@ -633,7 +633,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }; // run drop impl before the fields' drop impls if let Some(drop_def_id) = adt_def.destructor() { - drop.push((drop_def_id, Value::ByVal(PrimVal::from_ptr(adt_ptr)), substs)); + drop.push((drop_def_id, Value::ByVal(PrimVal::Pointer(adt_ptr)), substs)); } let layout = self.type_layout(ty)?; let fields = match *layout { @@ -701,7 +701,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (def_id, substs, _abi, sig) = self.memory.get_fn(drop_fn.alloc_id)?; let real_ty = sig.inputs()[0]; self.drop(Lvalue::from_ptr(ptr), real_ty, drop)?; - drop.push((def_id, Value::ByVal(PrimVal::from_ptr(ptr)), substs)); + drop.push((def_id, Value::ByVal(PrimVal::Pointer(ptr)), substs)); } else { // just a sanity check assert_eq!(drop_fn.offset, 0); diff --git a/src/value.rs b/src/value.rs index 4642018c124..7055548095d 100644 --- a/src/value.rs +++ b/src/value.rs @@ -46,13 +46,17 @@ pub enum Value { /// A `PrimVal` represents an immediate, primitive value existing outside of an allocation. It is /// considered to be like a #[derive(Clone, Copy, Debug, PartialEq)] -pub struct PrimVal { - pub bits: u64, +pub enum PrimVal { + Bytes(u64), + // FIXME(solson): Rename this variant to Ptr. + // FIXME(solson): Outdated comment, pulled from `relocations` field I deleted. /// This field is initialized when the `PrimVal` represents a pointer into an `Allocation`. An /// `Allocation` in the `memory` module has a list of relocations, but a `PrimVal` is only /// large enough to contain one, hence the `Option`. - pub relocation: Option, + Pointer(Pointer), + + Undefined, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -110,56 +114,64 @@ impl<'a, 'tcx: 'a> Value { } impl PrimVal { - pub fn new(bits: u64) -> Self { - PrimVal { bits: bits, relocation: None } + // 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::Pointer(p) => p.offset, + PrimVal::Undefined => panic!(".bits()() on PrimVal::Undefined"), + } } - pub fn new_with_relocation(bits: u64, alloc_id: AllocId) -> Self { - PrimVal { bits: bits, relocation: Some(alloc_id) } - } - - pub fn from_ptr(ptr: Pointer) -> Self { - PrimVal::new_with_relocation(ptr.offset as u64, ptr.alloc_id) + // FIXME(solson): Remove this. It's a temporary function to aid refactoring, but it shouldn't + // stick around with this name. + pub fn relocation(&self) -> Option { + if let PrimVal::Pointer(ref p) = *self { + Some(p.alloc_id) + } else { + None + } } pub fn from_bool(b: bool) -> Self { - PrimVal::new(b as u64) + PrimVal::Bytes(b as u64) } pub fn from_char(c: char) -> Self { - PrimVal::new(c as u64) + PrimVal::Bytes(c as u64) } pub fn from_f32(f: f32) -> Self { - PrimVal::new(f32_to_bits(f)) + PrimVal::Bytes(f32_to_bits(f)) } pub fn from_f64(f: f64) -> Self { - PrimVal::new(f64_to_bits(f)) + PrimVal::Bytes(f64_to_bits(f)) } pub fn from_uint(n: u64) -> Self { - PrimVal::new(n) + PrimVal::Bytes(n) } pub fn from_int(n: i64) -> Self { - PrimVal::new(n as u64) + PrimVal::Bytes(n as u64) } pub fn to_f32(self) -> f32 { - assert!(self.relocation.is_none()); - bits_to_f32(self.bits) + assert!(self.relocation().is_none()); + bits_to_f32(self.bits()) } pub fn to_f64(self) -> f64 { - assert!(self.relocation.is_none()); - bits_to_f64(self.bits) + assert!(self.relocation().is_none()); + bits_to_f64(self.bits()) } pub fn to_ptr(self) -> Pointer { - self.relocation.map(|alloc_id| { - Pointer::new(alloc_id, self.bits) - }).unwrap_or_else(|| Pointer::from_int(self.bits)) + self.relocation().map(|alloc_id| { + Pointer::new(alloc_id, self.bits()) + }).unwrap_or_else(|| Pointer::from_int(self.bits())) } pub fn try_as_uint<'tcx>(self) -> EvalResult<'tcx, u64> { @@ -170,24 +182,24 @@ impl PrimVal { if let Some(ptr) = self.try_as_ptr() { return ptr.to_int().expect("non abstract ptr") as u64; } - self.bits + self.bits() } pub fn to_i64(self) -> i64 { if let Some(ptr) = self.try_as_ptr() { return ptr.to_int().expect("non abstract ptr") as i64; } - self.bits as i64 + self.bits() as i64 } pub fn try_as_ptr(self) -> Option { - self.relocation.map(|alloc_id| { - Pointer::new(alloc_id, self.bits) + self.relocation().map(|alloc_id| { + Pointer::new(alloc_id, self.bits()) }) } pub fn try_as_bool<'tcx>(self) -> EvalResult<'tcx, bool> { - match self.bits { + match self.bits() { 0 => Ok(false), 1 => Ok(true), _ => Err(EvalError::InvalidBool),