From 525a798ca6513a204de8bd434bf260d79cbdfc9f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 22 Sep 2016 19:55:42 +0000 Subject: [PATCH] Rewrite emscripten unwinding to use libcxx --- src/libpanic_unwind/Cargo.lock | 9 ++++ src/libpanic_unwind/emcc.rs | 76 ++++++++++++++++++++++++++++++++++ src/libpanic_unwind/gcc.rs | 10 ----- src/libpanic_unwind/lib.rs | 8 +++- src/libunwind/libunwind.rs | 2 +- 5 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 src/libpanic_unwind/emcc.rs diff --git a/src/libpanic_unwind/Cargo.lock b/src/libpanic_unwind/Cargo.lock index 20d826d4a47..0cf75c94150 100644 --- a/src/libpanic_unwind/Cargo.lock +++ b/src/libpanic_unwind/Cargo.lock @@ -5,6 +5,7 @@ dependencies = [ "alloc 0.0.0", "core 0.0.0", "libc 0.0.0", + "unwind 0.0.0", ] [[package]] @@ -25,3 +26,11 @@ dependencies = [ "core 0.0.0", ] +[[package]] +name = "unwind" +version = "0.0.0" +dependencies = [ + "core 0.0.0", + "libc 0.0.0", +] + diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs new file mode 100644 index 00000000000..598f99ba27b --- /dev/null +++ b/src/libpanic_unwind/emcc.rs @@ -0,0 +1,76 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(private_no_mangle_fns)] + +use core::any::Any; +use core::ptr; +use alloc::boxed::Box; +use libc::{self, c_int}; +use unwind as uw; +use core::mem; + +pub fn payload() -> *mut u8 { + ptr::null_mut() +} + +pub unsafe fn cleanup(ptr: *mut u8) -> Box { + assert!(!ptr.is_null()); + let ex = ptr::read(ptr as *mut _); + __cxa_free_exception(ptr as *mut _); + ex +} + +pub unsafe fn panic(data: Box) -> u32 { + let sz = mem::size_of_val(&data); + let exception = __cxa_allocate_exception(sz); + if exception == ptr::null_mut() { + return uw::_URC_FATAL_PHASE1_ERROR as u32; + } + let exception = exception as *mut Box; + ptr::write(exception, data); + __cxa_throw(exception as *mut _, ptr::null_mut(), ptr::null_mut()); + + unreachable!() +} + +#[lang = "eh_personality"] +#[no_mangle] +unsafe extern "C" fn rust_eh_personality(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + exception_object: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code { + __gxx_personality_v0(version, actions, + exception_class, + exception_object, + context) +} + +#[lang = "eh_unwind_resume"] +#[unwind] +unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! { + uw::_Unwind_Resume(panic_ctx as *mut uw::_Unwind_Exception); +} + +extern { + fn __cxa_allocate_exception(thrown_size: libc::size_t) -> *mut libc::c_void; + fn __cxa_free_exception(thrown_exception: *mut libc::c_void); + fn __cxa_throw(thrown_exception: *mut libc::c_void, + tinfo: *mut libc::c_void, + dest: *mut libc::c_void); + fn __gxx_personality_v0(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + exception_object: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; +} diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 5bfa77cba7a..33b24fbaa26 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -133,16 +133,6 @@ const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4 #[cfg(target_arch = "s390x")] const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7 -// FIXME: This is completely and utterly wrong. -// I copy'n'pasted the x86 thing just to see if asmjs-unknown-emscripten compiles at all -// (the happy path) -#[cfg(target_arch = "asmjs")] -const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX - -// FIXME: Ditto the above -#[cfg(target_arch = "wasm32")] -const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX - // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 11dd9befe0a..ff483fa823e 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -68,10 +68,16 @@ mod imp; mod imp; // i686-pc-windows-gnu and all others -#[cfg(any(unix, all(windows, target_arch = "x86", target_env = "gnu")))] +#[cfg(any(all(unix, not(target_os = "emscripten")), + all(windows, target_arch = "x86", target_env = "gnu")))] #[path = "gcc.rs"] mod imp; +// emscripten +#[cfg(target_os = "emscripten")] +#[path = "emcc.rs"] +mod imp; + mod dwarf; mod windows; diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index 5d69a95da82..c2edf754e49 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -65,7 +65,7 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "s390x")] pub const unwinder_private_data_size: usize = 2; -#[cfg(any(target_arch = "asmjs", target_arch = "wasm32"))] +#[cfg(target_os = "emscripten")] pub const unwinder_private_data_size: usize = 20; #[repr(C)]