diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index dbdaf0aab34..9840fb2cfd7 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -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) - }) -} diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 714b2f9e025..b3e7370b66b 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -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>, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 41d48738567..e570468a467 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -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 { @@ -53,10 +48,6 @@ impl IsStatic for MemoryKind { } } -//////////////////////////////////////////////////////////////////////////////// -// 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::(self.tcx, id), } } @@ -588,7 +625,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { id: AllocId, kind: MemoryKind, ) -> EvalResult<'tcx> { - let alloc = static_alloc(self.tcx, id)?; + let alloc = const_eval_static::(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 - } -} diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 129c098099a..8559686fa41 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -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};