setjmp.h (3038B)
1 /* setjmp.h -- C11 7.13 -- Nonlocal jumps 2 * 3 * setjmp.h is *not* part of the C11 freestanding subset (C11 4p6); 4 * kit provides it as an extension. The setjmp/longjmp pair is 5 * target-specific assembly in libkit_rt.a. A target without that assembly 6 * support fails at link time rather than substituting a hosted implementation. 7 * 8 * jmp_buf is an array type (C11 7.13p2). The runtime reinterprets the 9 * buffer as a per-target struct of callee-saved GPRs + callee-saved 10 * FPRs + sp + return address. The size below is sized to the largest 11 * such struct across kit targets -- 256 bytes (x86_64 Windows: 12 12 * GPR slots + xmm6-15). C11 explicitly excludes the FP status flags 13 * and open-file state, so no signal-mask slot is reserved. The same 14 * 256-byte payload is shared with <kit/coro.h>'s coro_ctx so the 15 * underlying save/restore halves are reused across all three 16 * primitives. */ 17 #ifndef KIT_SETJMP_H 18 #define KIT_SETJMP_H 19 20 /* Wrap in a struct so 16-byte alignment is guaranteed even when the 21 user puts a jmp_buf on the stack -- xmm save instructions require 22 it on x86_64. The [1] makes jmp_buf an array type as the standard 23 demands, so passing one to setjmp/longjmp decays to a pointer. */ 24 typedef struct { 25 _Alignas(16) unsigned char __kit_storage[256]; 26 } jmp_buf[1]; 27 28 /* On Windows (mingw) there is no bare `setjmp` symbol to link against: libc's 29 * <setjmp.h> defines setjmp as a macro over the per-arch intrinsic. kit's 30 * freestanding code wants POSIX-style pure register save/restore with no SEH 31 * frame unwinding (kit is arena-allocated; longjmp targets have no cleanup to 32 * run). The mingw symbol that delivers that differs by architecture, so the 33 * binding below mirrors mingw's own non-SEH idiom per arch. kit's 256-byte 34 * jmp_buf covers mingw's aarch64/x86_64 _JBLEN. Non-Windows targets resolve 35 * bare setjmp from the host libc (POSIX) or libkit_rt's per-arch coro asm. */ 36 #if defined(_WIN32) 37 #if defined(__aarch64__) || defined(__arm__) 38 /* aarch64/arm mingw ship the self-contained non-SEH __mingw_setjmp / 39 * __mingw_longjmp pair (libmingwex, no .pdata dependency). Bind by asm-label. 40 */ 41 int setjmp(jmp_buf env) __asm__("__mingw_setjmp"); 42 _Noreturn void longjmp(jmp_buf env, int val) __asm__("__mingw_longjmp"); 43 #else 44 /* x86_64 mingw exposes no __mingw_setjmp; its non-SEH idiom (the header's 45 * __USE_MINGW_SETJMP_NON_SEH path) is `_setjmp((buf), NULL)` — the ucrt 46 * intrinsic with a null frame so longjmp performs no SEH unwinding. `_setjmp` 47 * is a COFF weak-external alias to ucrt's `__intrinsic_setjmp`; the linker 48 * resolves that alias (see src/link/link_resolve.c). longjmp is a real ucrt 49 * export. The macro supplies the implicit frame argument; the declaration keeps 50 * the standard 1-argument setjmp prototype for callers that take its address. 51 */ 52 int _setjmp(jmp_buf env, void* frame); 53 _Noreturn void longjmp(jmp_buf env, int val); 54 #define setjmp(env) _setjmp((env), (void*)0) 55 #endif 56 #else 57 int setjmp(jmp_buf env); 58 _Noreturn void longjmp(jmp_buf env, int val); 59 #endif 60 61 #endif