various small nits
- share implementation with miri_starting_unwind - make test use a custom unwinding class - extend comments - use NeedsUnwind more consistently
This commit is contained in:
parent
42cb1ffa36
commit
5e41ff516f
@ -145,7 +145,7 @@ case $HOST_TARGET in
|
|||||||
TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
|
TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
|
||||||
# Partially supported targets (tier 2)
|
# Partially supported targets (tier 2)
|
||||||
BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization)
|
BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization)
|
||||||
UNIX="panic/panic concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
|
UNIX="panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
|
||||||
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
|
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
|
||||||
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
|
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname libc-time fs
|
||||||
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync
|
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX pthread-sync
|
||||||
|
@ -116,7 +116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
args: instance.args,
|
args: instance.args,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
EmulateItemResult::NeedsJumping => {
|
EmulateItemResult::NeedsReturn => {
|
||||||
trace!("{:?}", this.dump_place(&dest.clone().into()));
|
trace!("{:?}", this.dump_place(&dest.clone().into()));
|
||||||
this.return_to_block(ret)?;
|
this.return_to_block(ret)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -446,6 +446,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -746,7 +746,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fminmax_op(
|
fn fminmax_op(
|
||||||
|
@ -87,7 +87,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
AllocatorKind::Default => {
|
AllocatorKind::Default => {
|
||||||
default(this)?;
|
default(this)?;
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The rest either implements the logic, or falls back to `lookup_exported_symbol`.
|
// The rest either implements the logic, or falls back to `lookup_exported_symbol`.
|
||||||
match this.emulate_foreign_item_inner(link_name, abi, args, dest, unwind)? {
|
match this.emulate_foreign_item_inner(link_name, abi, args, dest)? {
|
||||||
EmulateItemResult::NeedsJumping => {
|
EmulateItemResult::NeedsReturn => {
|
||||||
trace!("{:?}", this.dump_place(&dest.clone().into()));
|
trace!("{:?}", this.dump_place(&dest.clone().into()));
|
||||||
this.return_to_block(ret)?;
|
this.return_to_block(ret)?;
|
||||||
}
|
}
|
||||||
@ -210,7 +210,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
abi: Abi,
|
abi: Abi,
|
||||||
args: &[OpTy<'tcx, Provenance>],
|
args: &[OpTy<'tcx, Provenance>],
|
||||||
dest: &MPlaceTy<'tcx, Provenance>,
|
dest: &MPlaceTy<'tcx, Provenance>,
|
||||||
unwind: mir::UnwindAction,
|
|
||||||
) -> InterpResult<'tcx, EmulateItemResult> {
|
) -> InterpResult<'tcx, EmulateItemResult> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
@ -222,7 +221,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// by the specified `.so` file; we should continue and check if it corresponds to
|
// by the specified `.so` file; we should continue and check if it corresponds to
|
||||||
// a provided shim.
|
// a provided shim.
|
||||||
if this.call_native_fn(link_name, dest, args)? {
|
if this.call_native_fn(link_name, dest, args)? {
|
||||||
return Ok(EmulateItemResult::NeedsJumping);
|
return Ok(EmulateItemResult::NeedsReturn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,9 +266,9 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
match link_name.as_str() {
|
match link_name.as_str() {
|
||||||
// Miri-specific extern functions
|
// Miri-specific extern functions
|
||||||
"miri_start_unwind" => {
|
"miri_start_unwind" => {
|
||||||
// `check_shim` happens inside `handle_miri_start_unwind`.
|
let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
||||||
this.handle_miri_start_unwind(abi, link_name, args, unwind)?;
|
this.handle_miri_start_unwind(payload)?;
|
||||||
return Ok(EmulateItemResult::AlreadyJumped);
|
return Ok(EmulateItemResult::NeedsUnwind);
|
||||||
}
|
}
|
||||||
"miri_run_provenance_gc" => {
|
"miri_run_provenance_gc" => {
|
||||||
let [] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
let [] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
||||||
@ -484,7 +483,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
"__rust_alloc" => return this.emulate_allocator(default),
|
"__rust_alloc" => return this.emulate_allocator(default),
|
||||||
"miri_alloc" => {
|
"miri_alloc" => {
|
||||||
default(this)?;
|
default(this)?;
|
||||||
return Ok(EmulateItemResult::NeedsJumping);
|
return Ok(EmulateItemResult::NeedsReturn);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -544,7 +543,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
"miri_dealloc" => {
|
"miri_dealloc" => {
|
||||||
default(this)?;
|
default(this)?;
|
||||||
return Ok(EmulateItemResult::NeedsJumping);
|
return Ok(EmulateItemResult::NeedsReturn);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -965,6 +964,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
};
|
};
|
||||||
// We only fall through to here if we did *not* hit the `_` arm above,
|
// We only fall through to here if we did *not* hit the `_` arm above,
|
||||||
// i.e., if we actually emulated the function with one of the shims.
|
// i.e., if we actually emulated the function with one of the shims.
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,10 @@ pub use unix::{DirTable, FdTable};
|
|||||||
/// What needs to be done after emulating an item (a shim or an intrinsic) is done.
|
/// What needs to be done after emulating an item (a shim or an intrinsic) is done.
|
||||||
pub enum EmulateItemResult {
|
pub enum EmulateItemResult {
|
||||||
/// The caller is expected to jump to the return block.
|
/// The caller is expected to jump to the return block.
|
||||||
NeedsJumping,
|
NeedsReturn,
|
||||||
/// The caller is expected to jump to the unwind block.
|
/// The caller is expected to jump to the unwind block.
|
||||||
NeedsUnwind,
|
NeedsUnwind,
|
||||||
/// Jumping has already been taken care of.
|
/// Jumping to the next block has already been taken care of.
|
||||||
AlreadyJumped,
|
AlreadyJumped,
|
||||||
/// The item is not supported.
|
/// The item is not supported.
|
||||||
NotSupported,
|
NotSupported,
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_middle::{mir, ty};
|
use rustc_middle::{mir, ty};
|
||||||
use rustc_span::Symbol;
|
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_target::spec::PanicStrategy;
|
use rustc_target::spec::PanicStrategy;
|
||||||
|
|
||||||
@ -46,25 +45,15 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir,
|
|||||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
/// Handles the special `miri_start_unwind` intrinsic, which is called
|
/// Handles the special `miri_start_unwind` intrinsic, which is called
|
||||||
/// by libpanic_unwind to delegate the actual unwinding process to Miri.
|
/// by libpanic_unwind to delegate the actual unwinding process to Miri.
|
||||||
fn handle_miri_start_unwind(
|
fn handle_miri_start_unwind(&mut self, payload: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||||
&mut self,
|
|
||||||
abi: Abi,
|
|
||||||
link_name: Symbol,
|
|
||||||
args: &[OpTy<'tcx, Provenance>],
|
|
||||||
unwind: mir::UnwindAction,
|
|
||||||
) -> InterpResult<'tcx> {
|
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
|
|
||||||
trace!("miri_start_unwind: {:?}", this.frame().instance);
|
trace!("miri_start_unwind: {:?}", this.frame().instance);
|
||||||
|
|
||||||
// Get the raw pointer stored in arg[0] (the panic payload).
|
|
||||||
let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
|
||||||
let payload = this.read_scalar(payload)?;
|
let payload = this.read_scalar(payload)?;
|
||||||
let thread = this.active_thread_mut();
|
let thread = this.active_thread_mut();
|
||||||
thread.panic_payloads.push(payload);
|
thread.panic_payloads.push(payload);
|
||||||
|
|
||||||
// Jump to the unwind block to begin unwinding.
|
|
||||||
this.unwind_to_block(unwind)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,14 +640,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
|
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
|
||||||
}
|
}
|
||||||
"_Unwind_RaiseException" => {
|
"_Unwind_RaiseException" => {
|
||||||
trace!("_Unwind_RaiseException: {:?}", this.frame().instance);
|
// This is not formally part of POSIX, but it is very wide-spread on POSIX systems.
|
||||||
|
// It was originally specified as part of the Itanium C++ ABI:
|
||||||
// Get the raw pointer stored in arg[0] (the panic payload).
|
// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-throw.
|
||||||
|
// On Linux it is
|
||||||
|
// documented as part of the LSB:
|
||||||
|
// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib--unwind-raiseexception.html
|
||||||
|
// Basically every other UNIX uses the exact same api though. Arm also references
|
||||||
|
// back to the Itanium C++ ABI for the definition of `_Unwind_RaiseException` for
|
||||||
|
// arm64:
|
||||||
|
// https://github.com/ARM-software/abi-aa/blob/main/cppabi64/cppabi64.rst#toc-entry-35
|
||||||
|
// For arm32 they did something custom, but similar enough that the same
|
||||||
|
// `_Unwind_RaiseException` impl in miri should work:
|
||||||
|
// https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst
|
||||||
|
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris" | "android" | "macos") {
|
||||||
|
throw_unsup_format!(
|
||||||
|
"`_Unwind_RaiseException` is not supported on {}",
|
||||||
|
this.tcx.sess.target.os
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// This function looks and behaves excatly like miri_start_unwind.
|
||||||
let [payload] = this.check_shim(abi, Abi::C { unwind: true }, link_name, args)?;
|
let [payload] = this.check_shim(abi, Abi::C { unwind: true }, link_name, args)?;
|
||||||
let payload = this.read_scalar(payload)?;
|
this.handle_miri_start_unwind(payload)?;
|
||||||
let thread = this.active_thread_mut();
|
|
||||||
thread.panic_payloads.push(payload);
|
|
||||||
|
|
||||||
return Ok(EmulateItemResult::NeedsUnwind);
|
return Ok(EmulateItemResult::NeedsUnwind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,6 +785,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,6 +203,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -762,6 +762,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
// with an external crate.
|
// with an external crate.
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +344,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -440,6 +440,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
|
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,6 +212,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,6 +388,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
|||||||
}
|
}
|
||||||
_ => return Ok(EmulateItemResult::NotSupported),
|
_ => return Ok(EmulateItemResult::NotSupported),
|
||||||
}
|
}
|
||||||
Ok(EmulateItemResult::NeedsJumping)
|
Ok(EmulateItemResult::NeedsReturn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//@only-target-linux
|
//@ignore-target-windows: Windows uses a different unwinding mechanism
|
||||||
#![feature(core_intrinsics, panic_unwind, rustc_attrs)]
|
#![feature(core_intrinsics, panic_unwind, rustc_attrs)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
|
|
||||||
@ -16,28 +16,28 @@ struct Exception {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn panic(data: Box<dyn Any + Send>) -> u32 {
|
pub fn panic(data: Box<dyn Any + Send>) -> u32 {
|
||||||
let exception = Box::new(Exception {
|
|
||||||
_uwe: uw::_Unwind_Exception {
|
|
||||||
exception_class: rust_exception_class(),
|
|
||||||
exception_cleanup,
|
|
||||||
private: [core::ptr::null(); uw::unwinder_private_data_size],
|
|
||||||
},
|
|
||||||
cause: data,
|
|
||||||
});
|
|
||||||
let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
|
|
||||||
return unsafe { uw::_Unwind_RaiseException(exception_param) as u32 };
|
|
||||||
|
|
||||||
extern "C" fn exception_cleanup(
|
extern "C" fn exception_cleanup(
|
||||||
_unwind_code: uw::_Unwind_Reason_Code,
|
_unwind_code: uw::_Unwind_Reason_Code,
|
||||||
_exception: *mut uw::_Unwind_Exception,
|
_exception: *mut uw::_Unwind_Exception,
|
||||||
) {
|
) {
|
||||||
std::process::abort();
|
std::process::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let exception = Box::new(Exception {
|
||||||
|
_uwe: uw::_Unwind_Exception {
|
||||||
|
exception_class: miri_exception_class(),
|
||||||
|
exception_cleanup: Some(exception_cleanup),
|
||||||
|
private: [core::ptr::null(); uw::unwinder_private_data_size],
|
||||||
|
},
|
||||||
|
cause: data,
|
||||||
|
});
|
||||||
|
let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
|
||||||
|
return unsafe { uw::_Unwind_RaiseException(exception_param) as u32 };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn rust_panic_cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
|
pub unsafe fn rust_panic_cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
|
||||||
let exception = ptr as *mut uw::_Unwind_Exception;
|
let exception = ptr as *mut uw::_Unwind_Exception;
|
||||||
if (*exception).exception_class != rust_exception_class() {
|
if (*exception).exception_class != miri_exception_class() {
|
||||||
std::process::abort();
|
std::process::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +47,10 @@ pub unsafe fn rust_panic_cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
|
|||||||
exception.cause
|
exception.cause
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rust_exception_class() -> uw::_Unwind_Exception_Class {
|
fn miri_exception_class() -> uw::_Unwind_Exception_Class {
|
||||||
// M O Z \0 R U S T -- vendor, language
|
// M O Z \0 M I R I -- vendor, language
|
||||||
0x4d4f5a_00_52555354
|
// (Miri's own exception class is just used for testing)
|
||||||
|
0x4d4f5a_00_4d495249
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
||||||
@ -63,7 +64,7 @@ pub fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
|
|||||||
|
|
||||||
let data_ptr = ptr::addr_of_mut!(data) as *mut u8;
|
let data_ptr = ptr::addr_of_mut!(data) as *mut u8;
|
||||||
unsafe {
|
unsafe {
|
||||||
return if std::intrinsics::r#try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
|
return if std::intrinsics::catch_unwind(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
|
||||||
Ok(data.r.take().unwrap())
|
Ok(data.r.take().unwrap())
|
||||||
} else {
|
} else {
|
||||||
Err(data.p.take().unwrap())
|
Err(data.p.take().unwrap())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user