diff options
| author | Ralf Jung <post@ralfj.de> | 2019-11-29 09:59:52 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2019-12-02 08:55:42 +0100 |
| commit | b1aa3cac5b7f5ac3e527f32431fa82e1c7d00c52 (patch) | |
| tree | efca9b1a29e82e88500252349b3ff42022ba4b93 | |
| parent | f5c81e0a986e4285d3d0fd781a1bd475753eb12c (diff) | |
| download | rust-b1aa3cac5b7f5ac3e527f32431fa82e1c7d00c52.tar.gz rust-b1aa3cac5b7f5ac3e527f32431fa82e1c7d00c52.zip | |
Miri: add machine hook for MIR-level assertion panics
| -rw-r--r-- | src/librustc_mir/const_eval.rs | 35 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/machine.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/terminator.rs | 54 | ||||
| -rw-r--r-- | src/librustc_mir/transform/const_prop.rs | 8 |
4 files changed, 67 insertions, 39 deletions
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 0967b257885..18b965f4c34 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -23,7 +23,7 @@ use syntax::{source_map::{Span, DUMMY_SP}, symbol::Symbol}; use crate::interpret::{self, PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer, RawConst, ConstValue, Machine, - InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup, + InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup, AssertMessage, Allocation, AllocId, MemoryKind, Memory, snapshot, RefTracking, intern_const_alloc_recursive, }; @@ -395,6 +395,39 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ) } + fn assert_panic( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + msg: &AssertMessage<'tcx>, + _unwind: Option<mir::BasicBlock>, + ) -> InterpResult<'tcx> { + use rustc::mir::interpret::PanicInfo::*; + Err(match msg { + BoundsCheck { ref len, ref index } => { + let len = ecx + .read_immediate(ecx.eval_operand(len, None)?) + .expect("can't eval len") + .to_scalar()? + .to_machine_usize(&*ecx)?; + let index = ecx + .read_immediate(ecx.eval_operand(index, None)?) + .expect("can't eval index") + .to_scalar()? + .to_machine_usize(&*ecx)?; + err_panic!(BoundsCheck { len, index }) + } + Overflow(op) => err_panic!(Overflow(*op)), + OverflowNeg => err_panic!(OverflowNeg), + DivisionByZero => err_panic!(DivisionByZero), + RemainderByZero => err_panic!(RemainderByZero), + ResumedAfterReturn(generator_kind) + => err_panic!(ResumedAfterReturn(*generator_kind)), + ResumedAfterPanic(generator_kind) + => err_panic!(ResumedAfterPanic(*generator_kind)), + Panic { .. } => bug!("`Panic` variant cannot occur in MIR"), + } + .into()) + } + fn ptr_to_int( _mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index b7cde626415..42d5140e348 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -11,7 +11,7 @@ use rustc::ty::{self, Ty, TyCtxt}; use syntax_pos::Span; use super::{ - Allocation, AllocId, InterpResult, Scalar, AllocationExtra, + Allocation, AllocId, InterpResult, Scalar, AllocationExtra, AssertMessage, InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory, Frame, Operand, }; @@ -175,6 +175,13 @@ pub trait Machine<'mir, 'tcx>: Sized { unwind: Option<mir::BasicBlock>, ) -> InterpResult<'tcx>; + /// Called to evaluate `Assert` MIR terminators that trigger a panic. + fn assert_panic( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + msg: &AssertMessage<'tcx>, + unwind: Option<mir::BasicBlock>, + ) -> InterpResult<'tcx>; + /// Called for read access to a foreign static item. /// /// This will only be called once per static and machine; the result is cached in diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 50cd3188510..a4748252403 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -7,8 +7,8 @@ use syntax::source_map::Span; use rustc_target::spec::abi::Abi; use super::{ - GlobalId, InterpResult, PointerArithmetic, - InterpCx, Machine, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal, + GlobalId, InterpResult, InterpCx, Machine, + OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal, }; impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { @@ -115,40 +115,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { expected, ref msg, target, - .. + cleanup, } => { let cond_val = self.read_immediate(self.eval_operand(cond, None)?)? .to_scalar()?.to_bool()?; if expected == cond_val { self.go_to_block(target); } else { - // Compute error message - use rustc::mir::interpret::PanicInfo::*; - return Err(match msg { - BoundsCheck { ref len, ref index } => { - let len = self - .read_immediate(self.eval_operand(len, None)?) - .expect("can't eval len") - .to_scalar()? - .to_bits(self.memory.pointer_size())? as u64; - let index = self - .read_immediate(self.eval_operand(index, None)?) - .expect("can't eval index") - .to_scalar()? - .to_bits(self.memory.pointer_size())? as u64; - err_panic!(BoundsCheck { len, index }) - } - Overflow(op) => err_panic!(Overflow(*op)), - OverflowNeg => err_panic!(OverflowNeg), - DivisionByZero => err_panic!(DivisionByZero), - RemainderByZero => err_panic!(RemainderByZero), - ResumedAfterReturn(generator_kind) - => err_panic!(ResumedAfterReturn(*generator_kind)), - ResumedAfterPanic(generator_kind) - => err_panic!(ResumedAfterPanic(*generator_kind)), - Panic { .. } => bug!("`Panic` variant cannot occur in MIR"), - } - .into()); + M::assert_panic(self, msg, cleanup)?; } } @@ -164,15 +138,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(()) }, + // It is UB to ever encounter this. + Unreachable => throw_ub!(Unreachable), + + // These should never occur for MIR we actually run. + DropAndReplace { .. } | + FalseEdges { .. } | + FalseUnwind { .. } => + bug!("{:#?} should have been eliminated by MIR pass", terminator.kind), + + // These are not (yet) supported. It is unclear if they even can occur in + // MIR that we actually run. Yield { .. } | GeneratorDrop | - DropAndReplace { .. } | - Abort => unimplemented!("{:#?}", terminator.kind), - FalseEdges { .. } => bug!("should have been eliminated by\ - `simplify_branches` mir pass"), - FalseUnwind { .. } => bug!("should have been eliminated by\ - `simplify_branches` mir pass"), - Unreachable => throw_ub!(Unreachable), + Abort => + throw_unsup_format!("Unsupported terminator kind: {:#?}", terminator.kind), } Ok(()) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 67958af3460..1fb254fb69f 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -156,6 +156,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp")); } + fn assert_panic( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _msg: &rustc::mir::interpret::AssertMessage<'tcx>, + _unwind: Option<rustc::mir::BasicBlock>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("panics are not supported in ConstProp"); + } + fn ptr_to_int( _mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer, |
