diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index cb146059fb1..84031ec0f17 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -1,7 +1,7 @@ use rustc_middle::mir; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; -use std::borrow::{Borrow, Cow}; +use std::borrow::Borrow; use std::collections::hash_map::Entry; use std::hash::Hash; @@ -13,8 +13,8 @@ use rustc_middle::mir::AssertMessage; use rustc_span::symbol::Symbol; use crate::interpret::{ - self, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, - OpTy, PlaceTy, Pointer, Scalar, + self, compile_time_machine, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx, + InterpResult, Memory, OpTy, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -171,29 +171,9 @@ impl interpret::MayLeak for ! { } impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> { - type MemoryKind = !; - type PointerTag = (); - type ExtraFnVal = !; + compile_time_machine!(<'mir, 'tcx>); - type FrameExtra = (); type MemoryExtra = MemoryExtra; - type AllocExtra = (); - - type MemoryMap = FxHashMap, Allocation)>; - - const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory - - #[inline(always)] - fn enforce_alignment(_memory_extra: &Self::MemoryExtra) -> bool { - // We do not check for alignment to avoid having to carry an `Align` - // in `ConstValue::ByRef`. - false - } - - #[inline(always)] - fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { - false // for now, we don't enforce validity - } fn find_mir_or_eval_fn( ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -241,16 +221,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, })) } - fn call_extra_fn( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - fn_val: !, - _args: &[OpTy<'tcx>], - _ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>, - _unwind: Option, - ) -> InterpResult<'tcx> { - match fn_val {} - } - fn call_intrinsic( ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, @@ -310,20 +280,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } - #[inline(always)] - fn init_allocation_extra<'b>( - _memory_extra: &MemoryExtra, - _id: AllocId, - alloc: Cow<'b, Allocation>, - _kind: Option>, - ) -> (Cow<'b, Allocation>, Self::PointerTag) { - // We do not use a tag so we can just cheaply forward the allocation - (alloc, ()) - } - - #[inline(always)] - fn tag_global_base_pointer(_memory_extra: &MemoryExtra, _id: AllocId) -> Self::PointerTag {} - fn box_alloc( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, @@ -345,14 +301,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(()) } - #[inline(always)] - fn init_frame_extra( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - frame: Frame<'mir, 'tcx>, - ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> { - Ok(frame) - } - #[inline(always)] fn stack( ecx: &'a InterpCx<'mir, 'tcx, Self>, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index dfdd95c95a3..03a617993e9 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -357,3 +357,67 @@ pub trait Machine<'mir, 'tcx>: Sized { _ptr: Pointer, ) -> InterpResult<'tcx, u64>; } + +// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines +// (CTFE and ConstProp) use the same instance. Here, we share that code. +pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { + type PointerTag = (); + type ExtraFnVal = !; + + type MemoryKind = !; + type MemoryMap = rustc_data_structures::fx::FxHashMap, Allocation)>; + const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory + + type AllocExtra = (); + type FrameExtra = (); + + #[inline(always)] + fn enforce_alignment(_memory_extra: &Self::MemoryExtra) -> bool { + // We do not check for alignment to avoid having to carry an `Align` + // in `ConstValue::ByRef`. + false + } + + #[inline(always)] + fn enforce_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { + false // for now, we don't enforce validity + } + + #[inline(always)] + fn call_extra_fn( + _ecx: &mut InterpCx<$mir, $tcx, Self>, + fn_val: !, + _args: &[OpTy<$tcx>], + _ret: Option<(PlaceTy<$tcx>, mir::BasicBlock)>, + _unwind: Option, + ) -> InterpResult<$tcx> { + match fn_val {} + } + + #[inline(always)] + fn init_allocation_extra<'b>( + _memory_extra: &Self::MemoryExtra, + _id: AllocId, + alloc: Cow<'b, Allocation>, + _kind: Option>, + ) -> (Cow<'b, Allocation>, Self::PointerTag) { + // We do not use a tag so we can just cheaply forward the allocation + (alloc, ()) + } + + #[inline(always)] + fn tag_global_base_pointer( + _memory_extra: &Self::MemoryExtra, + _id: AllocId, + ) -> Self::PointerTag { + () + } + + #[inline(always)] + fn init_frame_extra( + _ecx: &mut InterpCx<$mir, $tcx, Self>, + frame: Frame<$mir, $tcx>, + ) -> InterpResult<$tcx, Frame<$mir, $tcx>> { + Ok(frame) + } +} diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index fb59a177b97..d46010d98a5 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -19,7 +19,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in pub use self::eval_context::{Frame, InterpCx, LocalState, LocalValue, StackPopCleanup}; pub use self::intern::{intern_const_alloc_recursive, InternKind}; -pub use self::machine::{AllocMap, Machine, MayLeak, StackPopJump}; +pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind}; pub use self::operand::{ImmTy, Immediate, OpTy, Operand}; pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 07822f865d2..ae7bbe9f36a 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -13,6 +13,7 @@ Rust MIR: a lowered representation of Rust. #![feature(const_fn)] #![feature(const_panic)] #![feature(crate_visibility_modifier)] +#![feature(decl_macro)] #![feature(drain_filter)] #![feature(exhaustive_patterns)] #![feature(iter_order_by)] diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index abe9249ec37..a38cf3bba85 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -1,11 +1,9 @@ //! Propagates constants for early reporting of statically known //! assertion failures -use std::borrow::Cow; use std::cell::Cell; use rustc_ast::ast::Mutability; -use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::HirId; use rustc_index::bit_set::BitSet; @@ -29,9 +27,9 @@ use rustc_trait_selection::traits; use crate::const_eval::error_to_const_error; use crate::interpret::{ - self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InternKind, - InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, - Pointer, ScalarMaybeUndef, StackPopCleanup, + self, compile_time_machine, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, + Immediate, InternKind, InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, + Operand as InterpOperand, PlaceTy, Pointer, ScalarMaybeUndef, StackPopCleanup, }; use crate::transform::{MirPass, MirSource}; @@ -162,27 +160,9 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { } impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> { - type MemoryKind = !; - type PointerTag = (); - type ExtraFnVal = !; + compile_time_machine!(<'mir, 'tcx>); - type FrameExtra = (); type MemoryExtra = (); - type AllocExtra = (); - - type MemoryMap = FxHashMap, Allocation)>; - - const GLOBAL_KIND: Option = None; // no copying of globals from `tcx` to machine memory - - #[inline(always)] - fn enforce_alignment(_memory_extra: &Self::MemoryExtra) -> bool { - false - } - - #[inline(always)] - fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { - false - } fn find_mir_or_eval_fn( _ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -194,16 +174,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> Ok(None) } - fn call_extra_fn( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - fn_val: !, - _args: &[OpTy<'tcx>], - _ret: Option<(PlaceTy<'tcx>, BasicBlock)>, - _unwind: Option, - ) -> InterpResult<'tcx> { - match fn_val {} - } - fn call_intrinsic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, @@ -236,20 +206,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } - #[inline(always)] - fn init_allocation_extra<'b>( - _memory_extra: &(), - _id: AllocId, - alloc: Cow<'b, Allocation>, - _kind: Option>, - ) -> (Cow<'b, Allocation>, Self::PointerTag) { - // We do not use a tag so we can just cheaply forward the allocation - (alloc, ()) - } - - #[inline(always)] - fn tag_global_base_pointer(_memory_extra: &(), _id: AllocId) -> Self::PointerTag {} - fn box_alloc( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, @@ -290,14 +246,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> Ok(()) } - #[inline(always)] - fn init_frame_extra( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - frame: Frame<'mir, 'tcx>, - ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> { - Ok(frame) - } - #[inline(always)] fn stack( ecx: &'a InterpCx<'mir, 'tcx, Self>,