]> git.lizzy.rs Git - rust.git/commitdiff
finally remove all traces of signs from memory
authorRalf Jung <post@ralfj.de>
Thu, 16 Aug 2018 09:38:16 +0000 (11:38 +0200)
committerRalf Jung <post@ralfj.de>
Wed, 22 Aug 2018 07:06:28 +0000 (09:06 +0200)
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/traits.rs

index 50b8c271233e38017bbcc03a465598179de4c3e1..ca664c6e18b4d40095227fec643d61568b60e69e 100644 (file)
@@ -567,18 +567,6 @@ pub fn write_target_uint(
     }
 }
 
-pub fn write_target_int(
-    endianness: layout::Endian,
-    mut target: &mut [u8],
-    data: i128,
-) -> Result<(), io::Error> {
-    let len = target.len();
-    match endianness {
-        layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
-        layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
-    }
-}
-
 pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
     match endianness {
         layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
@@ -586,6 +574,26 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Methods to faciliate working with signed integers stored in a u128
+////////////////////////////////////////////////////////////////////////////////
+
+pub fn sign_extend(value: u128, size: Size) -> u128 {
+    let size = size.bits();
+    // sign extend
+    let shift = 128 - size;
+    // shift the unsigned value to the left
+    // and back to the right as signed (essentially fills with FF on the left)
+    (((value << shift) as i128) >> shift) as u128
+}
+
+pub fn truncate(value: u128, size: Size) -> u128 {
+    let size = size.bits();
+    let shift = 128 - size;
+    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
+    (value << shift) >> shift
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Undefined byte tracking
 ////////////////////////////////////////////////////////////////////////////////
index 3f8130ec04ca9e64b92297d7b738da64393db0f9..e661da8792a9ec396df19a72f6e4a67ac36a4709 100644 (file)
@@ -191,7 +191,7 @@ pub enum Scalar {
     /// The raw bytes of a simple value.
     Bits {
         /// The first `size` bytes are the value.
-        /// Do not try to read less or more bytes that that
+        /// Do not try to read less or more bytes that that. The remaining bytes must be 0.
         size: u8,
         bits: u128,
     },
index 0bb0faf08484b3ac9513859a87a61e8d97e645f4..16d6a08981abc9a562854510eb5877def5829262 100644 (file)
 pub use self::check_match::check_crate;
 pub(crate) use self::check_match::check_match;
 
-use interpret::{const_field, const_variant_index, self};
+use interpret::{const_field, const_variant_index};
 
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
-use rustc::mir::interpret::{Scalar, GlobalId, ConstValue};
+use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -1086,8 +1086,8 @@ pub fn compare_const_vals<'a, 'tcx>(
             ty::TyInt(_) => {
                 let layout = tcx.layout_of(ty).ok()?;
                 assert!(layout.abi.is_signed());
-                let a = interpret::sign_extend(a, layout.size);
-                let b = interpret::sign_extend(b, layout.size);
+                let a = sign_extend(a, layout.size);
+                let b = sign_extend(b, layout.size);
                 Some((a as i128).cmp(&(b as i128)))
             },
             _ => Some(a.cmp(&b)),
index 036b84ee1fb7b35888634c164eb722dc480d2d9c..b4d36afa0f80d7524566574083d913d8bbf4132a 100644 (file)
@@ -1,9 +1,12 @@
 use rustc::ty::{self, Ty, TypeAndMut};
-use rustc::ty::layout::{self, TyLayout};
+use rustc::ty::layout::{self, TyLayout, Size};
 use syntax::ast::{FloatTy, IntTy, UintTy};
 
 use rustc_apfloat::ieee::{Single, Double};
-use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind};
+use rustc::mir::interpret::{
+    Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind,
+    truncate, sign_extend
+};
 use rustc::mir::CastKind;
 use rustc_apfloat::Float;
 
@@ -144,11 +147,26 @@ pub(super) fn cast_scalar(
         match val {
             Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
             Scalar::Bits { bits, size } => {
-                assert_eq!(size as u64, src_layout.size.bytes());
-                match src_layout.ty.sty {
-                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_layout.ty),
-                    _ => self.cast_from_int(bits, src_layout, dest_layout),
+                debug_assert_eq!(size as u64, src_layout.size.bytes());
+                debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                    "Unexpected value of size {} before casting", size);
+
+                let res = match src_layout.ty.sty {
+                    TyFloat(fty) => self.cast_from_float(bits, fty, dest_layout.ty)?,
+                    _ => self.cast_from_int(bits, src_layout, dest_layout)?,
+                };
+
+                // Sanity check
+                match res {
+                    Scalar::Ptr(_) => bug!("Fabricated a ptr value from an int...?"),
+                    Scalar::Bits { bits, size } => {
+                        debug_assert_eq!(size as u64, dest_layout.size.bytes());
+                        debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                            "Unexpected value of size {} after casting", size);
+                    }
                 }
+                // Done
+                Ok(res)
             }
         }
     }
@@ -218,30 +236,31 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
             // float -> uint
             TyUint(t) => {
                 let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
-                match fty {
-                    FloatTy::F32 => Ok(Scalar::Bits {
-                        bits: Single::from_bits(bits).to_u128(width).value,
-                        size: (width / 8) as u8,
-                    }),
-                    FloatTy::F64 => Ok(Scalar::Bits {
-                        bits: Double::from_bits(bits).to_u128(width).value,
-                        size: (width / 8) as u8,
-                    }),
-                }
+                let v = match fty {
+                    FloatTy::F32 => Single::from_bits(bits).to_u128(width).value,
+                    FloatTy::F64 => Double::from_bits(bits).to_u128(width).value,
+                };
+                // This should already fit the bit width
+                Ok(Scalar::Bits {
+                    bits: v,
+                    size: (width / 8) as u8,
+                })
             },
             // float -> int
             TyInt(t) => {
                 let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
-                match fty {
-                    FloatTy::F32 => Ok(Scalar::Bits {
-                        bits: Single::from_bits(bits).to_i128(width).value as u128,
-                        size: (width / 8) as u8,
-                    }),
-                    FloatTy::F64 => Ok(Scalar::Bits {
-                        bits: Double::from_bits(bits).to_i128(width).value as u128,
-                        size: (width / 8) as u8,
-                    }),
-                }
+                let v = match fty {
+                    FloatTy::F32 => Single::from_bits(bits).to_i128(width).value,
+                    FloatTy::F64 => Double::from_bits(bits).to_i128(width).value,
+                };
+                // We got an i128, but we may need something smaller. We have to truncate ourselves.
+                let truncated = truncate(v as u128, Size::from_bits(width as u64));
+                assert_eq!(sign_extend(truncated, Size::from_bits(width as u64)) as i128, v,
+                    "truncating and extending changed the value?!?");
+                Ok(Scalar::Bits {
+                    bits: truncated,
+                    size: (width / 8) as u8,
+                })
             },
             // f64 -> f32
             TyFloat(FloatTy::F32) if fty == FloatTy::F64 => {
index 2b97860187ab07ccde64b8de56d1a00e988d05db..539428b9e517e4679c58068eda1d553aed687c44 100644 (file)
@@ -18,6 +18,7 @@
     GlobalId, Scalar, FrameInfo, AllocType,
     EvalResult, EvalErrorKind,
     ScalarMaybeUndef,
+    truncate, sign_extend,
 };
 
 use syntax::source_map::{self, Span};
@@ -906,10 +907,12 @@ pub fn validate_mplace(
         }
     }
 
+    #[inline(always)]
     pub fn frame(&self) -> &Frame<'mir, 'tcx> {
         self.stack.last().expect("no call frames exist")
     }
 
+    #[inline(always)]
     pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> {
         self.stack.last_mut().expect("no call frames exist")
     }
@@ -1028,13 +1031,15 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
         (frames, self.tcx.span)
     }
 
+    #[inline(always)]
     pub fn sign_extend(&self, value: u128, ty: TyLayout<'_>) -> u128 {
         assert!(ty.abi.is_signed());
-        super::sign_extend(value, ty.size)
+        sign_extend(value, ty.size)
     }
 
+    #[inline(always)]
     pub fn truncate(&self, value: u128, ty: TyLayout<'_>) -> u128 {
-        super::truncate(value, ty.size)
+        truncate(value, ty.size)
     }
 
     fn dump_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usize) -> ::std::fmt::Result {
@@ -1105,18 +1110,3 @@ fn dump_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usize
     }
 }
 
-pub fn sign_extend(value: u128, size: Size) -> u128 {
-    let size = size.bits();
-    // sign extend
-    let shift = 128 - size;
-    // shift the unsigned value to the left
-    // and back to the right as signed (essentially fills with FF on the left)
-    (((value << shift) as i128) >> shift) as u128
-}
-
-pub fn truncate(value: u128, size: Size) -> u128 {
-    let size = size.bits();
-    let shift = 128 - size;
-    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
-    (value << shift) >> shift
-}
index 9cd82d84d7d03d25c55d6064d4b46d7122f87559..72bd32efe7bff839032d1ef455023f490c85c709 100644 (file)
@@ -8,8 +8,8 @@
 use rustc::ty::query::TyCtxtAt;
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
 use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, ScalarMaybeUndef,
-                            EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType};
-pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
+                            EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType, truncate};
+pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
 
 use syntax::ast::Mutability;
@@ -791,7 +791,6 @@ pub fn write_scalar(
         val: ScalarMaybeUndef,
         type_size: Size,
         type_align: Align,
-        signed: bool,
     ) -> EvalResult<'tcx> {
         let endianness = self.endianness();
         self.check_align(ptr, ptr_align)?;
@@ -815,6 +814,8 @@ pub fn write_scalar(
 
             Scalar::Bits { bits, size } => {
                 assert_eq!(size as u64, type_size.bytes());
+                assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                    "Unexpected value of size {} when writing to memory", size);
                 bits
             },
         };
@@ -823,12 +824,7 @@ pub fn write_scalar(
 
         {
             let dst = self.get_bytes_mut(ptr, type_size, ptr_align.min(type_align))?;
-            // TODO: Why do we still need `signed` here? We do NOT have it for loading!
-            if signed {
-                write_target_int(endianness, dst, bytes as i128).unwrap();
-            } else {
-                write_target_uint(endianness, dst, bytes).unwrap();
-            }
+            write_target_uint(endianness, dst, bytes).unwrap();
         }
 
         // See if we have to also write a relocation
@@ -845,9 +841,9 @@ pub fn write_scalar(
         Ok(())
     }
 
-    pub fn write_ptr_sized_unsigned(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) -> EvalResult<'tcx> {
+    pub fn write_ptr_sized(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) -> EvalResult<'tcx> {
         let ptr_size = self.pointer_size();
-        self.write_scalar(ptr.into(), ptr_align, val, ptr_size, ptr_align, false)
+        self.write_scalar(ptr.into(), ptr_align, val, ptr_size, ptr_align)
     }
 
     fn int_align(&self, size: Size) -> Align {
index 452708179009ec0e7e6345a7250ebdf74cce6b48..167fb5d184cfcc361214787ae91256e9fb4be46a 100644 (file)
@@ -13,8 +13,7 @@
 mod const_eval;
 
 pub use self::eval_context::{
-    EvalContext, Frame, StackPopCleanup,
-    sign_extend, truncate, LocalValue,
+    EvalContext, Frame, StackPopCleanup, LocalValue,
 };
 
 pub use self::place::{Place, PlaceExtra, PlaceTy, MemPlace, MPlaceTy};
index e92143c56f80ea0a8aad221f4b586767b1d23bc4..8b8c050acb7b31c5e9e2d65f5c1e423061db0ef5 100644 (file)
@@ -551,15 +551,8 @@ fn write_value_to_mplace(
         // correct if we never look at this data with the wrong type.
         match value {
             Value::Scalar(scalar) => {
-                let signed = match dest.layout.abi {
-                    layout::Abi::Scalar(ref scal) => match scal.value {
-                        layout::Primitive::Int(_, signed) => signed,
-                        _ => false,
-                    },
-                    _ => false,
-                };
                 self.memory.write_scalar(
-                    dest.ptr, dest.align, scalar, dest.layout.size, dest.layout.align, signed
+                    dest.ptr, dest.align, scalar, dest.layout.size, dest.layout.align
                 )
             }
             Value::ScalarPair(a_val, b_val) => {
@@ -572,9 +565,9 @@ fn write_value_to_mplace(
                 let a_ptr = dest.ptr;
                 let b_offset = a_size.abi_align(b_align);
                 let b_ptr = a_ptr.ptr_offset(b_offset, &self)?.into();
-                // TODO: What about signedess?
-                self.memory.write_scalar(a_ptr, dest.align, a_val, a_size, a_align, false)?;
-                self.memory.write_scalar(b_ptr, dest.align, b_val, b_size, b_align, false)
+
+                self.memory.write_scalar(a_ptr, dest.align, a_val, a_size, a_align)?;
+                self.memory.write_scalar(b_ptr, dest.align, b_val, b_size, b_align)
             }
         }
     }
index 1cc8644629ee9a13c993e312ce05d2f0ae5c9dca..18718cc3dcd6e396b7eef38501d700a0b867df29 100644 (file)
@@ -36,15 +36,15 @@ pub fn get_vtable(
 
         let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
         let drop = self.memory.create_fn_alloc(drop);
-        self.memory.write_ptr_sized_unsigned(vtable, ptr_align, Scalar::Ptr(drop).into())?;
+        self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?;
 
         let size_ptr = vtable.offset(ptr_size, &self)?;
-        self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bits {
+        self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::Bits {
             bits: size as u128,
             size: ptr_size.bytes() as u8,
         }.into())?;
         let align_ptr = vtable.offset(ptr_size * 2, &self)?;
-        self.memory.write_ptr_sized_unsigned(align_ptr, ptr_align, Scalar::Bits {
+        self.memory.write_ptr_sized(align_ptr, ptr_align, Scalar::Bits {
             bits: align as u128,
             size: ptr_size.bytes() as u8,
         }.into())?;
@@ -54,7 +54,7 @@ pub fn get_vtable(
                 let instance = self.resolve(def_id, substs)?;
                 let fn_ptr = self.memory.create_fn_alloc(instance);
                 let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
-                self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
+                self.memory.write_ptr_sized(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
             }
         }