diff options
| author | Ralf Jung <post@ralfj.de> | 2020-03-14 11:23:39 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2020-03-14 11:24:11 +0100 |
| commit | 9c5d8e9b520c12044c818dd3d48f02bcea075ec3 (patch) | |
| tree | 784caf6fbc79840b3c726f0fe3d82bdd913ce445 | |
| parent | 62087439a46f09b6a6716fc25b4a032f3d76eb71 (diff) | |
| download | rust-9c5d8e9b520c12044c818dd3d48f02bcea075ec3.tar.gz rust-9c5d8e9b520c12044c818dd3d48f02bcea075ec3.zip | |
adjust Miri interaction with panic runtime
| -rw-r--r-- | src/libcore/intrinsics.rs | 8 | ||||
| -rw-r--r-- | src/libpanic_unwind/lib.rs | 35 | ||||
| -rw-r--r-- | src/libpanic_unwind/miri.rs | 20 |
3 files changed, 47 insertions, 16 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index c2f13047e54..d722406b82b 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1892,10 +1892,12 @@ extern "rust-intrinsic" { pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize; /// Internal hook used by Miri to implement unwinding. - /// Compiles to a NOP during non-Miri codegen. + /// ICEs when encountered during non-Miri codegen. /// - /// Perma-unstable: do not use - pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> (); + /// The `payload` ptr here will be exactly the one `do_catch` gets passed by `try`. + /// + /// Perma-unstable: do not use. + pub fn miri_start_panic(payload: *mut u8) -> !; } // Some functions are defined here because they accidentally got made diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index d6c33666938..c213b19d062 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -31,6 +31,9 @@ #![panic_runtime] #![feature(panic_runtime)] +// `real_imp` is unused with Miri, so silence warnings. +#![cfg_attr(miri, allow(dead_code))] + use alloc::boxed::Box; use core::any::Any; use core::panic::BoxMeUp; @@ -38,25 +41,38 @@ use core::panic::BoxMeUp; cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] - mod imp; + mod real_imp; } else if #[cfg(target_arch = "wasm32")] { #[path = "dummy.rs"] - mod imp; + mod real_imp; } else if #[cfg(target_os = "hermit")] { #[path = "hermit.rs"] - mod imp; + mod real_imp; } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { #[path = "dummy.rs"] - mod imp; + mod real_imp; } else if #[cfg(target_env = "msvc")] { #[path = "seh.rs"] - mod imp; + mod real_imp; } else { // Rust runtime's startup objects depend on these symbols, so make them public. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] - pub use imp::eh_frame_registry::*; + pub use real_imp::eh_frame_registry::*; #[path = "gcc.rs"] + mod real_imp; + } +} + +cfg_if::cfg_if! { + if #[cfg(miri)] { + // Use the Miri runtime. + // We still need to also load the normal runtime above, as rustc expects certain lang + // items from there to be defined. + #[path = "miri.rs"] mod imp; + } else { + // Use the real runtime. + use real_imp as imp; } } @@ -81,12 +97,5 @@ pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { let payload = payload as *mut &mut dyn BoxMeUp; let payload = (*payload).take_box(); - // Miri panic support: cfg'd out of normal builds just to be sure. - // When going through normal codegen, `miri_start_panic` is a NOP, so the - // Miri-enabled sysroot still supports normal unwinding. But when executed in - // Miri, this line initiates unwinding. - #[cfg(miri)] - core::intrinsics::miri_start_panic(payload); - imp::panic(Box::from_raw(payload)) } diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs new file mode 100644 index 00000000000..5f44b98566f --- /dev/null +++ b/src/libpanic_unwind/miri.rs @@ -0,0 +1,20 @@ +//! Unwinding panics for Miri. +use core::any::Any; +use alloc::boxed::Box; + +// The type of the payload that the Miri engine propagates through unwinding for us. +// Must be pointer-sized. +type Payload = Box<Box<dyn Any + Send>>; + +pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 { + // The payload we pass to `miri_start_panic` will be exactly the argument we get + // in `cleanup` below. So we just box it up once, to get something pointer-sized. + let payload_box: Payload = Box::new(payload); + core::intrinsics::miri_start_panic(Box::into_raw(payload_box) as *mut u8) +} + +pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> { + // Recover the underlying `Box`. + let payload_box: Payload = Box::from_raw(payload_box as *mut _); + *payload_box +} |
