1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 // Implements Wasm exception handling proposal
9 // (https://github.com/WebAssembly/exception-handling) based C++ exceptions
11 //===----------------------------------------------------------------------===//
17 #ifdef __WASM_EXCEPTIONS__
22 _Unwind_Reason_Code
__gxx_personality_wasm0(int version
, _Unwind_Action actions
,
23 uint64_t exceptionClass
,
24 _Unwind_Exception
*unwind_exception
,
25 _Unwind_Context
*context
);
27 struct _Unwind_LandingPadContext
{
28 // Input information to personality function
29 uintptr_t lpad_index
; // landing pad index
30 uintptr_t lsda
; // LSDA address
32 // Output information computed by personality function
33 uintptr_t selector
; // selector value
36 // Communication channel between compiler-generated user code and personality
38 thread_local
struct _Unwind_LandingPadContext __wasm_lpad_context
;
40 /// Calls to this function is in landing pads in compiler-generated user code.
41 /// In other EH schemes, stack unwinding is done by libunwind library, which
42 /// calls the personality function for each each frame it lands. On the other
43 /// hand, WebAssembly stack unwinding process is performed by a VM, and the
44 /// personality function cannot be called from there. So the compiler inserts
45 /// a call to this function in landing pads in the user code, which in turn
46 /// calls the personality function.
47 _Unwind_Reason_Code
_Unwind_CallPersonality(void *exception_ptr
) {
48 struct _Unwind_Exception
*exception_object
=
49 (struct _Unwind_Exception
*)exception_ptr
;
50 _LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
51 (void *)exception_object
);
53 // Reset the selector.
54 __wasm_lpad_context
.selector
= 0;
56 // Call personality function. Wasm does not have two-phase unwinding, so we
57 // only do the cleanup phase.
58 return __gxx_personality_wasm0(
59 1, _UA_SEARCH_PHASE
, exception_object
->exception_class
, exception_object
,
60 (struct _Unwind_Context
*)&__wasm_lpad_context
);
63 /// Called by __cxa_throw.
64 _LIBUNWIND_EXPORT _Unwind_Reason_Code
65 _Unwind_RaiseException(_Unwind_Exception
*exception_object
) {
66 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",
67 (void *)exception_object
);
68 // Use Wasm EH's 'throw' instruction.
69 __builtin_wasm_throw(0, exception_object
);
72 /// Called by __cxa_end_catch.
73 _LIBUNWIND_EXPORT
void
74 _Unwind_DeleteException(_Unwind_Exception
*exception_object
) {
75 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
76 (void *)(exception_object
));
77 if (exception_object
->exception_cleanup
!= NULL
)
78 (*exception_object
->exception_cleanup
)(_URC_FOREIGN_EXCEPTION_CAUGHT
,
82 /// Called by personality handler to alter register values.
83 _LIBUNWIND_EXPORT
void _Unwind_SetGR(struct _Unwind_Context
*context
, int index
,
85 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",
86 (void *)context
, index
, value
);
87 // We only use this function to set __wasm_lpad_context.selector field, which
88 // is index 1 in the personality function.
90 ((struct _Unwind_LandingPadContext
*)context
)->selector
= value
;
93 /// Called by personality handler to get instruction pointer.
94 _LIBUNWIND_EXPORT
uintptr_t _Unwind_GetIP(struct _Unwind_Context
*context
) {
95 // The result will be used as an 1-based index after decrementing 1, so we
98 ((struct _Unwind_LandingPadContext
*)context
)->lpad_index
+ 2;
99 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context
,
104 /// Not used in Wasm.
105 _LIBUNWIND_EXPORT
void _Unwind_SetIP(struct _Unwind_Context
*context
,
108 /// Called by personality handler to get LSDA for current frame.
109 _LIBUNWIND_EXPORT
uintptr_t
110 _Unwind_GetLanguageSpecificData(struct _Unwind_Context
*context
) {
111 uintptr_t result
= ((struct _Unwind_LandingPadContext
*)context
)->lsda
;
112 _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",
113 (void *)context
, result
);
117 /// Not used in Wasm.
118 _LIBUNWIND_EXPORT
uintptr_t
119 _Unwind_GetRegionStart(struct _Unwind_Context
*context
) {
123 #endif // defined(__WASM_EXCEPTIONS__)