Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/compiler-rt/emscripten_setjmp.c
6162 views
1
/*
2
* Copyright 2020 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
8
#include <assert.h>
9
#include <stdint.h>
10
#include <stdlib.h>
11
#include <setjmp.h>
12
#include <threads.h>
13
14
#include "emscripten_internal.h"
15
16
#ifdef __WASM_SJLJ__
17
struct __WasmLongjmpArgs {
18
void *env;
19
int val;
20
};
21
#endif
22
23
// jmp_buf should have large enough size and alignment to contain
24
// this structure.
25
struct jmp_buf_impl {
26
void* func_invocation_id;
27
uint32_t label;
28
#ifdef __WASM_SJLJ__
29
struct __WasmLongjmpArgs arg;
30
#endif
31
};
32
33
void __wasm_setjmp(void* env, uint32_t label, void* func_invocation_id) {
34
struct jmp_buf_impl* jb = env;
35
assert(label != 0); // ABI contract
36
assert(func_invocation_id != NULL); // sanity check
37
jb->func_invocation_id = func_invocation_id;
38
jb->label = label;
39
}
40
41
uint32_t __wasm_setjmp_test(void* env, void* func_invocation_id) {
42
struct jmp_buf_impl* jb = env;
43
assert(jb->label != 0); // ABI contract
44
assert(func_invocation_id != NULL); // sanity check
45
if (jb->func_invocation_id == func_invocation_id) {
46
return jb->label;
47
}
48
return 0;
49
}
50
51
#ifdef __WASM_SJLJ__
52
// llvm uses `1` for the __c_longjmp tag.
53
// See https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h
54
#define C_LONGJMP 1
55
56
// Wasm EH allows us to throw and catch multiple values, but that requires
57
// multivalue support in the toolchain, which is not reliable at the time.
58
// TODO Consider switching to throwing two values at the same time later.
59
void __wasm_longjmp(void* env, int val) {
60
struct jmp_buf_impl* jb = env;
61
struct __WasmLongjmpArgs* arg = &jb->arg;
62
// C standard says:
63
// The longjmp function cannot cause the setjmp macro to return
64
// the value 0; if val is 0, the setjmp macro returns the value 1.
65
if (val == 0) {
66
val = 1;
67
}
68
arg->env = env;
69
arg->val = val;
70
__builtin_wasm_throw(C_LONGJMP, arg);
71
}
72
#else
73
void emscripten_longjmp(uintptr_t env, int val) {
74
// C standard:
75
// The longjmp function cannot cause the setjmp macro to return
76
// the value 0; if val is 0, the setjmp macro returns the value 1.
77
if (val == 0) {
78
val = 1;
79
}
80
setThrew(env, val);
81
_emscripten_throw_longjmp();
82
}
83
#endif
84
85