Skip to content
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
9 changes: 7 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,13 @@ jobs:
matrix:
include:
- name: default
- name: exceptions
defines: -DWASI_SDK_EXCEPTIONS=ON
# This one is temporarily disabled until LLVM 24 is available because
# we currently apply backported patches from
# https://github.com/llvm/llvm-project/pull/209282 which affect both
# the toolchain and the sysroot and which rely on each other.
#
# - name: exceptions
# defines: -DWASI_SDK_EXCEPTIONS=ON
- name: static
defines: -DWASI_SDK_BUILD_SHARED=OFF
steps:
Expand Down
11 changes: 4 additions & 7 deletions cmake/wasi-sdk-sysroot.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ function(define_libcxx_sub sysroot target target_suffix extra_target_flags extra
set(pic OFF)
set(target_flags -pthread)
else()
set(pic ON)
if(${target} MATCHES "p[23]")
set(pic ON)
endif()
set(target_flags "")
endif()
if(${target_suffix} MATCHES lto)
Expand All @@ -298,12 +300,6 @@ function(define_libcxx_sub sysroot target target_suffix extra_target_flags extra
set(exnsuffix "")

if (exceptions)
# TODO: lots of builds fail with shared libraries and `-fPIC`. Looks like
# things are maybe changing in llvm/llvm-project#159143 but otherwise I'm at
# least not really sure what the state of shared libraries and exceptions
# are. For now shared libraries are disabled and supporting them is left for
# a future endeavor.
set(pic OFF)
set(runtimes "libunwind;${runtimes}")
list(APPEND extra_flags -fwasm-exceptions -mllvm -wasm-use-legacy-eh=false)
if (WASI_SDK_EXCEPTIONS STREQUAL "DUAL")
Expand Down Expand Up @@ -348,6 +344,7 @@ function(define_libcxx_sub sysroot target target_suffix extra_target_flags extra
${CMAKE_SOURCE_DIR}/src/llvm-pr-168449.patch
${CMAKE_SOURCE_DIR}/src/llvm-pr-186054.patch
${CMAKE_SOURCE_DIR}/src/llvm-undo-part-of-194317.patch
${CMAKE_SOURCE_DIR}/src/llvm-sysroot-pr-209282-and-pr-222747.patch
)
list(JOIN patches " " patches)

Expand Down
8 changes: 8 additions & 0 deletions cmake/wasi-sdk-toolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,11 @@ endif()
list(TRANSFORM tools PREPEND --target= OUTPUT_VARIABLE build_targets)
list(TRANSFORM tools PREPEND --target=install- OUTPUT_VARIABLE install_targets)

set(patches
${CMAKE_SOURCE_DIR}/src/llvm-toolchain-pr-209282-and-pr-222747.patch
)
list(JOIN patches " " patches)

ExternalProject_Add(llvm-build
SOURCE_DIR "${llvm_proj_dir}/llvm"
CMAKE_ARGS
Expand Down Expand Up @@ -255,6 +260,9 @@ ExternalProject_Add(llvm-build
USES_TERMINAL_CONFIGURE ON
USES_TERMINAL_BUILD ON
USES_TERMINAL_INSTALL ON
PATCH_COMMAND
${CMAKE_COMMAND} -E chdir .. bash -c
"git apply ${patches} || git apply ${patches} -R --check"
)

add_custom_target(build ALL DEPENDS llvm-build)
Expand Down
140 changes: 140 additions & 0 deletions src/llvm-sysroot-pr-209282-and-pr-222747.patch

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Would it be possible to avoid manually splitting/merging *.patch files? I've historically attempted to keep the patch files as literal output of curl https://github.com/llvm/llvm-project/pull/208597.diff -L -o ./src/llvm-pr-208597.patch for example which makes it a bit easier to maintain over time. I couldn't do that for some versions in the past when things conflicted, however.

Another way to put this: if literal *.patch files-from-prs don't work, could you expand on why? (also the rationale for the sysroot/toolchain split)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

A few reasons:

  • The actual upstream git diff for each PR doesn't apply to LLVM 23 due to other changes which have happened on LLVM main, so I had to edit them it as part of the backport
  • Both PRs involve both toolchain and sysroot changes which depend on each other. And if I apply either patch only in wasi-sdk-toolchain.cmake or only in wasi-sdk-sysroot.cmake, but only the other one is built, then it won't have the required changes, hence the split.
  • Since 222747 depends on 209282 having been applied first, the git diff ... -R --check was erroring when they were two separate files. I later saw your reverse-the-list trick in the wasi-sdk-toolchain.cmake history which might address that, though.
  • I figured the test .ll files weren't relevant, so I stripped them out

Happy to revisit any of that if there's a better way.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ok I kind of figure it was something like that but wanted to double check, yeah, and it's ok to land as-is just wanted to have some written-down rationale as well

Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index c5050e46c0e8..da2d8b2599d9 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -1011,9 +1011,7 @@ static inline void get_landing_pad(__cxa_catch_temp_type &dest,
#endif
}

-#ifdef __WASM_EXCEPTIONS__
-_Unwind_Reason_Code __gxx_personality_wasm0
-#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+#if (defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)) || defined(__WASM_EXCEPTIONS__)
static _Unwind_Reason_Code __gxx_personality_imp
#else
_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
@@ -1114,6 +1112,22 @@ __gxx_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame,
}
#endif

+#ifdef __WASM_EXCEPTIONS__
+extern "C" _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __gxx_wasm_personality_v0(void* exception_ptr) {
+ struct _Unwind_Exception* exception_object = (struct _Unwind_Exception*)exception_ptr;
+
+ struct _Unwind_LandingPadContext* context = _Unwind_GetWasmLPadContext();
+
+ // Reset the selector.
+ context->selector = 0;
+
+ // Call personality function. Wasm does not have two-phase unwinding, so we
+ // only do the search phase.
+ return __gxx_personality_imp(
+ 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object, (struct _Unwind_Context*)context);
+}
+#endif
+
#else

extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*, _Unwind_Context*);
diff --git a/libunwind/include/unwind.h b/libunwind/include/unwind.h
index b1775d3a3dec..93a9d92f327d 100644
--- a/libunwind/include/unwind.h
+++ b/libunwind/include/unwind.h
@@ -61,6 +61,10 @@ typedef struct _Unwind_Context _Unwind_Context; // opaque
#include <unwind_itanium.h>
#endif

+#if defined(__WASM_EXCEPTIONS__)
+#include <unwind_wasm.h>
+#endif
+
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int version,
_Unwind_Action actions,
diff --git a/libunwind/include/unwind_wasm.h b/libunwind/include/unwind_wasm.h
new file mode 100644
index 000000000000..66d1792919ab
--- /dev/null
+++ b/libunwind/include/unwind_wasm.h
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __WASM_UNWIND_H__
+#define __WASM_UNWIND_H__
+
+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
+#ifdef __cplusplus
+extern "C"
+#endif
+ struct _Unwind_LandingPadContext *_Unwind_GetWasmLPadContext(void);
+
+#endif // __WASM_UNWIND_H__
diff --git a/libunwind/src/Unwind-wasm.c b/libunwind/src/Unwind-wasm.c
index 2e949d005b8f..f17eeb27e97b 100644
--- a/libunwind/src/Unwind-wasm.c
+++ b/libunwind/src/Unwind-wasm.c
@@ -19,45 +19,11 @@
#include "unwind.h"
#include <threads.h>

-_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 are 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 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 search phase.
- return __gxx_personality_wasm0(
- 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
- (struct _Unwind_Context *)&__wasm_lpad_context);
+_LIBUNWIND_EXPORT struct _Unwind_LandingPadContext *
+_Unwind_GetWasmLPadContext(void) {
+ return &__wasm_lpad_context;
}

/// Called by __cxa_throw.
Loading
Loading