Skip to content

Add downstream libunwind changes from emscripten #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libunwind/include/unwind_itanium.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct _Unwind_Exception {
_Unwind_Exception *exc);
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
uintptr_t private_[6];
#else
#elif !defined(__USING_WASM_EXCEPTIONS__)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a macro that already exists somewhere in libunwind ?

Copy link
Member Author

@aheejin aheejin Aug 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we add it to the command line from system_libs.py both for libcxxabi and libunwind.

uintptr_t private_1; // non-zero means forced unwind
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#endif
Expand Down
110 changes: 110 additions & 0 deletions libunwind/src/Unwind-wasm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include "config.h"
#include "unwind.h"
#include <stdbool.h>
#include <threads.h>

#ifdef __USING_WASM_EXCEPTIONS__

_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,
uint64_t exceptionClass,
_Unwind_Exception *unwind_exception,
_Unwind_Context *context);

struct _Unwind_LandingPadContext {
// Input information to personality function
uintptr_t lpad_index; // landing pad index
uintptr_t lsda; // LSDA address

// Output information computed by personality function
uintptr_t selector; // selector value
};

// Communication channel between compiler-generated user code and personality
// function
thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;

/// Calls to this function is in landing pads in compiler-generated user code.
/// In other EH schemes, stack unwinding is done by libunwind library, which
/// calls the personality function for each each frame it lands. On the other
/// hand, WebAssembly stack unwinding process is performed by a VM, and the
/// personality function cannot be called from there. So the compiler inserts
/// a call to this function in landing pads in the user code, which in turn
/// calls the personality function.
_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
struct _Unwind_Exception *exception_object =
(struct _Unwind_Exception *)exception_ptr;
_LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
(void *)exception_object);

// Reset the selector.
__wasm_lpad_context.selector = 0;

// Call personality function. Wasm does not have two-phase unwinding, so we
// only do the cleanup phase.
_Unwind_Reason_Code ret = __gxx_personality_wasm0(
1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)&__wasm_lpad_context);
return ret;
}

/// Called by __cxa_throw.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",
(void *)exception_object);
__builtin_wasm_throw(0, exception_object);
}

/// Called by __cxa_end_catch.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
(void *)(exception_object));
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
exception_object);
}

/// Called by personality handler to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",
(void *)context, index, value);
// We only use this function to set __wasm_lpad_context.selector field, which
// is index 1 in the personality function.
if (index != 1)
return;
((struct _Unwind_LandingPadContext *)context)->selector = value;
}

/// Called by personality handler to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
// The result will be used as an 1-based index after decrementing 1, so we
// increment 2 here
uintptr_t result =
((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context,
result);
return result;
}

/// Not used in wasm.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t value) {}

/// Called by personality handler to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda;
_LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",
(void *)context, result);
return result;
}

/// Not used in wasm.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
return 0;
}

#endif
1 change: 1 addition & 0 deletions libunwind/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
SYMBOL_NAME(name))) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname;
#endif
#elif defined(__EMSCRIPTEN__)
#else
#error Unsupported target
#endif
Expand Down