master
1/*
2 * a runtime implementation for
3 * https://github.com/llvm/llvm-project/pull/84137
4 * https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
5 */
6
7#include <stddef.h>
8#include <stdint.h>
9
10/*
11 * function prototypes
12 */
13void __wasm_setjmp(void *env, uint32_t label, void *func_invocation_id);
14uint32_t __wasm_setjmp_test(void *env, void *func_invocation_id);
15void __wasm_longjmp(void *env, int val);
16
17/*
18 * jmp_buf should have large enough size and alignment to contain
19 * this structure.
20 */
21struct jmp_buf_impl {
22 void *func_invocation_id;
23 uint32_t label;
24
25 /*
26 * this is a temorary storage used by the communication between
27 * __wasm_sjlj_longjmp and WebAssemblyLowerEmscriptenEHSjL-generated
28 * logic.
29 * ideally, this can be replaced with multivalue.
30 */
31 struct arg {
32 void *env;
33 int val;
34 } arg;
35};
36
37void
38__wasm_setjmp(void *env, uint32_t label, void *func_invocation_id)
39{
40 struct jmp_buf_impl *jb = env;
41 if (label == 0) { /* ABI contract */
42 __builtin_trap();
43 }
44 if (func_invocation_id == NULL) { /* sanity check */
45 __builtin_trap();
46 }
47 jb->func_invocation_id = func_invocation_id;
48 jb->label = label;
49}
50
51uint32_t
52__wasm_setjmp_test(void *env, void *func_invocation_id)
53{
54 struct jmp_buf_impl *jb = env;
55 if (jb->label == 0) { /* ABI contract */
56 __builtin_trap();
57 }
58 if (func_invocation_id == NULL) { /* sanity check */
59 __builtin_trap();
60 }
61 if (jb->func_invocation_id == func_invocation_id) {
62 return jb->label;
63 }
64 return 0;
65}
66
67void
68__wasm_longjmp(void *env, int val)
69{
70 struct jmp_buf_impl *jb = env;
71 struct arg *arg = &jb->arg;
72 /*
73 * C standard says:
74 * The longjmp function cannot cause the setjmp macro to return
75 * the value 0; if val is 0, the setjmp macro returns the value 1.
76 */
77 if (val == 0) {
78 val = 1;
79 }
80 arg->env = env;
81 arg->val = val;
82 __builtin_wasm_throw(1, arg); /* 1 == C_LONGJMP */
83}