Introduce Snapshot and SnapshotContext traits
This commit is contained in:
parent
2f5c3fde7c
commit
adb1965c12
1 changed files with 265 additions and 1 deletions
|
@ -1,9 +1,273 @@
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use rustc::ich::{StableHashingContext, StableHashingContextProvider};
|
use rustc::ich::{StableHashingContext, StableHashingContextProvider};
|
||||||
|
use rustc::mir;
|
||||||
|
use rustc::mir::interpret::{AllocId, Pointer, Scalar, ScalarMaybeUndef, Relocations, Allocation, UndefMask};
|
||||||
|
use rustc::ty;
|
||||||
|
use rustc::ty::layout::Align;
|
||||||
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
|
||||||
|
use syntax::ast::Mutability;
|
||||||
|
use syntax::source_map::Span;
|
||||||
|
|
||||||
use super::{Frame, Memory, Machine};
|
use super::eval_context::{LocalValue, StackPopCleanup};
|
||||||
|
use super::{Frame, Memory, Machine, Operand, MemPlace, Place, PlaceExtra, Value};
|
||||||
|
|
||||||
|
trait SnapshotContext<'a> {
|
||||||
|
type To;
|
||||||
|
type From;
|
||||||
|
fn resolve(&'a self, id: &Self::From) -> Option<&'a Self::To>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Snapshot<'a, Ctx: SnapshotContext<'a>> {
|
||||||
|
type Item;
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
struct AllocIdSnapshot<'a>(Option<AllocationSnapshot<'a>>);
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = AllocIdSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PointerSnapshot<'a> = Pointer<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Pointer
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = PointerSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
let Pointer{ alloc_id, offset } = self;
|
||||||
|
|
||||||
|
Pointer {
|
||||||
|
alloc_id: alloc_id.snapshot(ctx),
|
||||||
|
offset: *offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScalarSnapshot<'a> = Scalar<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = ScalarSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)),
|
||||||
|
Scalar::Bits{ size, bits } => Scalar::Bits{
|
||||||
|
size: *size,
|
||||||
|
bits: *bits,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScalarMaybeUndefSnapshot<'a> = ScalarMaybeUndef<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for ScalarMaybeUndef
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = ScalarMaybeUndefSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.snapshot(ctx)),
|
||||||
|
ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MemPlaceSnapshot<'a> = MemPlace<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for MemPlace
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = MemPlaceSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
let MemPlace{ ptr, extra, align } = self;
|
||||||
|
|
||||||
|
MemPlaceSnapshot{
|
||||||
|
ptr: ptr.snapshot(ctx),
|
||||||
|
extra: extra.snapshot(ctx),
|
||||||
|
align: *align,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlaceSnapshot<'a> = Place<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Place
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = PlaceSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)),
|
||||||
|
|
||||||
|
Place::Local{ frame, local } => Place::Local{
|
||||||
|
frame: *frame,
|
||||||
|
local: *local,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlaceExtraSnapshot<'a> = PlaceExtra<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for PlaceExtra
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = PlaceExtraSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
PlaceExtra::Vtable(p) => PlaceExtra::Vtable(p.snapshot(ctx)),
|
||||||
|
PlaceExtra::Length(l) => PlaceExtra::Length(*l),
|
||||||
|
PlaceExtra::None => PlaceExtra::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueSnapshot<'a> = Value<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Value
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = ValueSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
Value::Scalar(s) => Value::Scalar(s.snapshot(ctx)),
|
||||||
|
Value::ScalarPair(a, b) => Value::ScalarPair(a.snapshot(ctx), b.snapshot(ctx)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type OperandSnapshot<'a> = Operand<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Operand
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = OperandSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
Operand::Immediate(v) => Operand::Immediate(v.snapshot(ctx)),
|
||||||
|
Operand::Indirect(m) => Operand::Indirect(m.snapshot(ctx)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocalValueSnapshot<'a> = LocalValue<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for LocalValue
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = LocalValueSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
match self {
|
||||||
|
LocalValue::Live(v) => LocalValue::Live(v.snapshot(ctx)),
|
||||||
|
LocalValue::Dead => LocalValue::Dead,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RelocationsSnapshot<'a> = Relocations<AllocIdSnapshot<'a>>;
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = RelocationsSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
Relocations::from_presorted(self.iter().map(|(size, id)| (*size, id.snapshot(ctx))).collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
struct AllocationSnapshot<'a> {
|
||||||
|
bytes: &'a [u8],
|
||||||
|
relocations: RelocationsSnapshot<'a>,
|
||||||
|
undef_mask: &'a UndefMask,
|
||||||
|
align: &'a Align,
|
||||||
|
runtime_mutability: &'a Mutability,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = AllocationSnapshot<'a>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
let Allocation { bytes, relocations, undef_mask, align, runtime_mutability } = self;
|
||||||
|
|
||||||
|
AllocationSnapshot {
|
||||||
|
bytes,
|
||||||
|
undef_mask,
|
||||||
|
align,
|
||||||
|
runtime_mutability,
|
||||||
|
relocations: relocations.snapshot(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
struct FrameSnapshot<'a, 'tcx> {
|
||||||
|
instance: &'a ty::Instance<'tcx>,
|
||||||
|
span: &'a Span,
|
||||||
|
return_to_block: &'a StackPopCleanup,
|
||||||
|
return_place: PlaceSnapshot<'a>,
|
||||||
|
locals: IndexVec<mir::Local, LocalValueSnapshot<'a>>,
|
||||||
|
block: &'a mir::BasicBlock,
|
||||||
|
stmt: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
|
||||||
|
where Ctx: SnapshotContext<'a, To=Allocation, From=AllocId>,
|
||||||
|
{
|
||||||
|
type Item = FrameSnapshot<'a, 'tcx>;
|
||||||
|
|
||||||
|
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
|
||||||
|
let Frame {
|
||||||
|
mir: _,
|
||||||
|
instance,
|
||||||
|
span,
|
||||||
|
return_to_block,
|
||||||
|
return_place,
|
||||||
|
locals,
|
||||||
|
block,
|
||||||
|
stmt,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
FrameSnapshot {
|
||||||
|
instance,
|
||||||
|
span,
|
||||||
|
return_to_block,
|
||||||
|
block,
|
||||||
|
stmt: *stmt,
|
||||||
|
return_place: return_place.snapshot(ctx),
|
||||||
|
locals: locals.iter().map(|local| local.snapshot(ctx)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
struct MemorySnapshot<'a, 'mir: 'a, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx> + 'a> {
|
||||||
|
data: &'a M::MemoryData,
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
#[derive(Eq, PartialEq)]
|
#[derive(Eq, PartialEq)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue