kit

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

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