Skip to content

Commit

Permalink
Auto merge of #53424 - RalfJung:miri-refactor, r=oli-obk
Browse files Browse the repository at this point in the history
CTFE engine refactor

* Value gets renamed to `Operand`, so that now `interpret::{Place, Operand}` are the "dynamic" versions of `mir::{Place, Operand}`.
* `Operand` and `Place` share the data for their "stuff is in memory"-base in a new type, `MemPlace`. This also makes it possible to give some more precise types in other areas. Both `Operand` and `MemPlace` have methods available to project into fields (and other kinds of projections) without causing further allocations.
* The type for "a `Scalar` or a `ScalarPair`" is called `Value`, and again used to give some more precise types.
* All of these have versions with an attached layout, so that we can more often drag the layout along instead of recomputing it. This lets us get rid of `PlaceExtra::Downcast`. `MPlaceTy` and `PlaceTy` can only be constructed in place.rs, making sure the layout is handled properly. (The same should eventually be done for `ValTy` and `OpTy`.)
 This is used to check, when copying an operand to a place, that the sizes match (which caught a bunch of bugs).
* All the high-level functions to write typed memory take a `Place`, and live in `place.rs`. All the high-level typed functions to read typed memory take an `Operand`, and live in `operands.rs`.
* Remove `cur_frame` and handling of signedess from memory (catching a bug in the float casting code).
* [Only functional change] Enable sanity check to recurse below dyn traits and slices.

r? @oli-obk

Cc @eddyb
  • Loading branch information
bors committed Aug 22, 2018
2 parents 71a1ef1 + 4fec615 commit 674ef66
Show file tree
Hide file tree
Showing 39 changed files with 2,827 additions and 2,444 deletions.
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ define_dep_nodes!( <'tcx>
// queries). Making them anonymous avoids hashing the result, which
// may save a bit of time.
[anon] EraseRegionsTy { ty: Ty<'tcx> },
[anon] ConstValueToAllocation { val: &'tcx ty::Const<'tcx> },
[anon] ConstToAllocation { val: &'tcx ty::Const<'tcx> },

[input] Freevars(DefId),
[input] MaybeUnusedTraitImport(DefId),
Expand Down
6 changes: 0 additions & 6 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,6 @@ impl_stable_hash_for!(enum mir::interpret::ScalarMaybeUndef {
Undef
});

impl_stable_hash_for!(enum mir::interpret::Value {
Scalar(v),
ScalarPair(a, b),
ByRef(ptr, align)
});

impl_stable_hash_for!(struct mir::interpret::Pointer {
alloc_id,
offset
Expand Down
38 changes: 23 additions & 15 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub use self::error::{
FrameInfo, ConstEvalResult,
};

pub use self::value::{Scalar, Value, ConstValue, ScalarMaybeUndef};
pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};

use std::fmt;
use mir;
Expand Down Expand Up @@ -135,7 +135,7 @@ impl<'tcx> Pointer {
Pointer { alloc_id, offset }
}

pub(crate) fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
pub fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
Pointer::new(
self.alloc_id,
Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
Expand All @@ -147,7 +147,7 @@ impl<'tcx> Pointer {
(Pointer::new(self.alloc_id, Size::from_bytes(res)), over)
}

pub(crate) fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
Ok(Pointer::new(
self.alloc_id,
Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
Expand Down Expand Up @@ -567,25 +567,33 @@ 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()),
layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
}
}

////////////////////////////////////////////////////////////////////////////////
// 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
////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading

0 comments on commit 674ef66

Please sign in to comment.