| #ifdef __EMSCRIPTEN__ |
|
|
| #include "cxxabi.h" |
|
|
| #include "cxa_exception.h" |
| #include "private_typeinfo.h" |
| #include <assert.h> |
| #include <stdio.h> |
| |
| |
| #include <string.h> |
|
|
| namespace __cxxabiv1 { |
|
|
| |
| static |
| inline |
| __cxa_exception* |
| cxa_exception_from_thrown_object(void* thrown_object) |
| { |
| return static_cast<__cxa_exception*>(thrown_object) - 1; |
| } |
|
|
| |
| |
| static |
| inline |
| void* |
| thrown_object_from_cxa_exception(__cxa_exception* exception_header) |
| { |
| return static_cast<void*>(exception_header + 1); |
| } |
|
|
| |
| |
| |
| static inline __cxa_exception* cxa_exception_from_unwind_exception( |
| _Unwind_Exception* unwind_exception) { |
| return cxa_exception_from_thrown_object(unwind_exception + 1); |
| } |
|
|
| #ifdef __WASM_EXCEPTIONS__ |
| struct __cxa_dependent_exception; |
| uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception); |
| static bool isDependentException(_Unwind_Exception* unwind_exception) { |
| return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01; |
| } |
| #endif |
|
|
| extern "C" { |
|
|
| void* __thrown_object_from_unwind_exception( |
| _Unwind_Exception* unwind_exception) { |
| __cxa_exception* exception_header = |
| cxa_exception_from_unwind_exception(unwind_exception); |
| return thrown_object_from_cxa_exception(exception_header); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| void __get_exception_message(void* thrown_object, char** type, char** message) { |
| __cxa_exception* exception_header = |
| cxa_exception_from_thrown_object(thrown_object); |
| const __shim_type_info* thrown_type = |
| static_cast<const __shim_type_info*>(exception_header->exceptionType); |
| const char* type_name = thrown_type->name(); |
|
|
| int status = 0; |
| char* demangled_buf = __cxa_demangle(type_name, 0, 0, &status); |
| if (status == 0 && demangled_buf) { |
| *type = demangled_buf; |
| } else { |
| if (demangled_buf) { |
| free(demangled_buf); |
| } |
| *type = (char*)malloc(strlen(type_name) + 1); |
| strcpy(*type, type_name); |
| } |
|
|
| *message = NULL; |
| const __shim_type_info* catch_type = |
| static_cast<const __shim_type_info*>(&typeid(std::exception)); |
| int can_catch = catch_type->can_catch(thrown_type, thrown_object); |
| if (can_catch) { |
| #if __WASM_EXCEPTIONS__ |
| if (isDependentException(&exception_header->unwindHeader)) { |
| thrown_object = |
| reinterpret_cast<__cxa_dependent_exception*>(exception_header) |
| ->primaryException; |
| |
| [[maybe_unused]] bool ret = |
| catch_type->can_catch(thrown_type, thrown_object); |
| assert(ret); |
| } |
| #endif |
|
|
| const char* what = |
| static_cast<const std::exception*>(thrown_object)->what(); |
| *message = (char*)malloc(strlen(what) + 1); |
| strcpy(*message, what); |
| } |
| } |
|
|
| |
| |
| char* __get_exception_terminate_message(void* thrown_object) { |
| char* type; |
| char* message; |
| __get_exception_message(thrown_object, &type, &message); |
| char* result; |
| if (message != NULL) { |
| asprintf( |
| &result, "terminating with uncaught exception %s: %s", type, message); |
| free(message); |
| } else { |
| asprintf(&result, "terminating with uncaught exception of type %s", type); |
| } |
| free(type); |
| return result; |
| } |
|
|
| #ifdef __WASM_EXCEPTIONS__ |
| void __increment_uncaught_exception() throw() { |
| __cxa_get_globals()->uncaughtExceptions += 1; |
| } |
|
|
| void __decrement_uncaught_exception() throw() { |
| __cxa_get_globals()->uncaughtExceptions -= 1; |
| } |
| #endif |
|
|
| } |
|
|
| } |
|
|
| #endif |
|
|