Path: blob/main/contrib/llvm-project/libunwind/src/Unwind-wasm.c
35154 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//7// Implements Wasm exception handling proposal8// (https://github.com/WebAssembly/exception-handling) based C++ exceptions9//10//===----------------------------------------------------------------------===//1112#include <stdbool.h>1314#include "config.h"1516#ifdef __WASM_EXCEPTIONS__1718#include "unwind.h"19#include <threads.h>2021_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,22uint64_t exceptionClass,23_Unwind_Exception *unwind_exception,24_Unwind_Context *context);2526struct _Unwind_LandingPadContext {27// Input information to personality function28uintptr_t lpad_index; // landing pad index29uintptr_t lsda; // LSDA address3031// Output information computed by personality function32uintptr_t selector; // selector value33};3435// Communication channel between compiler-generated user code and personality36// function37thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;3839/// Calls to this function is in landing pads in compiler-generated user code.40/// In other EH schemes, stack unwinding is done by libunwind library, which41/// calls the personality function for each each frame it lands. On the other42/// hand, WebAssembly stack unwinding process is performed by a VM, and the43/// personality function cannot be called from there. So the compiler inserts44/// a call to this function in landing pads in the user code, which in turn45/// calls the personality function.46_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {47struct _Unwind_Exception *exception_object =48(struct _Unwind_Exception *)exception_ptr;49_LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",50(void *)exception_object);5152// Reset the selector.53__wasm_lpad_context.selector = 0;5455// Call personality function. Wasm does not have two-phase unwinding, so we56// only do the cleanup phase.57return __gxx_personality_wasm0(581, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,59(struct _Unwind_Context *)&__wasm_lpad_context);60}6162/// Called by __cxa_throw.63_LIBUNWIND_EXPORT _Unwind_Reason_Code64_Unwind_RaiseException(_Unwind_Exception *exception_object) {65_LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",66(void *)exception_object);67// Use Wasm EH's 'throw' instruction.68__builtin_wasm_throw(0, exception_object);69}7071/// Called by __cxa_end_catch.72_LIBUNWIND_EXPORT void73_Unwind_DeleteException(_Unwind_Exception *exception_object) {74_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",75(void *)(exception_object));76if (exception_object->exception_cleanup != NULL)77(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,78exception_object);79}8081/// Called by personality handler to alter register values.82_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,83uintptr_t value) {84_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",85(void *)context, index, value);86// We only use this function to set __wasm_lpad_context.selector field, which87// is index 1 in the personality function.88if (index == 1)89((struct _Unwind_LandingPadContext *)context)->selector = value;90}9192/// Called by personality handler to get instruction pointer.93_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {94// The result will be used as an 1-based index after decrementing 1, so we95// increment 2 here96uintptr_t result =97((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;98_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context,99result);100return result;101}102103/// Not used in Wasm.104_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,105uintptr_t value) {}106107/// Called by personality handler to get LSDA for current frame.108_LIBUNWIND_EXPORT uintptr_t109_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {110uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda;111_LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",112(void *)context, result);113return result;114}115116/// Not used in Wasm.117_LIBUNWIND_EXPORT uintptr_t118_Unwind_GetRegionStart(struct _Unwind_Context *context) {119return 0;120}121122#endif // defined(__WASM_EXCEPTIONS__)123124125