Skip to content

Commit 35f6cc7

Browse files
committed
Add a setjmp/longjmp runtime for a new mode proposed in LLVM
Hopefully, this implementation can replace the current `-sSUPPORT_LONGJMP=wasm` implementation sooner or later. system/lib/compiler-rt/wasm_setjmp.c is basically a copy from: https://github.com/yamt/garbage/blob/wasm-sjlj-alt2/wasm/longjmp/rt.c. the copyright comment was copy-and-pasted from: system/lib/compiler-rt/emscripten_exception_builtins.c The corresponding LLVM change: llvm/llvm-project#84137 Discussion: https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
1 parent 2ba2078 commit 35f6cc7

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

system/lib/compiler-rt/wasm_setjmp.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2024 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*
7+
* a runtime implementation for
8+
* https://github.com/llvm/llvm-project/pull/84137
9+
* https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
10+
*
11+
* a plan is to replace the __USING_WASM_SJLJ__ part of emscripten_setjmp.c
12+
* with this.
13+
*/
14+
15+
#ifdef __USING_WASM_SJLJ__
16+
17+
#include <stddef.h>
18+
#include <stdint.h>
19+
20+
/*
21+
* jmp_buf should have large enough size and alignment to contain
22+
* this structure.
23+
*/
24+
struct jmp_buf_impl {
25+
void *func_invocation_id;
26+
uint32_t label;
27+
28+
/*
29+
* this is a temorary storage used by the communication between
30+
* __wasm_sjlj_longjmp and WebAssemblyLowerEmscriptenEHSjL-generated
31+
* logic.
32+
* ideally, this can be replaced with multivalue.
33+
*/
34+
struct arg {
35+
void *env;
36+
int val;
37+
} arg;
38+
};
39+
40+
void
41+
__wasm_sjlj_setjmp(void *env, uint32_t label, void *func_invocation_id)
42+
{
43+
struct jmp_buf_impl *jb = env;
44+
if (label == 0) { /* ABI contract */
45+
__builtin_trap();
46+
}
47+
if (func_invocation_id == NULL) { /* sanity check */
48+
__builtin_trap();
49+
}
50+
jb->func_invocation_id = func_invocation_id;
51+
jb->label = label;
52+
}
53+
54+
uint32_t
55+
__wasm_sjlj_test(void *env, void *func_invocation_id)
56+
{
57+
struct jmp_buf_impl *jb = env;
58+
if (jb->label == 0) { /* ABI contract */
59+
__builtin_trap();
60+
}
61+
if (func_invocation_id == NULL) { /* sanity check */
62+
__builtin_trap();
63+
}
64+
if (jb->func_invocation_id == func_invocation_id) {
65+
return jb->label;
66+
}
67+
return 0;
68+
}
69+
70+
void
71+
__wasm_sjlj_longjmp(void *env, int val)
72+
{
73+
struct jmp_buf_impl *jb = env;
74+
struct arg *arg = &jb->arg;
75+
/*
76+
* C standard:
77+
* > The longjmp function cannot cause the setjmp macro to return
78+
* > the value 0; if val is 0, the setjmp macro returns the value 1.
79+
*/
80+
if (val == 0) {
81+
val = 1;
82+
}
83+
arg->env = env;
84+
arg->val = val;
85+
__builtin_wasm_throw(1, arg); /* 1 == C_LONGJMP */
86+
}
87+
88+
#endif /* __USING_WASM_SJLJ__ */

tools/system_libs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,7 @@ class libcompiler_rt(MTLibrary, SjLjLibrary):
936936
'emscripten_setjmp.c',
937937
'emscripten_exception_builtins.c',
938938
'emscripten_tempret.s',
939+
'wasm_setjmp.c',
939940
'__trap.c',
940941
])
941942

0 commit comments

Comments
 (0)