kit

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

commit 0dcc91b39522fbc9557618c46bf4d193aa40bba9
parent 10edd3fecf8e36b56b5b8b41b653755dd44de48c
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu,  7 May 2026 13:14:35 -0700

setjmp.h

Diffstat:
Mdoc/builtins.md | 4++++
Ainclude/setjmp.h | 23+++++++++++++++++++++++
Mtest/smoke.c | 13+++++++++++++
3 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/doc/builtins.md b/doc/builtins.md @@ -149,6 +149,10 @@ Always: - Float → float: `__extendsfdf2`, `__extendsftf2`, `__extenddftf2`, `__truncdfsf2`, `__trunctfsf2`, `__trunctfdf2` - Compare: `__eq`, `__ne`, `__lt`, `__le`, `__gt`, `__ge`, `__unord` × `sf2`/`df2`/`tf2` +### Nonlocal jumps (always shipped) +- `setjmp`, `longjmp` — target-specific assembly. The `jmp_buf` layout is + internal to these two functions; `<setjmp.h>` only fixes the array size. + ### Atomic fallbacks (only when target lacks native atomics for that width) - Generic: `__atomic_load`, `__atomic_store`, `__atomic_exchange`, `__atomic_compare_exchange` - Sized N ∈ {1,2,4,8,16}: `__atomic_load_N`, `__atomic_store_N`, `__atomic_exchange_N`, `__atomic_compare_exchange_N`, `__atomic_fetch_{add,sub,and,or,xor,nand}_N` diff --git a/include/setjmp.h b/include/setjmp.h @@ -0,0 +1,23 @@ +/* setjmp.h -- C11 7.13 -- Nonlocal jumps + * + * setjmp.h is *not* part of the C11 freestanding subset (C11 4p6); cfree + * provides it as an extension for code that wants nonlocal control flow + * without a hosted libc. The setjmp/longjmp pair is target-specific + * assembly and lives in libcfree_rt.a -- see doc/builtins.md. + * + * jmp_buf is an array type (C11 7.13p2). Its layout is internal to the + * runtime; the size below is conservative -- large enough to hold every + * cfree target's callee-saved GPRs + callee-saved FPRs + sp + return + * address. C11 7.13 explicitly excludes the floating-point status flags, + * the state of open files, and any other component of the abstract + * machine, so no signal-mask slot is reserved. + */ +#ifndef CFREE_SETJMP_H +#define CFREE_SETJMP_H + +typedef long jmp_buf[32]; + +int setjmp(jmp_buf env); +_Noreturn void longjmp(jmp_buf env, int val); + +#endif diff --git a/test/smoke.c b/test/smoke.c @@ -29,6 +29,7 @@ #include <float.h> #include <iso646.h> #include <limits.h> +#include <setjmp.h> #include <stdalign.h> #include <stdarg.h> #include <stdatomic.h> @@ -131,6 +132,17 @@ static int sum_n(int n, ...) { /* stdnoreturn: macro must expand to a usable function specifier. */ static noreturn void cfree_trap(void) { for (;;) {} } +/* setjmp: jmp_buf is an array type, setjmp is callable in the contexts + permitted by C11 7.13.1.1p4, longjmp is _Noreturn. Compile-only -- + smoke.c never links against a setjmp implementation. */ +_Static_assert(sizeof(jmp_buf) >= sizeof(void *) * 8, "jmp_buf room for regs"); +static jmp_buf cfree_jb; +static int cfree_setjmp_compiles(int x) { + if (setjmp(cfree_jb) != 0) return 1; /* allowed context */ + if (x) longjmp(cfree_jb, 42); + return 0; +} + /* stdatomic: types, memory_order, lock-free macros, plus a runtime exercise of load, store, exchange, CAS, fetch ops, and atomic_flag. */ _Static_assert(sizeof(atomic_int) == sizeof(int), "atomic_int matches int"); @@ -172,5 +184,6 @@ static int cfree_atomic_ok(void) { int cfree_smoke_ok(void) { (void)aligned_buf; if (0) cfree_trap(); + if (0) (void)cfree_setjmp_compiles(0); return sum_n(3, 1, 2, 3) == 6 && cfree_atomic_ok(); }