kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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