std support for wasm32 panic=unwind
This commit is contained in:
parent
f8131a48a4
commit
3908a935ef
@ -5,6 +5,7 @@
|
|||||||
};
|
};
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
|
use rustc_codegen_ssa::base::wants_wasm_eh;
|
||||||
use rustc_codegen_ssa::traits::PrintBackendInfo;
|
use rustc_codegen_ssa::traits::PrintBackendInfo;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
@ -98,8 +99,12 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind {
|
if sess.panic_strategy() == PanicStrategy::Unwind {
|
||||||
add("-enable-emscripten-cxx-exceptions", false);
|
if sess.target.os == "emscripten" {
|
||||||
|
add("-enable-emscripten-cxx-exceptions", false);
|
||||||
|
} else if wants_wasm_eh(sess) {
|
||||||
|
add("-wasm-enable-eh", false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
|
// HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
|
||||||
@ -520,6 +525,10 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||||||
.map(String::from),
|
.map(String::from),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind {
|
||||||
|
features.push("+exception-handling".into());
|
||||||
|
}
|
||||||
|
|
||||||
// -Ctarget-features
|
// -Ctarget-features
|
||||||
let supported_features = sess.target.supported_target_features();
|
let supported_features = sess.target.supported_target_features();
|
||||||
let mut featsmap = FxHashMap::default();
|
let mut featsmap = FxHashMap::default();
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
|
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
|
#![cfg_attr(
|
||||||
|
all(target_family = "wasm", not(target_os = "emscripten")),
|
||||||
|
feature(link_llvm_intrinsics)
|
||||||
|
)]
|
||||||
#![feature(panic_unwind)]
|
#![feature(panic_unwind)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(std_internals)]
|
#![feature(std_internals)]
|
||||||
@ -56,9 +60,16 @@
|
|||||||
))] {
|
))] {
|
||||||
#[path = "gcc.rs"]
|
#[path = "gcc.rs"]
|
||||||
mod real_imp;
|
mod real_imp;
|
||||||
|
} else if #[cfg(all(target_family = "wasm", panic = "unwind"))] {
|
||||||
|
// for now, PanicStrategy::Unwind is not the default for wasm targets,
|
||||||
|
// so we need the panic = "unwind" in the cfg above. to use llvm.wasm.throw,
|
||||||
|
// we need to pass -wasm-enable-eh to LLVM, but that only happens if rustc
|
||||||
|
// is compiling with -C panic=unwind. So, this lets us -Zbuild-std with
|
||||||
|
// panic=unwind, while keeping the default panic=abort working.
|
||||||
|
#[path = "wasm.rs"]
|
||||||
|
mod real_imp;
|
||||||
} else {
|
} else {
|
||||||
// Targets that don't support unwinding.
|
// Targets that don't support unwinding.
|
||||||
// - family=wasm
|
|
||||||
// - os=none ("bare metal" targets)
|
// - os=none ("bare metal" targets)
|
||||||
// - os=uefi
|
// - os=uefi
|
||||||
// - os=espidf
|
// - os=espidf
|
||||||
|
32
library/panic_unwind/src/wasm.rs
Normal file
32
library/panic_unwind/src/wasm.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//! Unwinding panics for wasm32.
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use core::any::Any;
|
||||||
|
|
||||||
|
// The type of the exception payload that the wasm engine propagates
|
||||||
|
// through unwinding for us. LLVM requires that it be a thin pointer.
|
||||||
|
type Payload = Box<Box<dyn Any + Send>>;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
/// LLVM lowers this intrinsic to the `throw` instruction.
|
||||||
|
#[link_name = "llvm.wasm.throw"]
|
||||||
|
fn wasm_throw(tag: i32, ptr: *mut u8) -> !;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
|
||||||
|
// The payload we pass to `wasm_throw` 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);
|
||||||
|
// The wasm `throw` instruction takes a "tag", which differentiates certain
|
||||||
|
// types of exceptions from others. LLVM currently just identifies these
|
||||||
|
// via integers, with 0 corresponding to C++ exceptions and 1 to C setjmp()/longjmp().
|
||||||
|
// Ideally, we'd be able to choose something unique for Rust, such that we
|
||||||
|
// don't try to treat a C++ exception payload as a `Box<Box<dyn Any>>`, but
|
||||||
|
// otherwise, pretending to be C++ works for now.
|
||||||
|
wasm_throw(0, 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
|
||||||
|
}
|
@ -16,11 +16,12 @@
|
|||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_os = "emscripten")] {
|
if #[cfg(target_os = "emscripten")] {
|
||||||
mod emcc;
|
mod emcc;
|
||||||
} else if #[cfg(target_env = "msvc")] {
|
} else if #[cfg(any(target_env = "msvc", target_family = "wasm"))] {
|
||||||
// This is required by the compiler to exist (e.g., it's a lang item),
|
// This is required by the compiler to exist (e.g., it's a lang item),
|
||||||
// but it's never actually called by the compiler because
|
// but it's never actually called by the compiler because
|
||||||
// _CxxFrameHandler3 is the personality function that is always used.
|
// __CxxFrameHandler3 (msvc) / __gxx_wasm_personality_v0 (wasm) is the
|
||||||
// Hence this is just an aborting stub.
|
// personality function that is always used. Hence this is just an
|
||||||
|
// aborting stub.
|
||||||
#[lang = "eh_personality"]
|
#[lang = "eh_personality"]
|
||||||
fn rust_eh_personality() {
|
fn rust_eh_personality() {
|
||||||
core::intrinsics::abort()
|
core::intrinsics::abort()
|
||||||
@ -36,7 +37,6 @@ fn rust_eh_personality() {
|
|||||||
mod gcc;
|
mod gcc;
|
||||||
} else {
|
} else {
|
||||||
// Targets that don't support unwinding.
|
// Targets that don't support unwinding.
|
||||||
// - family=wasm
|
|
||||||
// - os=none ("bare metal" targets)
|
// - os=none ("bare metal" targets)
|
||||||
// - os=uefi
|
// - os=uefi
|
||||||
// - os=espidf
|
// - os=espidf
|
||||||
|
Loading…
Reference in New Issue
Block a user