Introduce Snapshot and SnapshotContext traits

This commit is contained in:
Bruno Dutra 2018-08-18 12:14:18 +02:00
parent 2f5c3fde7c
commit adb1965c12

View File

@ -1,9 +1,273 @@
use std::hash::{Hash, Hasher};
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 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.
#[derive(Eq, PartialEq)]