#ifndef VLIBC_SETJMP_H #define VLIBC_SETJMP_H /* * vlibc — . * * Non-local jumps. setjmp(env) saves the calling environment and returns 0; * longjmp(env, val) makes that setjmp return val, with 0 coerced to 1 so the * two returns are distinguishable. sigsetjmp/siglongjmp additionally save and * restore the signal mask when the buffer's saved-mask flag is set. * * jmp_buf is an array type (C23 7.13.1 requires it); both types below are * arrays of unsigned long. The word layout is ABI: the x86_64 assembly in * src/setjmp/x86_64/{setjmp,longjmp,sigsetjmp,siglongjmp}.s reads and writes * exactly these slots. This comment is the single authoritative map — keep it * and those files in sync: * * [0] rbx callee-saved general registers (System V AMD64 ABI) * [1] rbp * [2] r12 * [3] r13 * [4] r14 * [5] r15 * [6] rsp the caller's stack pointer (just past the return address) * [7] rip the return address, where longjmp resumes execution * [8] mxcsr SSE control/status register (stmxcsr/ldmxcsr) * [9] x87 cw x87 control word (fnstcw/fldcw) * * sigjmp_buf extends the base layout with two more words: * * [10] saved-mask flag (1 when the signal mask was saved) * [11] signal mask (the x86_64 Linux sigset_t: a single 64-bit word) * * Because the base layout occupies words 0..9 of both types, the plain * setjmp/longjmp assembly works verbatim on sigjmp_buf storage as well. */ #include #ifdef __cplusplus extern "C" { #endif /* Word counts and per-slot indices (see the authoritative map above). */ #define VLIBC_JMP_BUF_WORDS 10 #define VLIBC_JMP_RBX 0 #define VLIBC_JMP_RBP 1 #define VLIBC_JMP_R12 2 #define VLIBC_JMP_R13 3 #define VLIBC_JMP_R14 4 #define VLIBC_JMP_R15 5 #define VLIBC_JMP_RSP 6 #define VLIBC_JMP_RIP 7 #define VLIBC_JMP_MXCSR 8 #define VLIBC_JMP_X87CW 9 #define VLIBC_SIGJMP_BUF_WORDS 12 #define VLIBC_SIGJMP_FLAG 10 #define VLIBC_SIGJMP_MASK 11 typedef unsigned long jmp_buf[VLIBC_JMP_BUF_WORDS]; typedef unsigned long sigjmp_buf[VLIBC_SIGJMP_BUF_WORDS]; /* * Save the calling environment and return 0; after longjmp(env, val) the * matching setjmp invocation returns val. A macro (C23 7.13.1: usable without * a prototype in scope); it expands to _setjmp(env). */ #define setjmp(env) _setjmp(env) /* * Like setjmp, plus the current signal mask is saved into env when savemask is * nonzero (siglongjmp then restores it). Macro expanding to * __sigsetjmp(env, savemask). */ #define sigsetjmp(env, savemask) __sigsetjmp(env, savemask) /* * The save behind the setjmp macro; identical semantics (POSIX _setjmp). */ int _setjmp(jmp_buf env); // NOLINT(bugprone-reserved-identifier) /* * Restore the environment saved by _setjmp/setjmp and make it return val, with * 0 coerced to 1. Does not return. */ __attribute__((noreturn)) void _longjmp(jmp_buf env, int val); // NOLINT(bugprone-reserved-identifier) /* * ISO C longjmp: same as _longjmp. */ __attribute__((noreturn)) void longjmp(jmp_buf env, int val); /* * The save behind the sigsetjmp macro. Implementation-reserved name, so the * public API keeps only the macro; declared because the macro expansion must * have a prototype in scope (C23 removed implicit declarations). */ int __sigsetjmp(sigjmp_buf env, int savemask); // NOLINT(bugprone-reserved-identifier) /* * Restore the environment saved by sigsetjmp and make it return val, with 0 * coerced to 1; when the buffer's saved-mask flag is set, the signal mask is * restored first. Does not return. */ __attribute__((noreturn)) void siglongjmp(sigjmp_buf env, int val); #ifdef __cplusplus } #endif #endif /* VLIBC_SETJMP_H */