allow Machine to hook into foreign statics; remove unused HasMemory trait
This commit is contained in:
parent
2592b20347
commit
286fc5caa2
@ -11,10 +11,10 @@
|
||||
use std::fmt;
|
||||
use std::error::Error;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{self, def_id::DefId};
|
||||
use rustc::mir::interpret::ConstEvalErr;
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, ParamEnv, TyCtxt, Instance, query::TyCtxtAt};
|
||||
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
|
||||
use rustc::ty::layout::{LayoutOf, TyLayout};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
@ -325,6 +325,13 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_foreign_static<'a>(
|
||||
_tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
_def_id: DefId,
|
||||
) -> EvalResult<'tcx, &'tcx Allocation> {
|
||||
err!(ReadForeignStatic)
|
||||
}
|
||||
|
||||
fn box_alloc<'a>(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_dest: PlaceTy<'tcx>,
|
||||
@ -333,16 +340,6 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
|
||||
ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn global_item_with_linkage<'a>(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_mutability: Mutability,
|
||||
) -> EvalResult<'tcx> {
|
||||
Err(
|
||||
ConstEvalError::NotConst("statics with `linkage` attribute".to_string()).into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Project to a field of a (variant of a) const
|
||||
@ -481,43 +478,3 @@ pub fn const_eval_provider<'a, 'tcx>(
|
||||
err.into()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// Helper function to obtain the global (tcx) allocation for a static
|
||||
pub fn static_alloc<'a, 'tcx>(
|
||||
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
id: AllocId,
|
||||
) -> EvalResult<'tcx, &'tcx Allocation> {
|
||||
let alloc = tcx.alloc_map.lock().get(id);
|
||||
let def_id = match alloc {
|
||||
Some(AllocType::Memory(mem)) => {
|
||||
return Ok(mem)
|
||||
}
|
||||
Some(AllocType::Function(..)) => {
|
||||
return err!(DerefFunctionPointer)
|
||||
}
|
||||
Some(AllocType::Static(did)) => {
|
||||
did
|
||||
}
|
||||
None =>
|
||||
return err!(DanglingPointerDeref),
|
||||
};
|
||||
// We got a "lazy" static that has not been computed yet, do some work
|
||||
trace!("static_alloc: Need to compute {:?}", def_id);
|
||||
if tcx.is_foreign_item(def_id) {
|
||||
return err!(ReadForeignStatic);
|
||||
}
|
||||
let instance = Instance::mono(tcx.tcx, def_id);
|
||||
let gid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
|
||||
// no need to report anything, the const_eval call takes care of that for statics
|
||||
assert!(tcx.is_static(def_id).is_some());
|
||||
EvalErrorKind::ReferencedConstant(err).into()
|
||||
}).map(|val| {
|
||||
// FIXME We got our static (will be a ByRef), now we make a *copy*?!?
|
||||
tcx.const_to_allocation(val)
|
||||
})
|
||||
}
|
||||
|
@ -14,12 +14,12 @@
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::interpret::{AllocId, Allocation, EvalResult, Scalar};
|
||||
use super::{EvalContext, PlaceTy, OpTy, Memory};
|
||||
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, layout::TyLayout};
|
||||
use syntax::ast::Mutability;
|
||||
use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
|
||||
|
||||
use super::{EvalContext, PlaceTy, OpTy, Memory};
|
||||
|
||||
/// Used by the machine to tell if a certain allocation is for static memory
|
||||
pub trait IsStatic {
|
||||
@ -62,6 +62,12 @@ pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
|
||||
dest: PlaceTy<'tcx>,
|
||||
) -> EvalResult<'tcx>;
|
||||
|
||||
/// Called for read access to a foreign static item.
|
||||
fn find_foreign_static<'a>(
|
||||
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
) -> EvalResult<'tcx, &'tcx Allocation>;
|
||||
|
||||
/// Called for all binary operations except on float types.
|
||||
///
|
||||
/// Returns `None` if the operation should be handled by the integer
|
||||
@ -91,13 +97,6 @@ pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
|
||||
dest: PlaceTy<'tcx>,
|
||||
) -> EvalResult<'tcx>;
|
||||
|
||||
/// Called when trying to access a global declared with a `linkage` attribute
|
||||
fn global_item_with_linkage<'a>(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
mutability: Mutability,
|
||||
) -> EvalResult<'tcx>;
|
||||
|
||||
/// Execute a validation operation
|
||||
fn validation_op<'a>(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
|
@ -20,21 +20,16 @@ use std::collections::VecDeque;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ptr;
|
||||
|
||||
use rustc::ty::Instance;
|
||||
use rustc::ty::query::TyCtxtAt;
|
||||
use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
|
||||
use rustc::mir::interpret::{Pointer, AllocId, Allocation, ScalarMaybeUndef,
|
||||
use rustc::ty::{self, Instance, query::TyCtxtAt};
|
||||
use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
|
||||
use rustc::mir::interpret::{Pointer, AllocId, Allocation, ScalarMaybeUndef, GlobalId,
|
||||
EvalResult, Scalar, EvalErrorKind, AllocType, truncate};
|
||||
pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
|
||||
|
||||
use syntax::ast::Mutability;
|
||||
|
||||
use super::{EvalContext, Machine, IsStatic, static_alloc};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Allocations and pointers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
use super::{Machine, IsStatic};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||
pub enum MemoryKind<T> {
|
||||
@ -53,10 +48,6 @@ impl<T: IsStatic> IsStatic for MemoryKind<T> {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Top-level interpreter memory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
|
||||
/// Additional data required by the Machine
|
||||
@ -70,6 +61,13 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
|
||||
pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a Memory<'a, 'mir, 'tcx, M> {
|
||||
#[inline]
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.tcx.data_layout
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M> Eq for Memory<'a, 'mir, 'tcx, M>
|
||||
where M: Machine<'mir, 'tcx>,
|
||||
'tcx: 'a + 'mir,
|
||||
@ -122,6 +120,45 @@ impl<'a, 'mir, 'tcx, M> Hash for Memory<'a, 'mir, 'tcx, M>
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to obtain the global (tcx) allocation for a static
|
||||
fn const_eval_static<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>>(
|
||||
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
id: AllocId
|
||||
) -> EvalResult<'tcx, &'tcx Allocation> {
|
||||
let alloc = tcx.alloc_map.lock().get(id);
|
||||
let def_id = match alloc {
|
||||
Some(AllocType::Memory(mem)) => {
|
||||
return Ok(mem)
|
||||
}
|
||||
Some(AllocType::Function(..)) => {
|
||||
return err!(DerefFunctionPointer)
|
||||
}
|
||||
Some(AllocType::Static(did)) => {
|
||||
did
|
||||
}
|
||||
None =>
|
||||
return err!(DanglingPointerDeref),
|
||||
};
|
||||
// We got a "lazy" static that has not been computed yet, do some work
|
||||
trace!("static_alloc: Need to compute {:?}", def_id);
|
||||
if tcx.is_foreign_item(def_id) {
|
||||
return M::find_foreign_static(tcx, def_id);
|
||||
}
|
||||
let instance = Instance::mono(tcx.tcx, def_id);
|
||||
let gid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
|
||||
// no need to report anything, the const_eval call takes care of that for statics
|
||||
assert!(tcx.is_static(def_id).is_some());
|
||||
EvalErrorKind::ReferencedConstant(err).into()
|
||||
}).map(|val| {
|
||||
// FIXME We got our static (will be a ByRef), now we make a *copy*?!?
|
||||
tcx.const_to_allocation(val)
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||
pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>, data: M::MemoryData) -> Self {
|
||||
Memory {
|
||||
@ -322,7 +359,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||
Some(alloc) => Ok(&alloc.1),
|
||||
// No need to make any copies, just provide read access to the global static
|
||||
// memory in tcx.
|
||||
None => static_alloc(self.tcx, id),
|
||||
None => const_eval_static::<M>(self.tcx, id),
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,7 +625,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||
id: AllocId,
|
||||
kind: MemoryKind<M::MemoryKinds>,
|
||||
) -> EvalResult<'tcx> {
|
||||
let alloc = static_alloc(self.tcx, id)?;
|
||||
let alloc = const_eval_static::<M>(self.tcx, id)?;
|
||||
if alloc.mutability == Mutability::Immutable {
|
||||
return err!(ModifiedConstantMemory);
|
||||
}
|
||||
@ -980,49 +1017,3 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Unaligned accesses
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub trait HasMemory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
|
||||
fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M>;
|
||||
fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M>;
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M> HasMemory<'a, 'mir, 'tcx, M> for Memory<'a, 'mir, 'tcx, M>
|
||||
where M: Machine<'mir, 'tcx>
|
||||
{
|
||||
#[inline]
|
||||
fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M> HasMemory<'a, 'mir, 'tcx, M> for EvalContext<'a, 'mir, 'tcx, M>
|
||||
where M: Machine<'mir, 'tcx>
|
||||
{
|
||||
#[inline]
|
||||
fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
|
||||
&mut self.memory
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> {
|
||||
&self.memory
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M> layout::HasDataLayout for &'a Memory<'a, 'mir, 'tcx, M>
|
||||
where M: Machine<'mir, 'tcx>
|
||||
{
|
||||
#[inline]
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.tcx.data_layout
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub use self::eval_context::{
|
||||
|
||||
pub use self::place::{Place, PlaceExtra, PlaceTy, MemPlace, MPlaceTy};
|
||||
|
||||
pub use self::memory::{Memory, MemoryKind, HasMemory};
|
||||
pub use self::memory::{Memory, MemoryKind};
|
||||
|
||||
pub use self::const_eval::{
|
||||
eval_promoted,
|
||||
@ -42,7 +42,6 @@ pub use self::const_eval::{
|
||||
const_field,
|
||||
const_variant_index,
|
||||
op_to_const,
|
||||
static_alloc,
|
||||
};
|
||||
|
||||
pub use self::machine::{Machine, IsStatic};
|
||||
|
Loading…
Reference in New Issue
Block a user