diff --git a/compiler-rt/emscripten_setjmp.c b/compiler-rt/emscripten_setjmp.c index 9c4afc3620d81..b43df61b9154e 100644 --- a/compiler-rt/emscripten_setjmp.c +++ b/compiler-rt/emscripten_setjmp.c @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include #include #include #include @@ -67,27 +68,71 @@ uint32_t testSetjmp(uintptr_t id, TableEntry* table, uint32_t size) { #include "emscripten_internal.h" void emscripten_longjmp(uintptr_t env, int val) { + // C standard: + // 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; + } setThrew(env, val); _emscripten_throw_longjmp(); } #endif #ifdef __USING_WASM_SJLJ__ - struct __WasmLongjmpArgs { void *env; int val; }; -thread_local struct __WasmLongjmpArgs __wasm_longjmp_args; +// llvm uses `1` for the __c_longjmp tag. +// See https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h +#define C_LONGJMP 1 +#endif +// jmp_buf should have large enough size and alignment to contain +// this structure. +struct jmp_buf_impl { + void* func_invocation_id; + uint32_t label; +#ifdef __USING_WASM_SJLJ__ + struct __WasmLongjmpArgs arg; +#endif +}; + +void __wasm_setjmp(void* env, uint32_t label, void* func_invocation_id) { + struct jmp_buf_impl* jb = env; + assert(label != 0); // ABI contract + assert(func_invocation_id != NULL); // sanity check + 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; + assert(jb->label != 0); // ABI contract + assert(func_invocation_id != NULL); // sanity check + if (jb->func_invocation_id == func_invocation_id) { + return jb->label; + } + return 0; +} + +#ifdef __USING_WASM_SJLJ__ // Wasm EH allows us to throw and catch multiple values, but that requires // multivalue support in the toolchain, whch is not reliable at the time. // TODO Consider switching to throwing two values at the same time later. -void __wasm_longjmp(void *env, int val) { - __wasm_longjmp_args.env = env; - __wasm_longjmp_args.val = val; - __builtin_wasm_throw(1, &__wasm_longjmp_args); +void __wasm_longjmp(void* env, int val) { + struct jmp_buf_impl* jb = env; + struct __WasmLongjmpArgs* 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(C_LONGJMP, arg); } - #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_emscripten.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_emscripten.cpp index babc6793663a7..c10dc0048a327 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_emscripten.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_emscripten.cpp @@ -127,6 +127,8 @@ u64 MonotonicNanoTime() { return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; } +void GetMemoryProfile(fill_profile_f cb, uptr *stats) {} + } // namespace __sanitizer #endif diff --git a/compiler-rt/stack_ops.S b/compiler-rt/stack_ops.S index b56b1dd524d69..9d1913d7219e3 100644 --- a/compiler-rt/stack_ops.S +++ b/compiler-rt/stack_ops.S @@ -1,6 +1,5 @@ -.globl stackSave -.globl stackRestore -.globl stackAlloc +.globl _emscripten_stack_restore +.globl _emscripten_stack_alloc .globl emscripten_stack_get_current #ifdef __wasm64__ @@ -13,19 +12,14 @@ .globaltype __stack_pointer, PTR -stackSave: - .functype stackSave() -> (PTR) - global.get __stack_pointer - end_function - -stackRestore: - .functype stackRestore(PTR) -> () +_emscripten_stack_restore: + .functype _emscripten_stack_restore(PTR) -> () local.get 0 global.set __stack_pointer end_function -stackAlloc: - .functype stackAlloc(PTR) -> (PTR) +_emscripten_stack_alloc: + .functype _emscripten_stack_alloc(PTR) -> (PTR) .local PTR, PTR global.get __stack_pointer # Get arg 0 -> number of bytes to allocate @@ -44,4 +38,3 @@ emscripten_stack_get_current: .functype emscripten_stack_get_current () -> (PTR) global.get __stack_pointer end_function -