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