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
6 changes: 6 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ jobs:
echo "NM=$CLANG_DIR/llvm-nm" >> $GITHUB_ENV
if: matrix.os == 'ubuntu-latest'

- name: Disable libsetjmp for old LLVM
shell: bash
run: |
echo "BUILD_LIBSETJMP=no" >> $GITHUB_ENV
if: matrix.clang_version == '10.0.0'

- name: Build libc
shell: bash
run: |
Expand Down
33 changes: 29 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ WASI_SNAPSHOT ?= p1
MALLOC_IMPL ?= dlmalloc
# yes or no
BUILD_LIBC_TOP_HALF ?= yes
# yes or no
BUILD_LIBSETJMP ?= yes
# The directory where we will store intermediate artifacts.
OBJDIR ?= build/$(TARGET_TRIPLE)
# The directory where we store files and tools for generating WASIp2 bindings
Expand Down Expand Up @@ -92,6 +94,7 @@ LIBC_BOTTOM_HALF_OMIT_SOURCES := \
$(LIBC_BOTTOM_HALF_SOURCES)/accept-wasip2.c
LIBC_BOTTOM_HALF_ALL_SOURCES := $(filter-out $(LIBC_BOTTOM_HALF_OMIT_SOURCES),$(LIBC_BOTTOM_HALF_ALL_SOURCES))
# Omit p2-specific headers from include-all.c test.
# for exception-handling.
INCLUDE_ALL_CLAUSES := -not -name wasip2.h -not -name descriptor_table.h
endif

Expand Down Expand Up @@ -123,6 +126,7 @@ LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c
LIBDL_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/dl.c
LIBSETJMP_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/setjmp/wasm32/rt.c
LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c)
LIBC_TOP_HALF_DIR = libc-top-half
LIBC_TOP_HALF_MUSL_DIR = $(LIBC_TOP_HALF_DIR)/musl
Expand Down Expand Up @@ -428,6 +432,7 @@ LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES))
LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES))
LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES))
LIBDL_OBJS = $(call objs,$(LIBDL_SOURCES))
LIBSETJMP_OBJS = $(call objs,$(LIBSETJMP_SOURCES))
LIBC_BOTTOM_HALF_CRT_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_CRT_SOURCES))

# These variables describe the locations of various files and
Expand Down Expand Up @@ -493,7 +498,6 @@ MUSL_OMIT_HEADERS += \
"netdb.h" \
"resolv.h" \
"pty.h" \
"setjmp.h" \
"ulimit.h" \
"sys/xattr.h" \
"wordexp.h" \
Expand Down Expand Up @@ -529,6 +533,7 @@ LIBWASI_EMULATED_GETPID_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_GETP
LIBWASI_EMULATED_SIGNAL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_OBJS))
LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS))
LIBDL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBDL_OBJS))
LIBSETJMP_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBSETJMP_OBJS))
BULK_MEMORY_SO_OBJS = $(patsubst %.o,%.pic.o,$(BULK_MEMORY_OBJS))
DLMALLOC_SO_OBJS = $(patsubst %.o,%.pic.o,$(DLMALLOC_OBJS))
LIBC_BOTTOM_HALF_ALL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBC_BOTTOM_HALF_ALL_OBJS))
Expand All @@ -543,6 +548,7 @@ PIC_OBJS = \
$(LIBWASI_EMULATED_SIGNAL_SO_OBJS) \
$(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) \
$(LIBDL_SO_OBJS) \
$(LIBSETJMP_SO_OBJS) \
$(BULK_MEMORY_SO_OBJS) \
$(DLMALLOC_SO_OBJS) \
$(LIBC_BOTTOM_HALF_ALL_SO_OBJS) \
Expand Down Expand Up @@ -572,6 +578,8 @@ $(OBJDIR)/libwasi-emulated-signal.so.a: $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) $(LIB

$(OBJDIR)/libdl.so.a: $(LIBDL_SO_OBJS)

$(OBJDIR)/libsetjmp.so.a: $(LIBSETJMP_SO_OBJS)

$(SYSROOT_LIB)/libc.a: $(LIBC_OBJS)

$(SYSROOT_LIB)/libc-printscan-long-double.a: $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS)
Expand All @@ -588,6 +596,8 @@ $(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBW

$(SYSROOT_LIB)/libdl.a: $(LIBDL_OBJS)

$(SYSROOT_LIB)/libsetjmp.a: $(LIBSETJMP_OBJS)

%.a:
@mkdir -p "$(@D)"
# On Windows, the commandline for the ar invocation got too long, so it needs to be split up.
Expand Down Expand Up @@ -617,6 +627,9 @@ $(BULK_MEMORY_OBJS) $(BULK_MEMORY_SO_OBJS): CFLAGS += \
$(BULK_MEMORY_OBJS) $(BULK_MEMORY_SO_OBJS): CFLAGS += \
-DBULK_MEMORY_THRESHOLD=$(BULK_MEMORY_THRESHOLD)

$(LIBSETJMP_OBJS) $(LIBSETJMP_SO_OBJS): CFLAGS += \
-mllvm -wasm-enable-sjlj

$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS): CFLAGS += \
-D_WASI_EMULATED_SIGNAL

Expand Down Expand Up @@ -660,7 +673,7 @@ startup_files $(LIBC_BOTTOM_HALF_ALL_OBJS) $(LIBC_BOTTOM_HALF_ALL_SO_OBJS): CFLA
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal

$(LIBC_TOP_HALF_ALL_OBJS) $(LIBC_TOP_HALF_ALL_SO_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) $(LIBDL_OBJS) $(LIBDL_SO_OBJS): CFLAGS += \
$(LIBC_TOP_HALF_ALL_OBJS) $(LIBC_TOP_HALF_ALL_SO_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) $(LIBDL_OBJS) $(LIBDL_SO_OBJS) $(LIBSETJMP_OBJS) $(LIBSETJMP_SO_OBJS): CFLAGS += \
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \
-I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 \
Expand Down Expand Up @@ -727,11 +740,15 @@ LIBC_SO = \
$(SYSROOT_LIB)/libwasi-emulated-getpid.so \
$(SYSROOT_LIB)/libwasi-emulated-signal.so \
$(SYSROOT_LIB)/libdl.so
ifeq ($(BUILD_LIBSETJMP),yes)
LIBC_SO += \
$(SYSROOT_LIB)/libsetjmp.so
endif
endif

libc_so: include_dirs $(LIBC_SO)

libc: include_dirs \
STATIC_LIBS = \
$(SYSROOT_LIB)/libc.a \
$(SYSROOT_LIB)/libc-printscan-long-double.a \
$(SYSROOT_LIB)/libc-printscan-no-floating-point.a \
Expand All @@ -740,6 +757,12 @@ libc: include_dirs \
$(SYSROOT_LIB)/libwasi-emulated-getpid.a \
$(SYSROOT_LIB)/libwasi-emulated-signal.a \
$(SYSROOT_LIB)/libdl.a
ifeq ($(BUILD_LIBSETJMP),yes)
STATIC_LIBS += \
$(SYSROOT_LIB)/libsetjmp.a
endif

libc: include_dirs $(STATIC_LIBS)

finish: startup_files libc
#
Expand Down Expand Up @@ -799,8 +822,10 @@ check-symbols: startup_files libc
#
# Generate a test file that includes all public C header files.
#
# setjmp.h is excluded because it requires a different compiler option
#
cd "$(SYSROOT_INC)" && \
for header in $$(find . -type f -not -name mman.h -not -name signal.h -not -name times.h -not -name resource.h $(INCLUDE_ALL_CLAUSES) |grep -v /bits/ |grep -v /c++/); do \
for header in $$(find . -type f -not -name mman.h -not -name signal.h -not -name times.h -not -name resource.h -not -name setjmp.h $(INCLUDE_ALL_CLAUSES) |grep -v /bits/ |grep -v /c++/); do \
echo '#include <'$$header'>' | sed 's/\.\///' ; \
done |LC_ALL=C sort >$(SYSROOT_SHARE)/include-all.c ; \
cd - >/dev/null
Expand Down
1 change: 1 addition & 0 deletions libc-top-half/musl/arch/wasm32/bits/setjmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
typedef unsigned long __jmp_buf[8];
10 changes: 6 additions & 4 deletions libc-top-half/musl/include/setjmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ extern "C" {

#include <features.h>

#ifdef __wasilibc_unmodified_upstream /* WASI has no setjmp */
#ifndef __wasilibc_unmodified_upstream
/* WASI has no setjmp */
#if !defined(__wasm_exception_handling__)
#error Setjmp/longjmp support requires Exception handling support, which is [not yet standardized](https://github.com/WebAssembly/proposals?tab=readme-ov-file#phase-3---implementation-phase-cg--wg). To enable it, compile with `-mllvm -wasm-enable-sjlj` and use an engine that implements the Exception handling proposal.
#endif
#endif
#include <bits/setjmp.h>

typedef struct __jmp_buf_tag {
Expand Down Expand Up @@ -40,9 +45,6 @@ int setjmp (jmp_buf) __setjmp_attr;
_Noreturn void longjmp (jmp_buf, int);

#define setjmp setjmp
#else
#warning setjmp is not yet implemented for WASI
#endif

#undef __setjmp_attr

Expand Down
83 changes: 83 additions & 0 deletions libc-top-half/musl/src/setjmp/wasm32/rt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* a runtime implementation for
* https://github.com/llvm/llvm-project/pull/84137
* https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
Copy link
Member

Choose a reason for hiding this comment

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

Ideally we should copy the content of this into the tool-conventions repo. Would you be interested in doing this, or would you mind if I did it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i agree we should document in the tool-conventions repo.
i think i can write something next month.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

*/

#include <stddef.h>
#include <stdint.h>

/*
* function prototypes
*/
void __wasm_setjmp(void *env, uint32_t label, void *func_invocation_id);
uint32_t __wasm_setjmp_test(void *env, void *func_invocation_id);
void __wasm_longjmp(void *env, int val);

/*
* jmp_buf should have large enough size and alignment to contain
* this structure.
*/
struct jmp_buf_impl {
void *func_invocation_id;
uint32_t label;

/*
* this is a temorary storage used by the communication between
* __wasm_sjlj_longjmp and WebAssemblyLowerEmscriptenEHSjL-generated
* logic.
* ideally, this can be replaced with multivalue.
*/
struct arg {
void *env;
int val;
} arg;
};

void
__wasm_setjmp(void *env, uint32_t label, void *func_invocation_id)
{
struct jmp_buf_impl *jb = env;
if (label == 0) { /* ABI contract */
__builtin_trap();
}
if (func_invocation_id == NULL) { /* sanity check */
__builtin_trap();
}
jb->func_invocation_id = func_invocation_id;
jb->label = label;
}

uint32_t
__wasm_setjmp_test(void *env, void *func_invocation_id)
{
struct jmp_buf_impl *jb = env;
if (jb->label == 0) { /* ABI contract */
__builtin_trap();
}
if (func_invocation_id == NULL) { /* sanity check */
__builtin_trap();
}
if (jb->func_invocation_id == func_invocation_id) {
return jb->label;
}
return 0;
}

void
__wasm_longjmp(void *env, int val)
{
struct jmp_buf_impl *jb = env;
struct arg *arg = &jb->arg;
/*
* C standard says:
* The longjmp function cannot cause the setjmp macro to return
* the value 0; if val is 0, the setjmp macro returns the value 1.
*/
if (val == 0) {
val = 1;
}
arg->env = env;
arg->val = val;
__builtin_wasm_throw(1, arg); /* 1 == C_LONGJMP */
}