Rollup merge of #71615 - RalfJung:share-machine-code, r=oli-obk

share some common code for compile-time miri instances

Fixes https://github.com/rust-lang/rust/issues/71129

r? @oli-obk
This commit is contained in:
Dylan DPC 2020-04-28 17:55:46 +02:00 committed by GitHub
commit 0bcdd5ffb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 113 deletions

View File

@ -1,7 +1,7 @@
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use std::borrow::{Borrow, Cow}; use std::borrow::Borrow;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::hash::Hash; use std::hash::Hash;
@ -13,8 +13,8 @@ use rustc_middle::mir::AssertMessage;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use crate::interpret::{ use crate::interpret::{
self, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, self, compile_time_machine, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx,
OpTy, PlaceTy, Pointer, Scalar, InterpResult, Memory, OpTy, PlaceTy, Pointer, Scalar,
}; };
use super::error::*; use super::error::*;
@ -171,29 +171,9 @@ impl interpret::MayLeak for ! {
} }
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> { impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
type MemoryKind = !; compile_time_machine!(<'mir, 'tcx>);
type PointerTag = ();
type ExtraFnVal = !;
type FrameExtra = ();
type MemoryExtra = MemoryExtra; type MemoryExtra = MemoryExtra;
type AllocExtra = ();
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, 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( fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>, 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<mir::BasicBlock>,
) -> InterpResult<'tcx> {
match fn_val {}
}
fn call_intrinsic( fn call_intrinsic(
ecx: &mut InterpCx<'mir, 'tcx, Self>, ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>, 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()) 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<MemoryKind<!>>,
) -> (Cow<'b, Allocation<Self::PointerTag>>, 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( fn box_alloc(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>, _dest: PlaceTy<'tcx>,
@ -345,14 +301,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Ok(()) 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)] #[inline(always)]
fn stack( fn stack(
ecx: &'a InterpCx<'mir, 'tcx, Self>, ecx: &'a InterpCx<'mir, 'tcx, Self>,

View File

@ -357,3 +357,67 @@ pub trait Machine<'mir, 'tcx>: Sized {
_ptr: Pointer<Self::PointerTag>, _ptr: Pointer<Self::PointerTag>,
) -> InterpResult<'tcx, u64>; ) -> 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<AllocId, (MemoryKind<!>, 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<mir::BasicBlock>,
) -> InterpResult<$tcx> {
match fn_val {}
}
#[inline(always)]
fn init_allocation_extra<'b>(
_memory_extra: &Self::MemoryExtra,
_id: AllocId,
alloc: Cow<'b, Allocation>,
_kind: Option<MemoryKind<!>>,
) -> (Cow<'b, Allocation<Self::PointerTag>>, 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)
}
}

View File

@ -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::eval_context::{Frame, InterpCx, LocalState, LocalValue, StackPopCleanup};
pub use self::intern::{intern_const_alloc_recursive, InternKind}; 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::memory::{AllocCheck, FnVal, Memory, MemoryKind};
pub use self::operand::{ImmTy, Immediate, OpTy, Operand}; pub use self::operand::{ImmTy, Immediate, OpTy, Operand};
pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};

View File

@ -13,6 +13,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(const_fn)] #![feature(const_fn)]
#![feature(const_panic)] #![feature(const_panic)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(drain_filter)] #![feature(drain_filter)]
#![feature(exhaustive_patterns)] #![feature(exhaustive_patterns)]
#![feature(iter_order_by)] #![feature(iter_order_by)]

View File

@ -1,11 +1,9 @@
//! Propagates constants for early reporting of statically known //! Propagates constants for early reporting of statically known
//! assertion failures //! assertion failures
use std::borrow::Cow;
use std::cell::Cell; use std::cell::Cell;
use rustc_ast::ast::Mutability; use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::HirId; use rustc_hir::HirId;
use rustc_index::bit_set::BitSet; 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::const_eval::error_to_const_error;
use crate::interpret::{ use crate::interpret::{
self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InternKind, self, compile_time_machine, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy,
InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Immediate, InternKind, InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy,
Pointer, ScalarMaybeUndef, StackPopCleanup, Operand as InterpOperand, PlaceTy, Pointer, ScalarMaybeUndef, StackPopCleanup,
}; };
use crate::transform::{MirPass, MirSource}; 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> { impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
type MemoryKind = !; compile_time_machine!(<'mir, 'tcx>);
type PointerTag = ();
type ExtraFnVal = !;
type FrameExtra = ();
type MemoryExtra = (); type MemoryExtra = ();
type AllocExtra = ();
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, 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( fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
@ -194,16 +174,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
Ok(None) Ok(None)
} }
fn call_extra_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
fn_val: !,
_args: &[OpTy<'tcx>],
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
_unwind: Option<BasicBlock>,
) -> InterpResult<'tcx> {
match fn_val {}
}
fn call_intrinsic( fn call_intrinsic(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_instance: ty::Instance<'tcx>, _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") 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<MemoryKind<!>>,
) -> (Cow<'b, Allocation<Self::PointerTag>>, 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( fn box_alloc(
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>, _dest: PlaceTy<'tcx>,
@ -290,14 +246,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
Ok(()) 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)] #[inline(always)]
fn stack( fn stack(
ecx: &'a InterpCx<'mir, 'tcx, Self>, ecx: &'a InterpCx<'mir, 'tcx, Self>,