mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Add UnwindAction::Unreachable
This also makes eval machine's `StackPopUnwind` redundant so that is replaced.
This commit is contained in:
parent
daeb844e0c
commit
5e6ed132fa
@ -1612,23 +1612,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
TerminatorKind::Drop { target, unwind, .. }
|
TerminatorKind::Drop { target, unwind, .. }
|
||||||
| TerminatorKind::Assert { target, unwind, .. } => {
|
| TerminatorKind::Assert { target, unwind, .. } => {
|
||||||
self.assert_iscleanup(body, block_data, target, is_cleanup);
|
self.assert_iscleanup(body, block_data, target, is_cleanup);
|
||||||
if let UnwindAction::Cleanup(unwind) = unwind {
|
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
|
||||||
if is_cleanup {
|
|
||||||
span_mirbug!(self, block_data, "unwind on cleanup block")
|
|
||||||
}
|
|
||||||
self.assert_iscleanup(body, block_data, unwind, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TerminatorKind::Call { ref target, unwind, .. } => {
|
TerminatorKind::Call { ref target, unwind, .. } => {
|
||||||
if let &Some(target) = target {
|
if let &Some(target) = target {
|
||||||
self.assert_iscleanup(body, block_data, target, is_cleanup);
|
self.assert_iscleanup(body, block_data, target, is_cleanup);
|
||||||
}
|
}
|
||||||
if let UnwindAction::Cleanup(cleanup) = unwind {
|
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
|
||||||
if is_cleanup {
|
|
||||||
span_mirbug!(self, block_data, "cleanup on cleanup block")
|
|
||||||
}
|
|
||||||
self.assert_iscleanup(body, block_data, cleanup, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TerminatorKind::FalseEdge { real_target, imaginary_target } => {
|
TerminatorKind::FalseEdge { real_target, imaginary_target } => {
|
||||||
self.assert_iscleanup(body, block_data, real_target, is_cleanup);
|
self.assert_iscleanup(body, block_data, real_target, is_cleanup);
|
||||||
@ -1636,23 +1626,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
TerminatorKind::FalseUnwind { real_target, unwind } => {
|
TerminatorKind::FalseUnwind { real_target, unwind } => {
|
||||||
self.assert_iscleanup(body, block_data, real_target, is_cleanup);
|
self.assert_iscleanup(body, block_data, real_target, is_cleanup);
|
||||||
if let UnwindAction::Cleanup(unwind) = unwind {
|
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
|
||||||
if is_cleanup {
|
|
||||||
span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind");
|
|
||||||
}
|
|
||||||
self.assert_iscleanup(body, block_data, unwind, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TerminatorKind::InlineAsm { destination, unwind, .. } => {
|
TerminatorKind::InlineAsm { destination, unwind, .. } => {
|
||||||
if let Some(target) = destination {
|
if let Some(target) = destination {
|
||||||
self.assert_iscleanup(body, block_data, target, is_cleanup);
|
self.assert_iscleanup(body, block_data, target, is_cleanup);
|
||||||
}
|
}
|
||||||
if let UnwindAction::Cleanup(cleanup) = unwind {
|
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
|
||||||
if is_cleanup {
|
|
||||||
span_mirbug!(self, block_data, "cleanup on cleanup block")
|
|
||||||
}
|
|
||||||
self.assert_iscleanup(body, block_data, cleanup, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1669,6 +1649,25 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_iscleanup_unwind(
|
||||||
|
&mut self,
|
||||||
|
body: &Body<'tcx>,
|
||||||
|
ctxt: &dyn fmt::Debug,
|
||||||
|
unwind: UnwindAction,
|
||||||
|
is_cleanup: bool,
|
||||||
|
) {
|
||||||
|
match unwind {
|
||||||
|
UnwindAction::Cleanup(unwind) => {
|
||||||
|
if is_cleanup {
|
||||||
|
span_mirbug!(self, ctxt, "unwind on cleanup block")
|
||||||
|
}
|
||||||
|
self.assert_iscleanup(body, ctxt, unwind, true);
|
||||||
|
}
|
||||||
|
UnwindAction::Continue => (),
|
||||||
|
UnwindAction::Unreachable => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
|
fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
|
||||||
match body.local_kind(local) {
|
match body.local_kind(local) {
|
||||||
LocalKind::ReturnPointer | LocalKind::Arg => {
|
LocalKind::ReturnPointer | LocalKind::Arg => {
|
||||||
|
@ -156,7 +156,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||||||
fn_ptr: Bx::Value,
|
fn_ptr: Bx::Value,
|
||||||
llargs: &[Bx::Value],
|
llargs: &[Bx::Value],
|
||||||
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
|
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
|
||||||
unwind: mir::UnwindAction,
|
mut unwind: mir::UnwindAction,
|
||||||
copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
|
copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
|
||||||
mergeable_succ: bool,
|
mergeable_succ: bool,
|
||||||
) -> MergingSucc {
|
) -> MergingSucc {
|
||||||
@ -164,27 +164,28 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||||||
// do an invoke, otherwise do a call.
|
// do an invoke, otherwise do a call.
|
||||||
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
|
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
|
||||||
|
|
||||||
let cleanup = match unwind {
|
if !fn_abi.can_unwind {
|
||||||
mir::UnwindAction::Cleanup(cleanup) => Some(cleanup),
|
unwind = mir::UnwindAction::Unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
let unwind_block = match unwind {
|
||||||
|
mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
|
||||||
|
_ if fx.mir[self.bb].is_cleanup
|
||||||
|
&& fn_abi.can_unwind
|
||||||
|
&& !base::wants_msvc_seh(fx.cx.tcx().sess) =>
|
||||||
|
{
|
||||||
|
// Exception must not propagate out of the execution of a cleanup (doing so
|
||||||
|
// can cause undefined behaviour). We insert a double unwind guard for
|
||||||
|
// functions that can potentially unwind to protect against this.
|
||||||
|
//
|
||||||
|
// This is not necessary for SEH which does not use successive unwinding
|
||||||
|
// like Itanium EH. EH frames in SEH are different from normal function
|
||||||
|
// frames and SEH will abort automatically if an exception tries to
|
||||||
|
// propagate out from cleanup.
|
||||||
|
Some(fx.double_unwind_guard())
|
||||||
|
}
|
||||||
mir::UnwindAction::Continue => None,
|
mir::UnwindAction::Continue => None,
|
||||||
};
|
mir::UnwindAction::Unreachable => None,
|
||||||
let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
|
|
||||||
Some(self.llbb_with_cleanup(fx, cleanup))
|
|
||||||
} else if fx.mir[self.bb].is_cleanup
|
|
||||||
&& fn_abi.can_unwind
|
|
||||||
&& !base::wants_msvc_seh(fx.cx.tcx().sess)
|
|
||||||
{
|
|
||||||
// Exception must not propagate out of the execution of a cleanup (doing so
|
|
||||||
// can cause undefined behaviour). We insert a double unwind guard for
|
|
||||||
// functions that can potentially unwind to protect against this.
|
|
||||||
//
|
|
||||||
// This is not necessary for SEH which does not use successive unwinding
|
|
||||||
// like Itanium EH. EH frames in SEH are different from normal function
|
|
||||||
// frames and SEH will abort automatically if an exception tries to
|
|
||||||
// propagate out from cleanup.
|
|
||||||
Some(fx.double_unwind_guard())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(unwind_block) = unwind_block {
|
if let Some(unwind_block) = unwind_block {
|
||||||
@ -640,7 +641,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
|
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
|
||||||
|
|
||||||
// Codegen the actual panic invoke/call.
|
// Codegen the actual panic invoke/call.
|
||||||
let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, mir::UnwindAction::Continue, &[], false);
|
let merging_succ = helper.do_call(
|
||||||
|
self,
|
||||||
|
bx,
|
||||||
|
fn_abi,
|
||||||
|
llfn,
|
||||||
|
&[],
|
||||||
|
None,
|
||||||
|
mir::UnwindAction::Unreachable,
|
||||||
|
&[],
|
||||||
|
false,
|
||||||
|
);
|
||||||
assert_eq!(merging_succ, MergingSucc::False);
|
assert_eq!(merging_succ, MergingSucc::False);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
|
|||||||
|
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx,
|
self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx,
|
||||||
InterpResult, OpTy, PlaceTy, Pointer, Scalar, StackPopUnwind,
|
InterpResult, OpTy, PlaceTy, Pointer, Scalar,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
@ -271,7 +271,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
|||||||
/* with_caller_location = */ false,
|
/* with_caller_location = */ false,
|
||||||
dest,
|
dest,
|
||||||
ret,
|
ret,
|
||||||
StackPopUnwind::NotAllowed,
|
mir::UnwindAction::Unreachable,
|
||||||
)?;
|
)?;
|
||||||
Ok(ControlFlow::Break(()))
|
Ok(ControlFlow::Break(()))
|
||||||
} else {
|
} else {
|
||||||
@ -401,7 +401,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||||||
args: &[OpTy<'tcx>],
|
args: &[OpTy<'tcx>],
|
||||||
dest: &PlaceTy<'tcx>,
|
dest: &PlaceTy<'tcx>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
_unwind: StackPopUnwind, // unwinding is not supported in consts
|
_unwind: mir::UnwindAction, // unwinding is not supported in consts
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
debug!("find_mir_or_eval_fn: {:?}", instance);
|
debug!("find_mir_or_eval_fn: {:?}", instance);
|
||||||
|
|
||||||
@ -450,7 +450,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||||||
args: &[OpTy<'tcx>],
|
args: &[OpTy<'tcx>],
|
||||||
dest: &PlaceTy<'tcx, Self::Provenance>,
|
dest: &PlaceTy<'tcx, Self::Provenance>,
|
||||||
target: Option<mir::BasicBlock>,
|
target: Option<mir::BasicBlock>,
|
||||||
_unwind: StackPopUnwind,
|
_unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
// Shared intrinsics.
|
// Shared intrinsics.
|
||||||
if ecx.emulate_intrinsic(instance, args, dest, target)? {
|
if ecx.emulate_intrinsic(instance, args, dest, target)? {
|
||||||
|
@ -139,17 +139,6 @@ pub struct FrameInfo<'tcx> {
|
|||||||
pub lint_root: Option<hir::HirId>,
|
pub lint_root: Option<hir::HirId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unwind information.
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
|
||||||
pub enum StackPopUnwind {
|
|
||||||
/// The cleanup block.
|
|
||||||
Cleanup(mir::BasicBlock),
|
|
||||||
/// No cleanup needs to be done.
|
|
||||||
Skip,
|
|
||||||
/// Unwinding is not allowed (UB).
|
|
||||||
NotAllowed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
|
||||||
pub enum StackPopCleanup {
|
pub enum StackPopCleanup {
|
||||||
/// Jump to the next block in the caller, or cause UB if None (that's a function
|
/// Jump to the next block in the caller, or cause UB if None (that's a function
|
||||||
@ -157,7 +146,7 @@ pub enum StackPopCleanup {
|
|||||||
/// we can validate it at that layout.
|
/// we can validate it at that layout.
|
||||||
/// `ret` stores the block we jump to on a normal return, while `unwind`
|
/// `ret` stores the block we jump to on a normal return, while `unwind`
|
||||||
/// stores the block used for cleanup during unwinding.
|
/// stores the block used for cleanup during unwinding.
|
||||||
Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind },
|
Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction },
|
||||||
/// The root frame of the stack: nowhere else to jump to.
|
/// The root frame of the stack: nowhere else to jump to.
|
||||||
/// `cleanup` says whether locals are deallocated. Static computation
|
/// `cleanup` says whether locals are deallocated. Static computation
|
||||||
/// wants them leaked to intern what they need (and just throw away
|
/// wants them leaked to intern what they need (and just throw away
|
||||||
@ -735,16 +724,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
/// *Unwind* to the given `target` basic block.
|
/// *Unwind* to the given `target` basic block.
|
||||||
/// Do *not* use for returning! Use `return_to_block` instead.
|
/// Do *not* use for returning! Use `return_to_block` instead.
|
||||||
///
|
///
|
||||||
/// If `target` is `StackPopUnwind::Skip`, that indicates the function does not need cleanup
|
/// If `target` is `UnwindAction::Continue`, that indicates the function does not need cleanup
|
||||||
/// during unwinding, and we will just keep propagating that upwards.
|
/// during unwinding, and we will just keep propagating that upwards.
|
||||||
///
|
///
|
||||||
/// If `target` is `StackPopUnwind::NotAllowed`, that indicates the function does not allow
|
/// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow
|
||||||
/// unwinding, and doing so is UB.
|
/// unwinding, and doing so is UB.
|
||||||
pub fn unwind_to_block(&mut self, target: StackPopUnwind) -> InterpResult<'tcx> {
|
pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> {
|
||||||
self.frame_mut().loc = match target {
|
self.frame_mut().loc = match target {
|
||||||
StackPopUnwind::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
|
mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
|
||||||
StackPopUnwind::Skip => Right(self.frame_mut().body.span),
|
mir::UnwindAction::Continue => Right(self.frame_mut().body.span),
|
||||||
StackPopUnwind::NotAllowed => {
|
mir::UnwindAction::Unreachable => {
|
||||||
throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
|
throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
|
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
|
||||||
InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
|
InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data returned by Machine::stack_pop,
|
/// Data returned by Machine::stack_pop,
|
||||||
@ -185,7 +185,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||||||
args: &[OpTy<'tcx, Self::Provenance>],
|
args: &[OpTy<'tcx, Self::Provenance>],
|
||||||
destination: &PlaceTy<'tcx, Self::Provenance>,
|
destination: &PlaceTy<'tcx, Self::Provenance>,
|
||||||
target: Option<mir::BasicBlock>,
|
target: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
|
||||||
|
|
||||||
/// Execute `fn_val`. It is the hook's responsibility to advance the instruction
|
/// Execute `fn_val`. It is the hook's responsibility to advance the instruction
|
||||||
@ -197,7 +197,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||||||
args: &[OpTy<'tcx, Self::Provenance>],
|
args: &[OpTy<'tcx, Self::Provenance>],
|
||||||
destination: &PlaceTy<'tcx, Self::Provenance>,
|
destination: &PlaceTy<'tcx, Self::Provenance>,
|
||||||
target: Option<mir::BasicBlock>,
|
target: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx>;
|
) -> InterpResult<'tcx>;
|
||||||
|
|
||||||
/// Directly process an intrinsic without pushing a stack frame. It is the hook's
|
/// Directly process an intrinsic without pushing a stack frame. It is the hook's
|
||||||
@ -208,7 +208,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||||||
args: &[OpTy<'tcx, Self::Provenance>],
|
args: &[OpTy<'tcx, Self::Provenance>],
|
||||||
destination: &PlaceTy<'tcx, Self::Provenance>,
|
destination: &PlaceTy<'tcx, Self::Provenance>,
|
||||||
target: Option<mir::BasicBlock>,
|
target: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx>;
|
) -> InterpResult<'tcx>;
|
||||||
|
|
||||||
/// Called to evaluate `Assert` MIR terminators that trigger a panic.
|
/// Called to evaluate `Assert` MIR terminators that trigger a panic.
|
||||||
@ -487,7 +487,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||||||
_args: &[OpTy<$tcx>],
|
_args: &[OpTy<$tcx>],
|
||||||
_destination: &PlaceTy<$tcx, Self::Provenance>,
|
_destination: &PlaceTy<$tcx, Self::Provenance>,
|
||||||
_target: Option<mir::BasicBlock>,
|
_target: Option<mir::BasicBlock>,
|
||||||
_unwind: StackPopUnwind,
|
_unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<$tcx> {
|
) -> InterpResult<$tcx> {
|
||||||
match fn_val {}
|
match fn_val {}
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,7 @@ mod visitor;
|
|||||||
|
|
||||||
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
|
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
|
||||||
|
|
||||||
pub use self::eval_context::{
|
pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup};
|
||||||
Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup, StackPopUnwind,
|
|
||||||
};
|
|
||||||
pub use self::intern::{intern_const_alloc_recursive, InternKind};
|
pub use self::intern::{intern_const_alloc_recursive, InternKind};
|
||||||
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
|
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
|
||||||
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
|
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
|
||||||
|
@ -13,7 +13,7 @@ use rustc_target::spec::abi::Abi;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand,
|
FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand,
|
||||||
PlaceTy, Scalar, StackPopCleanup, StackPopUnwind,
|
PlaceTy, Scalar, StackPopCleanup,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
@ -60,7 +60,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
ref args,
|
ref args,
|
||||||
destination,
|
destination,
|
||||||
target,
|
target,
|
||||||
ref unwind,
|
unwind,
|
||||||
from_hir_call: _,
|
from_hir_call: _,
|
||||||
fn_span: _,
|
fn_span: _,
|
||||||
} => {
|
} => {
|
||||||
@ -106,13 +106,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
with_caller_location,
|
with_caller_location,
|
||||||
&destination,
|
&destination,
|
||||||
target,
|
target,
|
||||||
match (unwind, fn_abi.can_unwind) {
|
if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable },
|
||||||
(mir::UnwindAction::Cleanup(cleanup), true) => {
|
|
||||||
StackPopUnwind::Cleanup(*cleanup)
|
|
||||||
}
|
|
||||||
(mir::UnwindAction::Continue, true) => StackPopUnwind::Skip,
|
|
||||||
(_, false) => StackPopUnwind::NotAllowed,
|
|
||||||
},
|
|
||||||
)?;
|
)?;
|
||||||
// Sanity-check that `eval_fn_call` either pushed a new frame or
|
// Sanity-check that `eval_fn_call` either pushed a new frame or
|
||||||
// did a jump to another block.
|
// did a jump to another block.
|
||||||
@ -353,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
with_caller_location: bool,
|
with_caller_location: bool,
|
||||||
destination: &PlaceTy<'tcx, M::Provenance>,
|
destination: &PlaceTy<'tcx, M::Provenance>,
|
||||||
target: Option<mir::BasicBlock>,
|
target: Option<mir::BasicBlock>,
|
||||||
mut unwind: StackPopUnwind,
|
mut unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
trace!("eval_fn_call: {:#?}", fn_val);
|
trace!("eval_fn_call: {:#?}", fn_val);
|
||||||
|
|
||||||
@ -412,9 +406,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matches!(unwind, StackPopUnwind::NotAllowed) && !callee_fn_abi.can_unwind {
|
if !callee_fn_abi.can_unwind {
|
||||||
// The callee cannot unwind.
|
// The callee cannot unwind, so force the `Unreachable` unwind handling.
|
||||||
unwind = StackPopUnwind::NotAllowed;
|
unwind = mir::UnwindAction::Unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push_stack_frame(
|
self.push_stack_frame(
|
||||||
@ -719,10 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
false,
|
false,
|
||||||
&ret.into(),
|
&ret.into(),
|
||||||
Some(target),
|
Some(target),
|
||||||
match unwind {
|
unwind,
|
||||||
mir::UnwindAction::Cleanup(cleanup) => StackPopUnwind::Cleanup(cleanup),
|
|
||||||
mir::UnwindAction::Continue => StackPopUnwind::Skip,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ pub struct MirPatch<'tcx> {
|
|||||||
new_statements: Vec<(Location, StatementKind<'tcx>)>,
|
new_statements: Vec<(Location, StatementKind<'tcx>)>,
|
||||||
new_locals: Vec<LocalDecl<'tcx>>,
|
new_locals: Vec<LocalDecl<'tcx>>,
|
||||||
resume_block: Option<BasicBlock>,
|
resume_block: Option<BasicBlock>,
|
||||||
|
// Only for unreachable in cleanup path.
|
||||||
|
unreachable_block: Option<BasicBlock>,
|
||||||
body_span: Span,
|
body_span: Span,
|
||||||
next_local: usize,
|
next_local: usize,
|
||||||
}
|
}
|
||||||
@ -25,11 +27,12 @@ impl<'tcx> MirPatch<'tcx> {
|
|||||||
new_locals: vec![],
|
new_locals: vec![],
|
||||||
next_local: body.local_decls.len(),
|
next_local: body.local_decls.len(),
|
||||||
resume_block: None,
|
resume_block: None,
|
||||||
|
unreachable_block: None,
|
||||||
body_span: body.span,
|
body_span: body.span,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if we already have a resume block
|
|
||||||
for (bb, block) in body.basic_blocks.iter_enumerated() {
|
for (bb, block) in body.basic_blocks.iter_enumerated() {
|
||||||
|
// Check if we already have a resume block
|
||||||
if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
|
if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
|
||||||
result.resume_block = Some(bb);
|
result.resume_block = Some(bb);
|
||||||
break;
|
break;
|
||||||
|
@ -753,12 +753,17 @@ pub enum TerminatorKind<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Action to be taken when a stack unwind happens.
|
/// Action to be taken when a stack unwind happens.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub enum UnwindAction {
|
pub enum UnwindAction {
|
||||||
// No action is to be taken. Continue unwinding.
|
/// No action is to be taken. Continue unwinding.
|
||||||
|
///
|
||||||
|
/// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not
|
||||||
|
/// equivalent, as presence of `Cleanup(_)` will make a frame non-POF.
|
||||||
Continue,
|
Continue,
|
||||||
// Cleanups to be done.
|
/// Triggers undefined behavior if unwind happens.
|
||||||
|
Unreachable,
|
||||||
|
/// Cleanups to be done.
|
||||||
Cleanup(BasicBlock),
|
Cleanup(BasicBlock),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,11 +270,16 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
|
|||||||
let labels = self.fmt_successor_labels();
|
let labels = self.fmt_successor_labels();
|
||||||
assert_eq!(successor_count, labels.len());
|
assert_eq!(successor_count, labels.len());
|
||||||
|
|
||||||
match successor_count {
|
let unwind = match self.unwind() {
|
||||||
0 => Ok(()),
|
// Not needed or included in successors
|
||||||
|
None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
|
||||||
1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
|
Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
|
||||||
|
};
|
||||||
|
|
||||||
|
match (successor_count, unwind) {
|
||||||
|
(0, None) => Ok(()),
|
||||||
|
(0, Some(unwind)) => write!(fmt, " -> {}", unwind),
|
||||||
|
(1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
|
||||||
_ => {
|
_ => {
|
||||||
write!(fmt, " -> [")?;
|
write!(fmt, " -> [")?;
|
||||||
for (i, target) in self.successors().enumerate() {
|
for (i, target) in self.successors().enumerate() {
|
||||||
@ -283,6 +288,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
|
|||||||
}
|
}
|
||||||
write!(fmt, "{}: {:?}", labels[i], target)?;
|
write!(fmt, "{}: {:?}", labels[i], target)?;
|
||||||
}
|
}
|
||||||
|
if let Some(unwind) = unwind {
|
||||||
|
write!(fmt, ", {unwind}")?;
|
||||||
|
}
|
||||||
write!(fmt, "]")
|
write!(fmt, "]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,30 +399,32 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||||||
Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
|
Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
|
||||||
vec!["return".into(), "unwind".into()]
|
vec!["return".into(), "unwind".into()]
|
||||||
}
|
}
|
||||||
Call { target: Some(_), unwind: UnwindAction::Continue, .. } => vec!["return".into()],
|
Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
|
||||||
Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
|
Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
|
||||||
Call { target: None, unwind: UnwindAction::Continue, .. } => vec![],
|
Call { target: None, unwind: _, .. } => vec![],
|
||||||
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
|
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
|
||||||
Yield { drop: None, .. } => vec!["resume".into()],
|
Yield { drop: None, .. } => vec!["resume".into()],
|
||||||
Drop { unwind: UnwindAction::Continue, .. } => vec!["return".into()],
|
|
||||||
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
|
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
|
||||||
Assert { unwind: UnwindAction::Continue, .. } => vec!["".into()],
|
Drop { unwind: _, .. } => vec!["return".into()],
|
||||||
Assert { .. } => vec!["success".into(), "unwind".into()],
|
Assert { unwind: UnwindAction::Cleanup(_), .. } => {
|
||||||
|
vec!["success".into(), "unwind".into()]
|
||||||
|
}
|
||||||
|
Assert { unwind: _, .. } => vec!["success".into()],
|
||||||
FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
|
FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
|
||||||
FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
|
FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
|
||||||
vec!["real".into(), "cleanup".into()]
|
vec!["real".into(), "unwind".into()]
|
||||||
}
|
}
|
||||||
FalseUnwind { unwind: UnwindAction::Continue, .. } => vec!["real".into()],
|
FalseUnwind { unwind: _, .. } => vec!["real".into()],
|
||||||
InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
|
InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
|
||||||
vec!["return".into(), "unwind".into()]
|
vec!["return".into(), "unwind".into()]
|
||||||
}
|
}
|
||||||
InlineAsm { destination: Some(_), unwind: UnwindAction::Continue, .. } => {
|
InlineAsm { destination: Some(_), unwind: _, .. } => {
|
||||||
vec!["return".into()]
|
vec!["return".into()]
|
||||||
}
|
}
|
||||||
InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
|
InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
|
||||||
vec!["unwind".into()]
|
vec!["unwind".into()]
|
||||||
}
|
}
|
||||||
InlineAsm { destination: None, unwind: UnwindAction::Continue, .. } => vec![],
|
InlineAsm { destination: None, unwind: _, .. } => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -946,7 +946,7 @@ where
|
|||||||
args,
|
args,
|
||||||
destination: unit_temp,
|
destination: unit_temp,
|
||||||
target: Some(target),
|
target: Some(target),
|
||||||
unwind: UnwindAction::Continue,
|
unwind: UnwindAction::Unreachable,
|
||||||
from_hir_call: false,
|
from_hir_call: false,
|
||||||
fn_span: self.source_info.span,
|
fn_span: self.source_info.span,
|
||||||
}; // FIXME(#43234)
|
}; // FIXME(#43234)
|
||||||
|
@ -131,7 +131,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||||||
|
|
||||||
for id in cleanups_to_remove {
|
for id in cleanups_to_remove {
|
||||||
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
|
let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
|
||||||
*cleanup = UnwindAction::Continue;
|
*cleanup = UnwindAction::Unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We may have invalidated some `cleanup` blocks so clean those up now.
|
// We may have invalidated some `cleanup` blocks so clean those up now.
|
||||||
|
@ -24,7 +24,7 @@ use crate::MirPass;
|
|||||||
use rustc_const_eval::interpret::{
|
use rustc_const_eval::interpret::{
|
||||||
self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
|
self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
|
||||||
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer,
|
ImmTy, Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer,
|
||||||
Scalar, StackPopCleanup, StackPopUnwind,
|
Scalar, StackPopCleanup,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The maximum number of bytes that we'll allocate space for a local or the return value.
|
/// The maximum number of bytes that we'll allocate space for a local or the return value.
|
||||||
@ -209,7 +209,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||||||
_args: &[OpTy<'tcx>],
|
_args: &[OpTy<'tcx>],
|
||||||
_destination: &PlaceTy<'tcx>,
|
_destination: &PlaceTy<'tcx>,
|
||||||
_target: Option<BasicBlock>,
|
_target: Option<BasicBlock>,
|
||||||
_unwind: StackPopUnwind,
|
_unwind: UnwindAction,
|
||||||
) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||||||
_args: &[OpTy<'tcx>],
|
_args: &[OpTy<'tcx>],
|
||||||
_destination: &PlaceTy<'tcx>,
|
_destination: &PlaceTy<'tcx>,
|
||||||
_target: Option<BasicBlock>,
|
_target: Option<BasicBlock>,
|
||||||
_unwind: StackPopUnwind,
|
_unwind: UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
|
throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||||||
let loc = Location { block: bb, statement_index: data.statements.len() };
|
let loc = Location { block: bb, statement_index: data.statements.len() };
|
||||||
let terminator = data.terminator();
|
let terminator = data.terminator();
|
||||||
|
|
||||||
let resume_block = self.patch.resume_block();
|
|
||||||
match terminator.kind {
|
match terminator.kind {
|
||||||
TerminatorKind::Drop { mut place, target, unwind } => {
|
TerminatorKind::Drop { mut place, target, unwind } => {
|
||||||
if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
|
if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
|
||||||
@ -408,22 +407,29 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||||||
|
|
||||||
self.init_data.seek_before(loc);
|
self.init_data.seek_before(loc);
|
||||||
match self.move_data().rev_lookup.find(place.as_ref()) {
|
match self.move_data().rev_lookup.find(place.as_ref()) {
|
||||||
LookupResult::Exact(path) => elaborate_drop(
|
LookupResult::Exact(path) => {
|
||||||
&mut Elaborator { ctxt: self },
|
let unwind = if data.is_cleanup {
|
||||||
terminator.source_info,
|
|
||||||
place,
|
|
||||||
path,
|
|
||||||
target,
|
|
||||||
if data.is_cleanup {
|
|
||||||
Unwind::InCleanup
|
Unwind::InCleanup
|
||||||
} else {
|
} else {
|
||||||
match unwind {
|
match unwind {
|
||||||
UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
|
UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
|
||||||
UnwindAction::Continue => Unwind::To(resume_block),
|
UnwindAction::Continue => Unwind::To(self.patch.resume_block()),
|
||||||
|
UnwindAction::Unreachable => {
|
||||||
|
Unwind::To(self.patch.unreachable_block())
|
||||||
|
}
|
||||||
|
UnwindAction::Terminate => Unwind::To(self.patch.terminate_block()),
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
bb,
|
elaborate_drop(
|
||||||
),
|
&mut Elaborator { ctxt: self },
|
||||||
|
terminator.source_info,
|
||||||
|
place,
|
||||||
|
path,
|
||||||
|
target,
|
||||||
|
unwind,
|
||||||
|
bb,
|
||||||
|
)
|
||||||
|
}
|
||||||
LookupResult::Parent(..) => {
|
LookupResult::Parent(..) => {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
terminator.source_info.span.desugaring_kind(),
|
terminator.source_info.span.desugaring_kind(),
|
||||||
|
@ -1063,6 +1063,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||||||
Unwind::To(match *unwind {
|
Unwind::To(match *unwind {
|
||||||
UnwindAction::Cleanup(tgt) => tgt,
|
UnwindAction::Cleanup(tgt) => tgt,
|
||||||
UnwindAction::Continue => elaborator.patch.resume_block(),
|
UnwindAction::Continue => elaborator.patch.resume_block(),
|
||||||
|
UnwindAction::Unreachable => elaborator.patch.unreachable_block(),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
elaborate_drop(
|
elaborate_drop(
|
||||||
|
@ -1020,11 +1020,12 @@ impl Integrator<'_, '_> {
|
|||||||
UnwindAction::Cleanup(_) => {
|
UnwindAction::Cleanup(_) => {
|
||||||
bug!("cleanup on cleanup block");
|
bug!("cleanup on cleanup block");
|
||||||
}
|
}
|
||||||
UnwindAction::Continue => return unwind,
|
UnwindAction::Continue | UnwindAction::Unreachable => return unwind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match unwind {
|
match unwind {
|
||||||
|
UnwindAction::Unreachable => unwind,
|
||||||
UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
|
UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
|
||||||
// Add an unwind edge to the original call's cleanup block
|
// Add an unwind edge to the original call's cleanup block
|
||||||
UnwindAction::Continue => self.cleanup_block,
|
UnwindAction::Continue => self.cleanup_block,
|
||||||
@ -1140,6 +1141,9 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
|||||||
terminator.kind = TerminatorKind::Goto { target: tgt };
|
terminator.kind = TerminatorKind::Goto { target: tgt };
|
||||||
}
|
}
|
||||||
UnwindAction::Continue => (),
|
UnwindAction::Continue => (),
|
||||||
|
UnwindAction::Unreachable => {
|
||||||
|
terminator.kind = TerminatorKind::Unreachable;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
TerminatorKind::Abort => {}
|
TerminatorKind::Abort => {}
|
||||||
TerminatorKind::Unreachable => {}
|
TerminatorKind::Unreachable => {}
|
||||||
|
@ -54,7 +54,7 @@ fn lower_slice_len_call<'tcx>(
|
|||||||
args,
|
args,
|
||||||
destination,
|
destination,
|
||||||
target: Some(bb),
|
target: Some(bb),
|
||||||
unwind: UnwindAction::Continue,
|
unwind: UnwindAction::Unreachable,
|
||||||
from_hir_call: true,
|
from_hir_call: true,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
@ -951,7 +951,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
if this.machine.panic_on_unsupported {
|
if this.machine.panic_on_unsupported {
|
||||||
// message is slightly different here to make automated analysis easier
|
// message is slightly different here to make automated analysis easier
|
||||||
let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
|
let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
|
||||||
this.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?;
|
this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
throw_unsup_format!("{}", error_msg.as_ref());
|
throw_unsup_format!("{}", error_msg.as_ref());
|
||||||
|
@ -834,7 +834,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
|
ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
|
||||||
}
|
}
|
||||||
@ -847,7 +847,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
_unwind: StackPopUnwind,
|
_unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
ecx.call_dlsym(fn_val, abi, args, dest, ret)
|
ecx.call_dlsym(fn_val, abi, args, dest, ret)
|
||||||
}
|
}
|
||||||
@ -859,7 +859,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
ecx.call_intrinsic(instance, args, dest, ret, unwind)
|
ecx.call_intrinsic(instance, args, dest, ret, unwind)
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
let link_name = this.item_link_name(def_id);
|
let link_name = this.item_link_name(def_id);
|
||||||
|
@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
_unwind: StackPopUnwind,
|
_unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
|
trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
|
||||||
@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
align_op: &OpTy<'tcx, Provenance>,
|
align_op: &OpTy<'tcx, Provenance>,
|
||||||
dest: &PlaceTy<'tcx, Provenance>,
|
dest: &PlaceTy<'tcx, Provenance>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx, bool> {
|
) -> InterpResult<'tcx, bool> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
let ret = ret.unwrap();
|
let ret = ret.unwrap();
|
||||||
|
@ -53,7 +53,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
abi: Abi,
|
abi: Abi,
|
||||||
link_name: Symbol,
|
link_name: Symbol,
|
||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
unwind: StackPopUnwind,
|
unwind: mir::UnwindAction,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
&[data.into()],
|
&[data.into()],
|
||||||
None,
|
None,
|
||||||
// Directly return to caller.
|
// Directly return to caller.
|
||||||
StackPopCleanup::Goto { ret: Some(ret), unwind: StackPopUnwind::Skip },
|
StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue },
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// We ourselves will return `0`, eventually (will be overwritten if we catch a panic).
|
// We ourselves will return `0`, eventually (will be overwritten if we catch a panic).
|
||||||
@ -157,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
&[catch_unwind.data.into(), payload.into()],
|
&[catch_unwind.data.into(), payload.into()],
|
||||||
None,
|
None,
|
||||||
// Directly return to caller of `try`.
|
// Directly return to caller of `try`.
|
||||||
StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: StackPopUnwind::Skip },
|
StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue },
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// We pushed a new stack frame, the engine should not do any jumping now!
|
// We pushed a new stack frame, the engine should not do any jumping now!
|
||||||
@ -168,7 +168,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start a panic in the interpreter with the given message as payload.
|
/// Start a panic in the interpreter with the given message as payload.
|
||||||
fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
|
fn start_panic(&mut self, msg: &str, unwind: mir::UnwindAction) -> InterpResult<'tcx> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
// First arg: message.
|
// First arg: message.
|
||||||
@ -213,10 +213,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
None,
|
None,
|
||||||
StackPopCleanup::Goto {
|
StackPopCleanup::Goto {
|
||||||
ret: None,
|
ret: None,
|
||||||
unwind: match unwind {
|
unwind,
|
||||||
Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
|
|
||||||
None => StackPopUnwind::Skip,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -252,10 +249,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Forward everything else to `panic` lang item.
|
// Forward everything else to `panic` lang item.
|
||||||
this.start_panic(
|
this.start_panic(
|
||||||
msg.description(),
|
msg.description(),
|
||||||
match unwind {
|
unwind,
|
||||||
Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
|
|
||||||
None => StackPopUnwind::Skip,
|
|
||||||
},
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user