Path: blob/main/system/lib/compiler-rt/emscripten_setjmp.c
6162 views
/*1* Copyright 2020 The Emscripten Authors. All rights reserved.2* Emscripten is available under two separate licenses, the MIT license and the3* University of Illinois/NCSA Open Source License. Both these licenses can be4* found in the LICENSE file.5*/67#include <assert.h>8#include <stdint.h>9#include <stdlib.h>10#include <setjmp.h>11#include <threads.h>1213#include "emscripten_internal.h"1415#ifdef __WASM_SJLJ__16struct __WasmLongjmpArgs {17void *env;18int val;19};20#endif2122// jmp_buf should have large enough size and alignment to contain23// this structure.24struct jmp_buf_impl {25void* func_invocation_id;26uint32_t label;27#ifdef __WASM_SJLJ__28struct __WasmLongjmpArgs arg;29#endif30};3132void __wasm_setjmp(void* env, uint32_t label, void* func_invocation_id) {33struct jmp_buf_impl* jb = env;34assert(label != 0); // ABI contract35assert(func_invocation_id != NULL); // sanity check36jb->func_invocation_id = func_invocation_id;37jb->label = label;38}3940uint32_t __wasm_setjmp_test(void* env, void* func_invocation_id) {41struct jmp_buf_impl* jb = env;42assert(jb->label != 0); // ABI contract43assert(func_invocation_id != NULL); // sanity check44if (jb->func_invocation_id == func_invocation_id) {45return jb->label;46}47return 0;48}4950#ifdef __WASM_SJLJ__51// llvm uses `1` for the __c_longjmp tag.52// See https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h53#define C_LONGJMP 15455// Wasm EH allows us to throw and catch multiple values, but that requires56// multivalue support in the toolchain, which is not reliable at the time.57// TODO Consider switching to throwing two values at the same time later.58void __wasm_longjmp(void* env, int val) {59struct jmp_buf_impl* jb = env;60struct __WasmLongjmpArgs* arg = &jb->arg;61// C standard says:62// The longjmp function cannot cause the setjmp macro to return63// the value 0; if val is 0, the setjmp macro returns the value 1.64if (val == 0) {65val = 1;66}67arg->env = env;68arg->val = val;69__builtin_wasm_throw(C_LONGJMP, arg);70}71#else72void emscripten_longjmp(uintptr_t env, int val) {73// C standard:74// The longjmp function cannot cause the setjmp macro to return75// the value 0; if val is 0, the setjmp macro returns the value 1.76if (val == 0) {77val = 1;78}79setThrew(env, val);80_emscripten_throw_longjmp();81}82#endif838485