Skip to content

Commit aa760a5

Browse files
committed
finally remove all traces of signs from memory
1 parent b1df2ae commit aa760a5

File tree

9 files changed

+93
-88
lines changed

9 files changed

+93
-88
lines changed

src/librustc/mir/interpret/mod.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -567,25 +567,33 @@ pub fn write_target_uint(
567567
}
568568
}
569569

570-
pub fn write_target_int(
571-
endianness: layout::Endian,
572-
mut target: &mut [u8],
573-
data: i128,
574-
) -> Result<(), io::Error> {
575-
let len = target.len();
576-
match endianness {
577-
layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
578-
layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
579-
}
580-
}
581-
582570
pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
583571
match endianness {
584572
layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
585573
layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
586574
}
587575
}
588576

577+
////////////////////////////////////////////////////////////////////////////////
578+
// Methods to faciliate working with signed integers stored in a u128
579+
////////////////////////////////////////////////////////////////////////////////
580+
581+
pub fn sign_extend(value: u128, size: Size) -> u128 {
582+
let size = size.bits();
583+
// sign extend
584+
let shift = 128 - size;
585+
// shift the unsigned value to the left
586+
// and back to the right as signed (essentially fills with FF on the left)
587+
(((value << shift) as i128) >> shift) as u128
588+
}
589+
590+
pub fn truncate(value: u128, size: Size) -> u128 {
591+
let size = size.bits();
592+
let shift = 128 - size;
593+
// truncate (shift left to drop out leftover values, shift right to fill with zeroes)
594+
(value << shift) >> shift
595+
}
596+
589597
////////////////////////////////////////////////////////////////////////////////
590598
// Undefined byte tracking
591599
////////////////////////////////////////////////////////////////////////////////

src/librustc/mir/interpret/value.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ pub enum Scalar {
191191
/// The raw bytes of a simple value.
192192
Bits {
193193
/// The first `size` bytes are the value.
194-
/// Do not try to read less or more bytes that that
194+
/// Do not try to read less or more bytes that that. The remaining bytes must be 0.
195195
size: u8,
196196
bits: u128,
197197
},

src/librustc_mir/hair/pattern/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ mod check_match;
1616
pub use self::check_match::check_crate;
1717
pub(crate) use self::check_match::check_match;
1818

19-
use interpret::{const_field, const_variant_index, self};
19+
use interpret::{const_field, const_variant_index};
2020

2121
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
22-
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue};
22+
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
2323
use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
2424
use rustc::ty::subst::{Substs, Kind};
2525
use rustc::hir::{self, PatKind, RangeEnd};
@@ -1086,8 +1086,8 @@ pub fn compare_const_vals<'a, 'tcx>(
10861086
ty::TyInt(_) => {
10871087
let layout = tcx.layout_of(ty).ok()?;
10881088
assert!(layout.abi.is_signed());
1089-
let a = interpret::sign_extend(a, layout.size);
1090-
let b = interpret::sign_extend(b, layout.size);
1089+
let a = sign_extend(a, layout.size);
1090+
let b = sign_extend(b, layout.size);
10911091
Some((a as i128).cmp(&(b as i128)))
10921092
},
10931093
_ => Some(a.cmp(&b)),

src/librustc_mir/interpret/cast.rs

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use rustc::ty::{self, Ty, TypeAndMut};
2-
use rustc::ty::layout::{self, TyLayout};
2+
use rustc::ty::layout::{self, TyLayout, Size};
33
use syntax::ast::{FloatTy, IntTy, UintTy};
44

55
use rustc_apfloat::ieee::{Single, Double};
6-
use rustc::mir::interpret::{Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind};
6+
use rustc::mir::interpret::{
7+
Scalar, EvalResult, Pointer, PointerArithmetic, EvalErrorKind,
8+
truncate, sign_extend
9+
};
710
use rustc::mir::CastKind;
811
use rustc_apfloat::Float;
912

@@ -144,11 +147,26 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
144147
match val {
145148
Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
146149
Scalar::Bits { bits, size } => {
147-
assert_eq!(size as u64, src_layout.size.bytes());
148-
match src_layout.ty.sty {
149-
TyFloat(fty) => self.cast_from_float(bits, fty, dest_layout.ty),
150-
_ => self.cast_from_int(bits, src_layout, dest_layout),
150+
debug_assert_eq!(size as u64, src_layout.size.bytes());
151+
debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
152+
"Unexpected value of size {} before casting", size);
153+
154+
let res = match src_layout.ty.sty {
155+
TyFloat(fty) => self.cast_from_float(bits, fty, dest_layout.ty)?,
156+
_ => self.cast_from_int(bits, src_layout, dest_layout)?,
157+
};
158+
159+
// Sanity check
160+
match res {
161+
Scalar::Ptr(_) => bug!("Fabricated a ptr value from an int...?"),
162+
Scalar::Bits { bits, size } => {
163+
debug_assert_eq!(size as u64, dest_layout.size.bytes());
164+
debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
165+
"Unexpected value of size {} after casting", size);
166+
}
151167
}
168+
// Done
169+
Ok(res)
152170
}
153171
}
154172
}
@@ -218,30 +236,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
218236
// float -> uint
219237
TyUint(t) => {
220238
let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
221-
match fty {
222-
FloatTy::F32 => Ok(Scalar::Bits {
223-
bits: Single::from_bits(bits).to_u128(width).value,
224-
size: (width / 8) as u8,
225-
}),
226-
FloatTy::F64 => Ok(Scalar::Bits {
227-
bits: Double::from_bits(bits).to_u128(width).value,
228-
size: (width / 8) as u8,
229-
}),
230-
}
239+
let v = match fty {
240+
FloatTy::F32 => Single::from_bits(bits).to_u128(width).value,
241+
FloatTy::F64 => Double::from_bits(bits).to_u128(width).value,
242+
};
243+
// This should already fit the bit width
244+
Ok(Scalar::Bits {
245+
bits: v,
246+
size: (width / 8) as u8,
247+
})
231248
},
232249
// float -> int
233250
TyInt(t) => {
234251
let width = t.bit_width().unwrap_or(self.memory.pointer_size().bits() as usize);
235-
match fty {
236-
FloatTy::F32 => Ok(Scalar::Bits {
237-
bits: Single::from_bits(bits).to_i128(width).value as u128,
238-
size: (width / 8) as u8,
239-
}),
240-
FloatTy::F64 => Ok(Scalar::Bits {
241-
bits: Double::from_bits(bits).to_i128(width).value as u128,
242-
size: (width / 8) as u8,
243-
}),
244-
}
252+
let v = match fty {
253+
FloatTy::F32 => Single::from_bits(bits).to_i128(width).value,
254+
FloatTy::F64 => Double::from_bits(bits).to_i128(width).value,
255+
};
256+
// We got an i128, but we may need something smaller. We have to truncate ourselves.
257+
let truncated = truncate(v as u128, Size::from_bits(width as u64));
258+
assert_eq!(sign_extend(truncated, Size::from_bits(width as u64)) as i128, v,
259+
"truncating and extending changed the value?!?");
260+
Ok(Scalar::Bits {
261+
bits: truncated,
262+
size: (width / 8) as u8,
263+
})
245264
},
246265
// f64 -> f32
247266
TyFloat(FloatTy::F32) if fty == FloatTy::F64 => {

src/librustc_mir/interpret/eval_context.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc::mir::interpret::{
1818
GlobalId, Scalar, FrameInfo, AllocType,
1919
EvalResult, EvalErrorKind,
2020
ScalarMaybeUndef,
21+
truncate, sign_extend,
2122
};
2223

2324
use syntax::source_map::{self, Span};
@@ -906,10 +907,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
906907
}
907908
}
908909

910+
#[inline(always)]
909911
pub fn frame(&self) -> &Frame<'mir, 'tcx> {
910912
self.stack.last().expect("no call frames exist")
911913
}
912914

915+
#[inline(always)]
913916
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx> {
914917
self.stack.last_mut().expect("no call frames exist")
915918
}
@@ -1028,13 +1031,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
10281031
(frames, self.tcx.span)
10291032
}
10301033

1034+
#[inline(always)]
10311035
pub fn sign_extend(&self, value: u128, ty: TyLayout<'_>) -> u128 {
10321036
assert!(ty.abi.is_signed());
1033-
super::sign_extend(value, ty.size)
1037+
sign_extend(value, ty.size)
10341038
}
10351039

1040+
#[inline(always)]
10361041
pub fn truncate(&self, value: u128, ty: TyLayout<'_>) -> u128 {
1037-
super::truncate(value, ty.size)
1042+
truncate(value, ty.size)
10381043
}
10391044

10401045
fn dump_field_name(&self, s: &mut String, ty: Ty<'tcx>, i: usize, variant: usize) -> ::std::fmt::Result {
@@ -1105,18 +1110,3 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
11051110
}
11061111
}
11071112

1108-
pub fn sign_extend(value: u128, size: Size) -> u128 {
1109-
let size = size.bits();
1110-
// sign extend
1111-
let shift = 128 - size;
1112-
// shift the unsigned value to the left
1113-
// and back to the right as signed (essentially fills with FF on the left)
1114-
(((value << shift) as i128) >> shift) as u128
1115-
}
1116-
1117-
pub fn truncate(value: u128, size: Size) -> u128 {
1118-
let size = size.bits();
1119-
let shift = 128 - size;
1120-
// truncate (shift left to drop out leftover values, shift right to fill with zeroes)
1121-
(value << shift) >> shift
1122-
}

src/librustc_mir/interpret/memory.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use rustc::ty::ParamEnv;
88
use rustc::ty::query::TyCtxtAt;
99
use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
1010
use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, ScalarMaybeUndef,
11-
EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType};
12-
pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
11+
EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType, truncate};
12+
pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
1313
use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
1414

1515
use syntax::ast::Mutability;
@@ -791,7 +791,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
791791
val: ScalarMaybeUndef,
792792
type_size: Size,
793793
type_align: Align,
794-
signed: bool,
795794
) -> EvalResult<'tcx> {
796795
let endianness = self.endianness();
797796
self.check_align(ptr, ptr_align)?;
@@ -815,6 +814,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
815814

816815
Scalar::Bits { bits, size } => {
817816
assert_eq!(size as u64, type_size.bytes());
817+
assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
818+
"Unexpected value of size {} when writing to memory", size);
818819
bits
819820
},
820821
};
@@ -823,12 +824,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
823824

824825
{
825826
let dst = self.get_bytes_mut(ptr, type_size, ptr_align.min(type_align))?;
826-
// TODO: Why do we still need `signed` here? We do NOT have it for loading!
827-
if signed {
828-
write_target_int(endianness, dst, bytes as i128).unwrap();
829-
} else {
830-
write_target_uint(endianness, dst, bytes).unwrap();
831-
}
827+
write_target_uint(endianness, dst, bytes).unwrap();
832828
}
833829

834830
// See if we have to also write a relocation
@@ -845,9 +841,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
845841
Ok(())
846842
}
847843

848-
pub fn write_ptr_sized_unsigned(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) -> EvalResult<'tcx> {
844+
pub fn write_ptr_sized(&mut self, ptr: Pointer, ptr_align: Align, val: ScalarMaybeUndef) -> EvalResult<'tcx> {
849845
let ptr_size = self.pointer_size();
850-
self.write_scalar(ptr.into(), ptr_align, val, ptr_size, ptr_align, false)
846+
self.write_scalar(ptr.into(), ptr_align, val, ptr_size, ptr_align)
851847
}
852848

853849
fn int_align(&self, size: Size) -> Align {

src/librustc_mir/interpret/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ mod traits;
1313
mod const_eval;
1414

1515
pub use self::eval_context::{
16-
EvalContext, Frame, StackPopCleanup,
17-
sign_extend, truncate, LocalValue,
16+
EvalContext, Frame, StackPopCleanup, LocalValue,
1817
};
1918

2019
pub use self::place::{Place, PlaceExtra, PlaceTy, MemPlace, MPlaceTy};

src/librustc_mir/interpret/place.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -551,15 +551,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
551551
// correct if we never look at this data with the wrong type.
552552
match value {
553553
Value::Scalar(scalar) => {
554-
let signed = match dest.layout.abi {
555-
layout::Abi::Scalar(ref scal) => match scal.value {
556-
layout::Primitive::Int(_, signed) => signed,
557-
_ => false,
558-
},
559-
_ => false,
560-
};
561554
self.memory.write_scalar(
562-
dest.ptr, dest.align, scalar, dest.layout.size, dest.layout.align, signed
555+
dest.ptr, dest.align, scalar, dest.layout.size, dest.layout.align
563556
)
564557
}
565558
Value::ScalarPair(a_val, b_val) => {
@@ -572,9 +565,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
572565
let a_ptr = dest.ptr;
573566
let b_offset = a_size.abi_align(b_align);
574567
let b_ptr = a_ptr.ptr_offset(b_offset, &self)?.into();
575-
// TODO: What about signedess?
576-
self.memory.write_scalar(a_ptr, dest.align, a_val, a_size, a_align, false)?;
577-
self.memory.write_scalar(b_ptr, dest.align, b_val, b_size, b_align, false)
568+
569+
self.memory.write_scalar(a_ptr, dest.align, a_val, a_size, a_align)?;
570+
self.memory.write_scalar(b_ptr, dest.align, b_val, b_size, b_align)
578571
}
579572
}
580573
}

src/librustc_mir/interpret/traits.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
3636

3737
let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
3838
let drop = self.memory.create_fn_alloc(drop);
39-
self.memory.write_ptr_sized_unsigned(vtable, ptr_align, Scalar::Ptr(drop).into())?;
39+
self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?;
4040

4141
let size_ptr = vtable.offset(ptr_size, &self)?;
42-
self.memory.write_ptr_sized_unsigned(size_ptr, ptr_align, Scalar::Bits {
42+
self.memory.write_ptr_sized(size_ptr, ptr_align, Scalar::Bits {
4343
bits: size as u128,
4444
size: ptr_size.bytes() as u8,
4545
}.into())?;
4646
let align_ptr = vtable.offset(ptr_size * 2, &self)?;
47-
self.memory.write_ptr_sized_unsigned(align_ptr, ptr_align, Scalar::Bits {
47+
self.memory.write_ptr_sized(align_ptr, ptr_align, Scalar::Bits {
4848
bits: align as u128,
4949
size: ptr_size.bytes() as u8,
5050
}.into())?;
@@ -54,7 +54,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
5454
let instance = self.resolve(def_id, substs)?;
5555
let fn_ptr = self.memory.create_fn_alloc(instance);
5656
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
57-
self.memory.write_ptr_sized_unsigned(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
57+
self.memory.write_ptr_sized(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
5858
}
5959
}
6060

0 commit comments

Comments
 (0)