Derive HashStable in librustc_mir.
This commit is contained in:
parent
e1522fa183
commit
d9eaaf5973
|
@ -3720,6 +3720,7 @@ dependencies = [
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_lexer",
|
"rustc_lexer",
|
||||||
|
"rustc_macros",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
"serialize",
|
"serialize",
|
||||||
"smallvec 1.0.0",
|
"smallvec 1.0.0",
|
||||||
|
|
|
@ -22,6 +22,7 @@ rustc_data_structures = { path = "../librustc_data_structures" }
|
||||||
rustc_index = { path = "../librustc_index" }
|
rustc_index = { path = "../librustc_index" }
|
||||||
rustc_errors = { path = "../librustc_errors" }
|
rustc_errors = { path = "../librustc_errors" }
|
||||||
rustc_lexer = { path = "../librustc_lexer" }
|
rustc_lexer = { path = "../librustc_lexer" }
|
||||||
|
rustc_macros = { path = "../librustc_macros" }
|
||||||
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||||
syntax = { path = "../libsyntax" }
|
syntax = { path = "../libsyntax" }
|
||||||
syntax_pos = { path = "../libsyntax_pos" }
|
syntax_pos = { path = "../libsyntax_pos" }
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::Write;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use syntax::source_map::{self, Span, DUMMY_SP};
|
use syntax::source_map::{self, Span, DUMMY_SP};
|
||||||
|
use rustc::ich::StableHashingContext;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::def::DefKind;
|
use rustc::hir::def::DefKind;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
|
@ -18,6 +19,8 @@ use rustc::mir::interpret::{
|
||||||
InterpResult, truncate, sign_extend,
|
InterpResult, truncate, sign_extend,
|
||||||
};
|
};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
|
use rustc_macros::HashStable;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Immediate, Operand, MemPlace, MPlaceTy, Place, PlaceTy, ScalarMaybeUndef,
|
Immediate, Operand, MemPlace, MPlaceTy, Place, PlaceTy, ScalarMaybeUndef,
|
||||||
|
@ -93,7 +96,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> {
|
||||||
pub stmt: usize,
|
pub stmt: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug)] // Miri debug-prints these
|
#[derive(Clone, Eq, PartialEq, Debug, HashStable)] // Miri debug-prints these
|
||||||
pub enum StackPopCleanup {
|
pub enum StackPopCleanup {
|
||||||
/// Jump to the next block in the caller, or cause UB if None (that's a function
|
/// Jump to the next block in the caller, or cause UB if None (that's a function
|
||||||
/// that may never return). Also store layout of return place so
|
/// that may never return). Also store layout of return place so
|
||||||
|
@ -109,15 +112,16 @@ pub enum StackPopCleanup {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State of a local variable including a memoized layout
|
/// State of a local variable including a memoized layout
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq, HashStable)]
|
||||||
pub struct LocalState<'tcx, Tag=(), Id=AllocId> {
|
pub struct LocalState<'tcx, Tag=(), Id=AllocId> {
|
||||||
pub value: LocalValue<Tag, Id>,
|
pub value: LocalValue<Tag, Id>,
|
||||||
/// Don't modify if `Some`, this is only used to prevent computing the layout twice
|
/// Don't modify if `Some`, this is only used to prevent computing the layout twice
|
||||||
|
#[stable_hasher(ignore)]
|
||||||
pub layout: Cell<Option<TyLayout<'tcx>>>,
|
pub layout: Cell<Option<TyLayout<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Current value of a local variable
|
/// Current value of a local variable
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)] // Miri debug-prints these
|
#[derive(Clone, PartialEq, Eq, Debug, HashStable)] // Miri debug-prints these
|
||||||
pub enum LocalValue<Tag=(), Id=AllocId> {
|
pub enum LocalValue<Tag=(), Id=AllocId> {
|
||||||
/// This local is not currently alive, and cannot be used at all.
|
/// This local is not currently alive, and cannot be used at all.
|
||||||
Dead,
|
Dead,
|
||||||
|
@ -827,3 +831,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
frames
|
frames
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ctx, 'mir, 'tcx, Tag, Extra> HashStable<StableHashingContext<'ctx>>
|
||||||
|
for Frame<'mir, 'tcx, Tag, Extra>
|
||||||
|
where Extra: HashStable<StableHashingContext<'ctx>>,
|
||||||
|
Tag: HashStable<StableHashingContext<'ctx>>
|
||||||
|
{
|
||||||
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
|
||||||
|
self.body.hash_stable(hcx, hasher);
|
||||||
|
self.instance.hash_stable(hcx, hasher);
|
||||||
|
self.span.hash_stable(hcx, hasher);
|
||||||
|
self.return_to_block.hash_stable(hcx, hasher);
|
||||||
|
self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
|
||||||
|
self.locals.hash_stable(hcx, hasher);
|
||||||
|
self.block.hash_stable(hcx, hasher);
|
||||||
|
self.stmt.hash_stable(hcx, hasher);
|
||||||
|
self.extra.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use super::{
|
||||||
MemPlace, MPlaceTy, PlaceTy, Place,
|
MemPlace, MPlaceTy, PlaceTy, Place,
|
||||||
};
|
};
|
||||||
pub use rustc::mir::interpret::ScalarMaybeUndef;
|
pub use rustc::mir::interpret::ScalarMaybeUndef;
|
||||||
|
use rustc_macros::HashStable;
|
||||||
|
|
||||||
/// An `Immediate` represents a single immediate self-contained Rust value.
|
/// An `Immediate` represents a single immediate self-contained Rust value.
|
||||||
///
|
///
|
||||||
|
@ -26,7 +27,7 @@ pub use rustc::mir::interpret::ScalarMaybeUndef;
|
||||||
/// operations and fat pointers. This idea was taken from rustc's codegen.
|
/// operations and fat pointers. This idea was taken from rustc's codegen.
|
||||||
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
|
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
|
||||||
/// defined on `Immediate`, and do not have to work with a `Place`.
|
/// defined on `Immediate`, and do not have to work with a `Place`.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
|
||||||
pub enum Immediate<Tag=(), Id=AllocId> {
|
pub enum Immediate<Tag=(), Id=AllocId> {
|
||||||
Scalar(ScalarMaybeUndef<Tag, Id>),
|
Scalar(ScalarMaybeUndef<Tag, Id>),
|
||||||
ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
|
ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
|
||||||
|
@ -103,7 +104,7 @@ impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> {
|
||||||
/// An `Operand` is the result of computing a `mir::Operand`. It can be immediate,
|
/// An `Operand` is the result of computing a `mir::Operand`. It can be immediate,
|
||||||
/// or still in memory. The latter is an optimization, to delay reading that chunk of
|
/// or still in memory. The latter is an optimization, to delay reading that chunk of
|
||||||
/// memory and to avoid having to store arbitrary-sized data here.
|
/// memory and to avoid having to store arbitrary-sized data here.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
|
||||||
pub enum Operand<Tag=(), Id=AllocId> {
|
pub enum Operand<Tag=(), Id=AllocId> {
|
||||||
Immediate(Immediate<Tag, Id>),
|
Immediate(Immediate<Tag, Id>),
|
||||||
Indirect(MemPlace<Tag, Id>),
|
Indirect(MemPlace<Tag, Id>),
|
||||||
|
|
|
@ -12,6 +12,7 @@ use rustc::ty::layout::{
|
||||||
self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
|
self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
|
||||||
};
|
};
|
||||||
use rustc::ty::TypeFoldable;
|
use rustc::ty::TypeFoldable;
|
||||||
|
use rustc_macros::HashStable;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
|
GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
|
||||||
|
@ -19,7 +20,7 @@ use super::{
|
||||||
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue,
|
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
pub struct MemPlace<Tag=(), Id=AllocId> {
|
pub struct MemPlace<Tag=(), Id=AllocId> {
|
||||||
/// A place may have an integral pointer for ZSTs, and since it might
|
/// A place may have an integral pointer for ZSTs, and since it might
|
||||||
/// be turned back into a reference before ever being dereferenced.
|
/// be turned back into a reference before ever being dereferenced.
|
||||||
|
@ -32,7 +33,7 @@ pub struct MemPlace<Tag=(), Id=AllocId> {
|
||||||
pub meta: Option<Scalar<Tag, Id>>,
|
pub meta: Option<Scalar<Tag, Id>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)]
|
||||||
pub enum Place<Tag=(), Id=AllocId> {
|
pub enum Place<Tag=(), Id=AllocId> {
|
||||||
/// A place referring to a value allocated in the `Memory` system.
|
/// A place referring to a value allocated in the `Memory` system.
|
||||||
Ptr(MemPlace<Tag, Id>),
|
Ptr(MemPlace<Tag, Id>),
|
||||||
|
|
|
@ -19,6 +19,7 @@ use rustc::ty::layout::{Align, Size};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
|
use rustc_macros::HashStable;
|
||||||
use syntax::ast::Mutability;
|
use syntax::ast::Mutability;
|
||||||
use syntax::source_map::Span;
|
use syntax::source_map::Span;
|
||||||
|
|
||||||
|
@ -197,21 +198,12 @@ impl_snapshot_for!(enum ScalarMaybeUndef {
|
||||||
Undef,
|
Undef,
|
||||||
});
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(struct crate::interpret::MemPlace {
|
|
||||||
ptr,
|
|
||||||
align,
|
|
||||||
meta,
|
|
||||||
});
|
|
||||||
impl_snapshot_for!(struct MemPlace {
|
impl_snapshot_for!(struct MemPlace {
|
||||||
ptr,
|
ptr,
|
||||||
meta,
|
meta,
|
||||||
align -> *align, // just copy alignment verbatim
|
align -> *align, // just copy alignment verbatim
|
||||||
});
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(enum crate::interpret::Place {
|
|
||||||
Ptr(mem_place),
|
|
||||||
Local { frame, local },
|
|
||||||
});
|
|
||||||
impl<'a, Ctx> Snapshot<'a, Ctx> for Place
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Place
|
||||||
where Ctx: SnapshotContext<'a>,
|
where Ctx: SnapshotContext<'a>,
|
||||||
{
|
{
|
||||||
|
@ -229,29 +221,16 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for Place
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(enum crate::interpret::Immediate {
|
|
||||||
Scalar(x),
|
|
||||||
ScalarPair(x, y),
|
|
||||||
});
|
|
||||||
impl_snapshot_for!(enum Immediate {
|
impl_snapshot_for!(enum Immediate {
|
||||||
Scalar(s),
|
Scalar(s),
|
||||||
ScalarPair(s, t),
|
ScalarPair(s, t),
|
||||||
});
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(enum crate::interpret::Operand {
|
|
||||||
Immediate(x),
|
|
||||||
Indirect(x),
|
|
||||||
});
|
|
||||||
impl_snapshot_for!(enum Operand {
|
impl_snapshot_for!(enum Operand {
|
||||||
Immediate(v),
|
Immediate(v),
|
||||||
Indirect(m),
|
Indirect(m),
|
||||||
});
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(enum crate::interpret::LocalValue {
|
|
||||||
Dead,
|
|
||||||
Uninitialized,
|
|
||||||
Live(x),
|
|
||||||
});
|
|
||||||
impl_snapshot_for!(enum LocalValue {
|
impl_snapshot_for!(enum LocalValue {
|
||||||
Dead,
|
Dead,
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
@ -314,11 +293,6 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(enum crate::interpret::eval_context::StackPopCleanup {
|
|
||||||
Goto { ret, unwind },
|
|
||||||
None { cleanup },
|
|
||||||
});
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
struct FrameSnapshot<'a, 'tcx> {
|
struct FrameSnapshot<'a, 'tcx> {
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
|
@ -330,18 +304,6 @@ struct FrameSnapshot<'a, 'tcx> {
|
||||||
stmt: usize,
|
stmt: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(impl<> for struct Frame<'mir, 'tcx> {
|
|
||||||
body,
|
|
||||||
instance,
|
|
||||||
span,
|
|
||||||
return_to_block,
|
|
||||||
return_place -> (return_place.as_ref().map(|r| &**r)),
|
|
||||||
locals,
|
|
||||||
block,
|
|
||||||
stmt,
|
|
||||||
extra,
|
|
||||||
});
|
|
||||||
|
|
||||||
impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
|
impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
|
||||||
where Ctx: SnapshotContext<'a>,
|
where Ctx: SnapshotContext<'a>,
|
||||||
{
|
{
|
||||||
|
@ -383,11 +345,6 @@ impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct LocalState<'tcx> {
|
|
||||||
value,
|
|
||||||
layout -> _,
|
|
||||||
});
|
|
||||||
|
|
||||||
impl<'b, 'mir, 'tcx> SnapshotContext<'b>
|
impl<'b, 'mir, 'tcx> SnapshotContext<'b>
|
||||||
for Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>
|
for Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>
|
||||||
{
|
{
|
||||||
|
@ -399,7 +356,10 @@ impl<'b, 'mir, 'tcx> SnapshotContext<'b>
|
||||||
/// The virtual machine state during const-evaluation at a given point in time.
|
/// The virtual machine state during const-evaluation at a given point in time.
|
||||||
/// We assume the `CompileTimeInterpreter` has no interesting extra state that
|
/// We assume the `CompileTimeInterpreter` has no interesting extra state that
|
||||||
/// is worth considering here.
|
/// is worth considering here.
|
||||||
|
#[derive(HashStable)]
|
||||||
struct InterpSnapshot<'mir, 'tcx> {
|
struct InterpSnapshot<'mir, 'tcx> {
|
||||||
|
// Not hashing memory: Avoid hashing memory all the time during execution
|
||||||
|
#[stable_hasher(ignore)]
|
||||||
memory: Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
memory: Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
|
||||||
stack: Vec<Frame<'mir, 'tcx>>,
|
stack: Vec<Frame<'mir, 'tcx>>,
|
||||||
}
|
}
|
||||||
|
@ -434,12 +394,6 @@ impl<'mir, 'tcx> Hash for InterpSnapshot<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(impl<> for struct InterpSnapshot<'mir, 'tcx> {
|
|
||||||
// Not hashing memory: Avoid hashing memory all the time during execution
|
|
||||||
memory -> _,
|
|
||||||
stack,
|
|
||||||
});
|
|
||||||
|
|
||||||
impl<'mir, 'tcx> Eq for InterpSnapshot<'mir, 'tcx> {}
|
impl<'mir, 'tcx> Eq for InterpSnapshot<'mir, 'tcx> {}
|
||||||
|
|
||||||
impl<'mir, 'tcx> PartialEq for InterpSnapshot<'mir, 'tcx> {
|
impl<'mir, 'tcx> PartialEq for InterpSnapshot<'mir, 'tcx> {
|
||||||
|
|
Loading…
Reference in New Issue