libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_tailcall.h
1/*-
2 * Copyright (c) 2026, The XTC Project
3 * Use of this source code is governed by the ISC License.
4 *
5 * src/inc/xtc_tailcall.h
6 * Mark functions/call-sites as MUST-be-tail-called. GCC and
7 * Clang both perform tail-call optimization (TCO) when the
8 * last operation in a function is a call to another function
9 * whose return value is also returned. We document the
10 * intent at the call site so a script can verify that the
11 * compiler actually emitted a `jmp` (or arch-equivalent) and
12 * not a `call` followed by `ret`.
13 *
14 * Usage:
15 * - At a call-site that MUST be tail-called for correctness
16 * (e.g. avoiding stack growth in a deep dispatch chain),
17 * annotate via XTC_MUSTTAIL:
18 *
19 * return XTC_MUSTTAIL fn(args);
20 *
21 * - GCC's `__attribute__((musttail))` (15+) and Clang's
22 * `[[clang::musttail]]` are honored. On older toolchains
23 * we fall back to `__attribute__((always_inline))` of a
24 * helper that returns directly.
25 *
26 * Validation:
27 * scripts/check-tailcalls.sh disassembles the static lib
28 * and confirms each annotated site is a `jmp` not a `call`.
29 * Run via `make check-tailcalls`.
30 *
31 * When TCO matters in xtc:
32 * - State-machine dispatch: handler returning a tail-call to
33 * the next state's handler (e.g. parse trees).
34 * - Scheduler dispatch: loop's task-step jumping into the
35 * coroutine entry without growing the loop's stack.
36 * - Lock-free fast paths where one inline helper jumps to
37 * the slow path on miss.
38 */
39
40#ifndef XTC_TAILCALL_H
41#define XTC_TAILCALL_H
42
43/* musttail is a *statement* attribute, not a function attribute.
44 * Both clang's `[[clang::musttail]]` and gcc-15's
45 * `__attribute__((musttail))` are accepted as statement attributes,
46 * but only in compilers that parse C2x bracket attributes (clang)
47 * or have GCC 15's extension. In strict C11 mode -- which xtc uses --
48 * we fall back to a no-op and rely on the optimizer. The
49 * `scripts/check-tailcalls.sh` validator inspects the .o to confirm
50 * `jmp` was emitted regardless. */
51/* XTC_MUSTTAIL is a marker; it's prefixed to a function call inside
52 * a return statement to signal intent. In gcc 15+ and clang's C2x
53 * mode the attribute can be attached to the return statement itself
54 * (`__attribute__((musttail)) return foo();`) but the syntactic
55 * position varies enough across toolchains that we keep the macro
56 * as a no-op universally and rely on:
57 * 1. the -O2 optimizer doing TCO when it can, and
58 * 2. scripts/check-tailcalls.sh validating the .o emitted `jmp`.
59 * When compiler enforcement matters more than convenience, callers
60 * can use the explicit form directly. */
61#define XTC_MUSTTAIL /* no-op marker; see check-tailcalls.sh */
62
63/* Marker macro for the validator script: annotated call sites
64 * become a #pragma comment that survives into the disassembly's
65 * line metadata. */
66#if defined(XTC_TAILCALL_MARK_SITES)
67# define XTC_TAIL_CALL(expr) \
68 (__extension__ ({ \
69 _Pragma("message \"xtc-tailcall-marker\""); \
70 XTC_MUSTTAIL expr; \
71 }))
72#else
73# define XTC_TAIL_CALL(expr) (XTC_MUSTTAIL expr)
74#endif
75
76#endif /* XTC_TAILCALL_H */