Files
psxrecomp/runtime/include/overlay_backend.h
T
Matthew Stanley c2a3f6ad79 overlay: add tcc tier (toolchain-free fallback) replacing sljit; extract overlay_backend
Compiler-neutral tier-selection policy extracted from the mis-named
overlay_sljit.{c,h} into NEW overlay_backend.{c,h} (OverlayBackend enum +
resolve/name/active). overlay_sljit.{c,h} is now just the deprecated emitter.

New tcc tier. gcc and tcc run the IDENTICAL pipeline (recompiler -> C ->
compiler -> DLL -> loader); only the compiler binary differs, so both map to the
autocompile-spawn provider (code_provider.c) and the COMMAND is chosen by the
resolved backend (main.cpp). compile_overlays.py gains --compiler gcc|tcc: tcc
writes a separate tcc/ cache namespace, BOM-strips the C + a copy of the include
headers (tcc 0.9.27 can't skip a UTF-8 BOM), and uses tcc's built-in linker.

Backends (overlay_backend): auto (gcc if a gcc TOOLCHAIN is present, else tcc --
was sljit), gcc, tcc, auto-no-gcc (dev/test: force tcc even with gcc present, to
exercise the toolchain-less user path), sljit (DEPRECATED, gated off, lowest).
Priority: static > gcc shard > tcc shard > sljit(off) > interp. The loader scans
gcc/ then tcc/ and dedups by region+crc (filename) so a gcc shard always wins a
tie.

Self-contained tcc: with no explicit overlay_autocompile_cmd_tcc, the runtime
CONSTRUCTS the tcc command from a toolchain bundled beside the exe
(<exe>/overlay_toolchain/: embedded python + tcc + recompiler + compile_overlays.py
+ runtime headers) -- no system python or gcc needed. config_loader gains
overlay_autocompile_cmd_tcc (a dev override). autocompile cmd buffers enlarged for
the constructed path-heavy command.

Compilation stays OFF the dispatch/render thread (off-process autocompile
subprocess, same model as gcc); the main thread only spawns it and dlopens the
finished DLL.

Validated: MMX6 with overlay_backend=auto-no-gcc fills the tcc/ namespace live
from the bundled toolchain and plays through save-load + gameplay -- the exact
path the sljit tier softlocked on. The gcc path is untouched.

Runtime-only, no regen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 13:10:57 -07:00

58 lines
2.6 KiB
C

#ifndef OVERLAY_BACKEND_H
#define OVERLAY_BACKEND_H
/* overlay_backend — compiler-NEUTRAL overlay tier-selection policy.
*
* This is NOT specific to any one producer. It decides which native overlay
* tier fills a gap, in priority order:
*
* static > gcc shard > tcc shard > sljit shard (deprecated) > interp
*
* - gcc: spawn-gcc -> overlay DLL. The developer / production "holy grail"
* (best-optimized; the shards shipped in releases).
* - tcc: spawn-tcc -> overlay DLL. Bundled, toolchain-free user fallback that
* fills regions the shipped gcc cache misses on a machine without gcc.
* - sljit: in-process JIT. DEPRECATED (it mis-compiled; gated off) — kept only
* until it is removed, and always the lowest native priority.
*
* gcc and tcc go through the IDENTICAL pipeline (recompiler -> C -> compiler ->
* DLL -> loader); they differ only in the compiler binary the autocompile
* command runs. So both map to the same in-runtime "code provider" (the
* autocompile spawn) — see code_provider.c — and which compiler runs is chosen
* here by the resolved backend.
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
OVERLAY_BACKEND_AUTO = 0, /* gcc if a gcc toolchain is present, else tcc */
OVERLAY_BACKEND_GCC = 1, /* force spawn-gcc->DLL (dev / production shards) */
OVERLAY_BACKEND_SLJIT = 2, /* DEPRECATED in-process sljit producer (gated off) */
OVERLAY_BACKEND_TCC = 3, /* spawn-tcc->DLL (bundled, toolchain-free fallback) */
OVERLAY_BACKEND_AUTO_NO_GCC = 4 /* dev/test: resolve like AUTO but pretend no gcc toolchain
* (gcc shards still LOAD; gaps fill via tcc) — simulate a
* toolchain-less user box on a dev machine. */
} OverlayBackend;
/* Resolve the effective backend once at startup. `gcc_toolchain_available` is 1
* when a gcc toolchain is actually reachable AND a compile command is wired (a
* real dev/production box). Precedence: env PSX_OVERLAY_BACKEND > game.toml
* [runtime] overlay_backend (`cfg`) > AUTO. AUTO -> gcc if the toolchain is
* present, else tcc. AUTO_NO_GCC -> tcc regardless (the simulate-user mode).
* The result is cached + logged. */
OverlayBackend overlay_backend_resolve(const char *cfg, int gcc_toolchain_available);
/* The cached resolution (OVERLAY_BACKEND_AUTO until resolve() runs). */
OverlayBackend overlay_backend_active(void);
/* "auto" | "gcc" | "sljit" | "tcc" | "auto-no-gcc". */
const char *overlay_backend_name(OverlayBackend b);
#ifdef __cplusplus
}
#endif
#endif /* OVERLAY_BACKEND_H */