Derive HashStable in librustc_mir.

This commit is contained in:
Camille GILLOT 2019-11-10 19:30:19 +01:00
parent e1522fa183
commit d9eaaf5973
6 changed files with 37 additions and 57 deletions

View File

@ -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",

View File

@ -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" }

View File

@ -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);
}
}

View File

@ -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>),

View File

@ -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>),

View File

@ -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> {