kit

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

commit 805d7438efb536c528cd923294e4aa8fe7b7ef1f
parent 84391328a6db0a49e399438b7899ab18724949f5
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 25 May 2026 13:07:13 -0700

build: isolate hosted driver environment

Diffstat:
MMakefile | 41++++++++++++++++++++++++++++-------------
Mdriver/driver.h | 181+------------------------------------------------------------------------------
Mdriver/env.c | 2++
Adriver/env.h | 190+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/lib_deps.allowlist | 10+---------
Mtest/test.mk | 30+++++++++++++++---------------
6 files changed, 238 insertions(+), 216 deletions(-)

diff --git a/Makefile b/Makefile @@ -10,20 +10,31 @@ HOST_OPTFLAGS ?= -O1 HOST_SYSROOT_CFLAGS = -isysroot $(SYSROOT) HOST_SYSROOT_LDFLAGS = -isysroot $(SYSROOT) -CFLAGS_COMMON = $(HOST_OPTFLAGS) -std=c11 -Wpedantic -Wall -Wextra -Werror $(HOST_SYSROOT_CFLAGS) +CFLAGS_COMMON = $(HOST_OPTFLAGS) -std=c11 -Wpedantic -Wall -Wextra -Werror +HOST_CFLAGS = $(CFLAGS_COMMON) $(HOST_SYSROOT_CFLAGS) DEPFLAGS = -MMD -MP +# Freestanding objects must not see host SDK/libc headers. Homebrew clang can +# also inject a configured sysroot before command-line flags; use +# --no-default-config when the selected compiler supports it, but omit it for +# bootstrap stages where $(CC) is cfree cc. +FREESTANDING_CONFIG_CFLAGS = $(shell $(CC) --no-default-config -x c -E /dev/null >/dev/null 2>&1 && printf '%s' --no-default-config) +FREESTANDING_CFLAGS = $(CFLAGS_COMMON) $(FREESTANDING_CONFIG_CFLAGS) -ffreestanding -nostdinc -Irt/include + # libcfree: written in C11 freestanding; sees both src/ (internal) and # include/ (its own public surface). -LIB_CFLAGS = $(CFLAGS_COMMON) -ffreestanding -Iinclude -Isrc - -# Driver: hosted CLI binary. Sees only the public include/ tree — that's -# what makes the driver the first consumer of libcfree. -Ilang lets `cc` reach -# the C frontend's public header ("c/c.h") for the JIT REPL; it deliberately -# does NOT get -Isrc, so internal headers ("core/...", "link/...") are -# unreachable from the driver. -DRIVER_CFLAGS = $(CFLAGS_COMMON) -Iinclude -Ilang +LIB_CFLAGS = $(FREESTANDING_CFLAGS) -Iinclude -Isrc + +# Driver: mostly freestanding CLI binary. Sees only the public include/ tree — +# that's what makes the driver the first consumer of libcfree. -Ilang lets `cc` +# reach the C frontend's public header ("c/c.h") for the JIT REPL; it +# deliberately does NOT get -Isrc, so internal headers ("core/...", "link/...") +# are unreachable from the driver. driver/env.c is the sole hosted OS/libc +# adapter and is compiled with DRIVER_ENV_CFLAGS below. +DRIVER_CFLAGS = $(FREESTANDING_CFLAGS) -Iinclude -Ilang +DRIVER_ENV_CFLAGS = $(HOST_CFLAGS) -Iinclude -Ilang +TEST_HOST_CFLAGS = $(HOST_CFLAGS) -Iinclude -Ilang include mk/config.mk @@ -187,18 +198,18 @@ $(BUILD_DIR)/lib/api/lang_registry.o: src/api/lang_registry.c Makefile $(BUILD_DIR)/lang/cpp/%.o: lang/cpp/%.c Makefile @mkdir -p $(dir $@) - $(CC) $(CFLAGS_COMMON) -ffreestanding -Iinclude -Ilang/cpp $(DEPFLAGS) -c $< -o $@ + $(CC) $(FREESTANDING_CFLAGS) -Iinclude -Ilang/cpp $(DEPFLAGS) -c $< -o $@ # The C frontend includes the lexer and preprocessor headers (pp/pp.h, # lex/lex.h) which now live under lang/cpp/, and cpp_support.h is the # shared substrate. So lang/c objects build with -Ilang/cpp -Ilang/c. $(BUILD_DIR)/lang/c/%.o: lang/c/%.c Makefile @mkdir -p $(dir $@) - $(CC) $(CFLAGS_COMMON) -ffreestanding -Iinclude -Ilang/cpp -Ilang/c $(DEPFLAGS) -c $< -o $@ + $(CC) $(FREESTANDING_CFLAGS) -Iinclude -Ilang/cpp -Ilang/c $(DEPFLAGS) -c $< -o $@ $(BUILD_DIR)/lang/wasm/%.o: lang/wasm/%.c Makefile @mkdir -p $(dir $@) - $(CC) $(CFLAGS_COMMON) -ffreestanding -Iinclude -Ilang/wasm $(DEPFLAGS) -c $< -o $@ + $(CC) $(FREESTANDING_CFLAGS) -Iinclude -Ilang/wasm $(DEPFLAGS) -c $< -o $@ $(BUILD_DIR)/lib/%.o: src/%.S Makefile @mkdir -p $(dir $@) @@ -208,9 +219,13 @@ $(BUILD_DIR)/driver/%.o: driver/%.c Makefile @mkdir -p $(dir $@) $(CC) $(DRIVER_CFLAGS) $(DEPFLAGS) -c $< -o $@ +$(BUILD_DIR)/driver/env.o: driver/env.c Makefile + @mkdir -p $(dir $@) + $(CC) $(DRIVER_ENV_CFLAGS) $(DEPFLAGS) -c $< -o $@ + $(BUILD_DIR)/lang/toy/%.o: lang/toy/%.c Makefile @mkdir -p $(dir $@) - $(CC) $(CFLAGS_COMMON) -ffreestanding -Iinclude -Ilang/toy $(DEPFLAGS) -c $< -o $@ + $(CC) $(FREESTANDING_CFLAGS) -Iinclude -Ilang/toy $(DEPFLAGS) -c $< -o $@ include rt/Makefile diff --git a/driver/driver.h b/driver/driver.h @@ -6,6 +6,8 @@ #include <cfree/jit.h> #include <cfree/dbg.h> +#include "env.h" + /* The cfree CLI driver. Multi-call binary: dispatches to one of seven tool * front-ends by argv[0]'s basename, falling back to argv[1] (e.g. * `cfree cc ...`). The driver only depends on libcfree's public API @@ -77,61 +79,6 @@ int driver_is_help_flag(const char *arg); * help request — the convention is "no args means show help". */ int driver_argv_wants_help(int argc, char **argv, int accept_short_h); -/* Shared host environment used by every tool that calls into libcfree. - * driver_env_init wires up the libc-backed heap, the stderr diag sink, and - * a POSIX file_io implementation (open/read/write on real paths). It is - * the single piece of glue that turns "the host" into a CfreeContext. - * - * The execmem / dbg_os / jit_tls vtables that used to live on CfreeEnv now - * live on CfreeJitHost / CfreeDbgHost. They are still constructed here so - * that one DriverEnv covers every libcfree-using tool, but they're handed - * to libcfree per-call via the appropriate host struct. */ -typedef struct DriverEnv { - CfreeHeap *heap; - CfreeDiagSink *diag; - CfreeFileIO file_io; - const CfreeExecMem *execmem; - const CfreeDbgOs *dbg_os; /* NULL unless `cfree dbg` paths run */ - const CfreeJitTls *jit_tls; /* NULL unless `cfree run` w/ TLV paths run */ - const CfreeMetrics *metrics; /* optional scoped metrics sink */ - int64_t now; /* unix seconds; -1 = unknown */ -} DriverEnv; - -void driver_env_init(DriverEnv *); -void driver_env_fini(DriverEnv *); - -/* Build a CfreeContext value pointing at the DriverEnv's heap/diag/file_io - * vtables. The returned value can be passed by const-pointer to any - * libcfree entry that takes `const CfreeContext *`. */ -CfreeContext driver_env_to_context(const DriverEnv *); - -/* Build a CfreeJitHost from the DriverEnv (execmem + tls). The returned - * struct holds borrowed pointers to vtables owned by g_execmem_posix / - * g_jit_tls_posix; callers must not outlive driver_env_fini. */ -CfreeJitHost driver_env_to_jit_host(const DriverEnv *); - -/* Build a CfreeDbgHost from the DriverEnv (dbg_os). */ -CfreeDbgHost driver_env_to_dbg_host(const DriverEnv *); - -/* Tells the stderr diag sink which compiler to use when resolving - * SrcLoc.file_id to a path. The driver_compiler_{new,free} helpers - * below already manage this; call this directly only when you hand a - * CfreeCompiler from outside those helpers (none today). */ -void driver_diag_set_compiler(CfreeCompiler *); - -/* Lifecycle helpers around cfree_compiler_{new,free}. Identical to the - * raw entries except they register the C / TOY / WASM frontends and - * register the active compiler with the stderr diag sink so diagnostics - * resolve loc.file_id to its registered path. Returns CFREE_OK on - * success; on failure *out is NULL. */ -CfreeStatus driver_compiler_new(CfreeTarget, const CfreeContext *, - CfreeCompiler **out); -void driver_compiler_free(CfreeCompiler *); - -/* Default target used by tools that don't expose a target-selection flag - * yet. v1: native-looking host target (chosen at compile time). */ -CfreeTarget driver_host_target(void); - /* Parse a target triple string (`<arch>[-<vendor>]-<os>[-<env>]`) into a * CfreeTarget. Recognized arches: x86_64/amd64, i386/i486/i586/i686, aarch64/ * arm64, arm/armv7, riscv64, riscv32, wasm32, wasm64. Recognized OSes (scanned @@ -146,128 +93,4 @@ int driver_target_from_triple(const char *triple, CfreeTarget *out); * nonzero when `buf` is too small. */ int driver_target_to_triple(CfreeTarget target, char *buf, size_t cap); -/* ---------------------------------------------------------------------- - * Host-shim helpers - * - * driver/env.c is the only TU in the driver allowed to depend on libc - * facilities that issue syscalls or touch host state — stdio, malloc, - * POSIX I/O, environment, time. Pure platform-independent libc (e.g. - * <string.h>, <ctype.h>, <stdint.h>, <stddef.h>) is fine in any TU. - * The shims below exist primarily for the syscall-shaped surface; other - * TUs may also call them for consistency. - * ---------------------------------------------------------------------- */ - -/* String predicates and lookups. driver_streq / driver_strneq return - * non-zero when the strings (or first n bytes) match — sense-flipped - * from libc's strcmp so call sites read naturally. */ -int driver_streq(const char *a, const char *b); -int driver_strneq(const char *a, const char *b, size_t n); -size_t driver_strlen(const char *s); -const char *driver_strchr(const char *s, int c); -const char *driver_basename(const char *path); -int driver_has_suffix(const char *s, const char *suffix); - -/* Memory. Allocations route through DriverEnv.heap; release returns the - * size used at allocation (so the heap implementation can track usage). */ -void *driver_alloc(DriverEnv *, size_t); -void *driver_alloc_zeroed(DriverEnv *, size_t); -void driver_free(DriverEnv *, void *p, size_t); -void driver_memcpy(void *dst, const void *src, size_t n); - -/* Opens a Writer that writes to stdout (fd 1). close frees the struct but - * does not close the fd. */ -CfreeWriter *driver_stdout_writer(DriverEnv *); - -/* Test whether `path` names an existing filesystem entry (any type). - * Returns nonzero on existence, zero otherwise. Used by library-path - * resolution; intentionally distinct from read_all so candidate-search - * loops don't slurp file contents on a hit. */ -int driver_path_exists(const char *path); - -/* Read a path's last modification time in nanoseconds since the Unix epoch. - * Returns 0 on success, nonzero on stat failure. */ -int driver_path_mtime_ns(const char *path, int64_t *out); - -/* Create a directory and any missing parents. Returns 0 on success. */ -int driver_mkdir_p(DriverEnv *, const char *path); - -/* Set a linked binary output's final mode according to the active umask. - * Returns 0 on success, nonzero on chmod failure. */ -int driver_mark_executable_output(const char *path); - -/* Diagnostic printing to host stderr. Format is `"<tool>: <fmt>\n"`. */ -void driver_errf(const char *tool, const char *fmt, ...); - -/* Raw hosted stderr log. Used by optional metrics so libcfree stays callback- - * only and freestanding. */ -void driver_logf(const char *fmt, ...); - -/* Formatted output to stdout. */ -void driver_printf(const char *fmt, ...); - -/* Monotonic host time in nanoseconds, or 0 if unavailable. */ -uint64_t driver_now_ns(void); - -/* Lookup a process environment variable; returns NULL if unset. The returned - * pointer aliases libc-owned storage and is valid until the next setenv/ - * putenv from any caller. */ -const char *driver_getenv(const char *name); - -/* Read all of stdin into a freshly-allocated buffer. On success returns 1 - * and stores the buffer/size in out_data/out_size; the caller frees via - * driver_free(env, *out_data, *out_size). Returns 0 on read failure or - * allocation failure. */ -int driver_read_stdin(DriverEnv *, uint8_t **out_data, size_t *out_size); - -/* Open a temporary file in $VISUAL, then $EDITOR, then vi. `suffix` should - * include the leading dot when a language-specific extension is useful. - * On success, returns the edited bytes in a freshly allocated buffer that the - * caller frees with driver_free(env, *out_data, *out_size). */ -int driver_edit_temp(DriverEnv *, const char *suffix, const uint8_t *initial, - size_t initial_size, uint8_t **out_data, size_t *out_size); - -/* Path-shaped input loader. Wraps env.file_io.read_all so each tool can - * convert a list of paths to a list of CfreeSlice without re-implementing - * load/release/error bookkeeping. `loaded` is set to 1 on success; release is - * idempotent and does nothing when loaded is already 0. driver_load_bytes - * fills `in.name = path` plus the loaded data/len; driver_release_bytes hands - * the buffer back through file_io.release. On failure an error is emitted via - * driver_errf using the supplied tool tag. */ -typedef struct DriverLoad { - CfreeFileData fd; - int loaded; -} DriverLoad; - -int driver_load_bytes(const CfreeFileIO *, const char *tool, const char *path, - DriverLoad *out, CfreeSlice *in); -void driver_release_bytes(const CfreeFileIO *, DriverLoad *); - -/* Read one line from stdin into `buf` (cap >= 2). Strips the trailing - * newline and NUL-terminates. Returns the line length on success, 0 at - * EOF (with buf[0]='\0'), -1 on read error, or -2 when the read was - * interrupted by a signal (caller should print a fresh prompt and - * retry). Over-long lines are truncated to cap-1 bytes; the remainder - * up to the next newline is consumed silently. */ -int driver_read_line(char *buf, size_t cap); - -/* Flush the host stdout. The dbg REPL prompt has no trailing newline, so - * without an explicit flush the prompt stays buffered until the next - * line of output. */ -void driver_flush_stdout(void); - -/* Install / restore a SIGINT handler. While installed, SIGINT runs `cb(user)` - * synchronously (so `cb` must be async-signal safe). Used by `dbg` to - * forward Ctrl-C into cfree_jit_session_interrupt while the worker is - * running, and to restore SIG_DFL while sitting at the REPL prompt so - * Ctrl-C terminates the program normally. Returns 0 on success. */ -int driver_install_sigint(void (*cb)(void *), void *user); -void driver_restore_sigint(void); - -/* Host-symbol resolver for JIT extern_resolver. Looks up `name` via - * dlsym(RTLD_DEFAULT, ...) on POSIX hosts, returning NULL on miss. Stateless; - * `user` is ignored and may be NULL. Wired into `cfree run` so JITed code - * can call libc symbols (printf, malloc, ...) without an explicit linker - * step. */ -void *driver_dlsym_resolver(void *user, CfreeSlice name); - #endif diff --git a/driver/env.c b/driver/env.c @@ -36,6 +36,8 @@ #include <libkern/OSCacheControl.h> #endif +#include "env.h" + #include "driver.h" /* Dual-mapping back-ends for strict W^X. Picks per-platform: diff --git a/driver/env.h b/driver/env.h @@ -0,0 +1,190 @@ +#ifndef CFREE_DRIVER_ENV_H +#define CFREE_DRIVER_ENV_H + +#include <stddef.h> +#include <stdint.h> + +#include <cfree/compile.h> +#include <cfree/core.h> +#include <cfree/dbg.h> +#include <cfree/jit.h> + +/* Shared host environment used by every tool that calls into libcfree. + * driver_env_init wires up the libc-backed heap, the stderr diag sink, and + * a POSIX file_io implementation (open/read/write on real paths). It is + * the single piece of glue that turns "the host" into a CfreeContext. + * + * The execmem / dbg_os / jit_tls vtables that used to live on CfreeEnv now + * live on CfreeJitHost / CfreeDbgHost. They are still constructed here so + * that one DriverEnv covers every libcfree-using tool, but they're handed + * to libcfree per-call via the appropriate host struct. */ +typedef struct DriverEnv { + CfreeHeap *heap; + CfreeDiagSink *diag; + CfreeFileIO file_io; + const CfreeExecMem *execmem; + const CfreeDbgOs *dbg_os; /* NULL unless `cfree dbg` paths run */ + const CfreeJitTls *jit_tls; /* NULL unless `cfree run` w/ TLV paths run */ + const CfreeMetrics *metrics; /* optional scoped metrics sink */ + int64_t now; /* unix seconds; -1 = unknown */ +} DriverEnv; + +void driver_env_init(DriverEnv *); +void driver_env_fini(DriverEnv *); + +/* Build a CfreeContext value pointing at the DriverEnv's heap/diag/file_io + * vtables. The returned value can be passed by const-pointer to any + * libcfree entry that takes `const CfreeContext *`. */ +CfreeContext driver_env_to_context(const DriverEnv *); + +/* Build a CfreeJitHost from the DriverEnv (execmem + tls). The returned + * struct holds borrowed pointers to vtables owned by g_execmem_posix / + * g_jit_tls_posix; callers must not outlive driver_env_fini. */ +CfreeJitHost driver_env_to_jit_host(const DriverEnv *); + +/* Build a CfreeDbgHost from the DriverEnv (dbg_os). */ +CfreeDbgHost driver_env_to_dbg_host(const DriverEnv *); + +/* Tells the stderr diag sink which compiler to use when resolving + * SrcLoc.file_id to a path. The driver_compiler_{new,free} helpers + * below already manage this; call this directly only when you hand a + * CfreeCompiler from outside those helpers (none today). */ +void driver_diag_set_compiler(CfreeCompiler *); + +/* Lifecycle helpers around cfree_compiler_{new,free}. Identical to the + * raw entries except they register the active compiler with the stderr + * diag sink so diagnostics resolve loc.file_id to its registered path. + * Returns CFREE_OK on success; on failure *out is NULL. */ +CfreeStatus driver_compiler_new(CfreeTarget, const CfreeContext *, + CfreeCompiler **out); +void driver_compiler_free(CfreeCompiler *); + +/* Default target used by tools that don't expose a target-selection flag + * yet. v1: native-looking host target (chosen at compile time). */ +CfreeTarget driver_host_target(void); + +/* ---------------------------------------------------------------------- + * Host-shim helpers + * + * driver/env.c is the only TU in the driver allowed to depend on libc + * facilities that issue syscalls or touch host state -- host stdio, malloc, + * POSIX I/O, environment, time. Other driver TUs are compiled freestanding + * against rt/include plus libcfree's public headers. The shims below exist + * primarily for the syscall-shaped surface; other TUs may also call them for + * consistency. + * ---------------------------------------------------------------------- */ + +/* String predicates and lookups. driver_streq / driver_strneq return + * non-zero when the strings (or first n bytes) match -- sense-flipped + * from libc's strcmp so call sites read naturally. */ +int driver_streq(const char *a, const char *b); +int driver_strneq(const char *a, const char *b, size_t n); +size_t driver_strlen(const char *s); +const char *driver_strchr(const char *s, int c); +const char *driver_basename(const char *path); +int driver_has_suffix(const char *s, const char *suffix); + +/* Memory. Allocations route through DriverEnv.heap; release returns the + * size used at allocation (so the heap implementation can track usage). */ +void *driver_alloc(DriverEnv *, size_t); +void *driver_alloc_zeroed(DriverEnv *, size_t); +void driver_free(DriverEnv *, void *p, size_t); +void driver_memcpy(void *dst, const void *src, size_t n); + +/* Opens a Writer that writes to stdout. close frees the struct but does + * not close stdout. */ +CfreeWriter *driver_stdout_writer(DriverEnv *); + +/* Test whether `path` names an existing filesystem entry (any type). + * Returns nonzero on existence, zero otherwise. Used by library-path + * resolution; intentionally distinct from read_all so candidate-search + * loops don't slurp file contents on a hit. */ +int driver_path_exists(const char *path); + +/* Read a path's last modification time in nanoseconds since the Unix epoch. + * Returns 0 on success, nonzero on stat failure. */ +int driver_path_mtime_ns(const char *path, int64_t *out); + +/* Create a directory and any missing parents. Returns 0 on success. */ +int driver_mkdir_p(DriverEnv *, const char *path); + +/* Set a linked binary output's final mode according to the active umask. + * Returns 0 on success, nonzero on chmod failure. */ +int driver_mark_executable_output(const char *path); + +/* Diagnostic printing to host stderr. Format is `"<tool>: <fmt>\n"`. */ +void driver_errf(const char *tool, const char *fmt, ...); + +/* Raw hosted stderr log. Used by optional metrics so libcfree stays callback- + * only and freestanding. */ +void driver_logf(const char *fmt, ...); + +/* Formatted output to stdout. */ +void driver_printf(const char *fmt, ...); + +/* Monotonic host time in nanoseconds, or 0 if unavailable. */ +uint64_t driver_now_ns(void); + +/* Lookup a process environment variable; returns NULL if unset. The returned + * pointer aliases libc-owned storage and is valid until the next setenv/ + * putenv from any caller. */ +const char *driver_getenv(const char *name); + +/* Read all of stdin into a freshly-allocated buffer. On success returns 1 + * and stores the buffer/size in out_data/out_size; the caller frees via + * driver_free(env, *out_data, *out_size). Returns 0 on read failure or + * allocation failure. */ +int driver_read_stdin(DriverEnv *, uint8_t **out_data, size_t *out_size); + +/* Open a temporary file in $VISUAL, then $EDITOR, then vi. `suffix` should + * include the leading dot when a language-specific extension is useful. + * On success, returns the edited bytes in a freshly allocated buffer that the + * caller frees with driver_free(env, *out_data, *out_size). */ +int driver_edit_temp(DriverEnv *, const char *suffix, const uint8_t *initial, + size_t initial_size, uint8_t **out_data, size_t *out_size); + +/* Path-shaped input loader. Wraps env.file_io.read_all so each tool can + * convert a list of paths to a list of CfreeSlice without re-implementing + * load/release/error bookkeeping. `loaded` is set to 1 on success; release is + * idempotent and does nothing when loaded is already 0. driver_load_bytes + * fills `in.name = path` plus the loaded data/len; driver_release_bytes hands + * the buffer back through file_io.release. On failure an error is emitted via + * driver_errf using the supplied tool tag. */ +typedef struct DriverLoad { + CfreeFileData fd; + int loaded; +} DriverLoad; + +int driver_load_bytes(const CfreeFileIO *, const char *tool, const char *path, + DriverLoad *out, CfreeSlice *in); +void driver_release_bytes(const CfreeFileIO *, DriverLoad *); + +/* Read one line from stdin into `buf` (cap >= 2). Strips the trailing + * newline and NUL-terminates. Returns the line length on success, 0 at + * EOF (with buf[0]='\0'), -1 on read error, or -2 when the read was + * interrupted by a signal (caller should print a fresh prompt and + * retry). Over-long lines are truncated to cap-1 bytes; the remainder + * up to the next newline is consumed silently. */ +int driver_read_line(char *buf, size_t cap); + +/* Flush the host stdout. The dbg REPL prompt has no trailing newline, so + * without an explicit flush the prompt stays buffered until the next + * line of output. */ +void driver_flush_stdout(void); + +/* Install / restore a SIGINT handler. While installed, SIGINT runs `cb(user)` + * synchronously (so `cb` must be async-signal safe). Used by `dbg` to + * forward Ctrl-C into cfree_jit_session_interrupt while the worker is + * running, and to restore SIG_DFL while sitting at the REPL prompt so + * Ctrl-C terminates the program normally. Returns 0 on success. */ +int driver_install_sigint(void (*cb)(void *), void *user); +void driver_restore_sigint(void); + +/* Host-symbol resolver for JIT extern_resolver. Looks up `name` via + * dlsym(RTLD_DEFAULT, ...) on POSIX hosts, returning NULL on miss. Stateless; + * `user` is ignored and may be NULL. Wired into `cfree run` so JITed code + * can call libc symbols (printf, malloc, ...) without an explicit linker + * step. */ +void *driver_dlsym_resolver(void *user, CfreeSlice name); + +#endif diff --git a/test/lib_deps.allowlist b/test/lib_deps.allowlist @@ -1,11 +1,5 @@ -___memcpy_chk -___memset_chk -___snprintf_chk ___stack_chk_fail ___stack_chk_guard -_bzero -_fma -_fmaf _longjmp _memcmp _memcpy @@ -13,9 +7,7 @@ _memmove _memset _qsort _setjmp -_sqrt +_snprintf _strcmp _strlen -_strncmp -_strstr _strtod diff --git a/test/test.mk b/test/test.mk @@ -68,7 +68,7 @@ test-ar: $(AR_TEST_BIN) $(AR_TEST_BIN): test/ar_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) test/ar_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) test/ar_test.c $(LIB_AR) -o $@ test-ar-driver: bin @CFREE=$(abspath $(BIN)) test/ar/run.sh @@ -93,7 +93,7 @@ test-dwarf: $(DWARF_TEST_BIN) $(DWARF_TEST_BIN): test/dwarf/dwarf_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/dwarf/dwarf_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/dwarf/dwarf_test.c $(LIB_AR) -o $@ # DWARF producer self-roundtrip unit test. Drives Debug directly, calls # debug_emit, asserts the produced sections have valid DWARF 5 structure @@ -107,7 +107,7 @@ test-debug: $(DEBUG_TEST_BIN) $(DEBUG_TEST_BIN): test/debug/roundtrip_unit.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/debug/roundtrip_unit.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/debug/roundtrip_unit.c $(LIB_AR) -o $@ # aa64 ISA descriptor-table unit test (doc/ASM.md phase 2). Covers # every AA64Format the table maps and the alias-precedence invariant @@ -122,11 +122,11 @@ test-isa: $(AA64_ISA_TEST_BIN) $(RV64_DECODE_TEST_BIN) $(AA64_ISA_TEST_BIN): test/arch/aa64_isa_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/arch/aa64_isa_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/arch/aa64_isa_test.c $(LIB_AR) -o $@ $(RV64_DECODE_TEST_BIN): test/arch/rv64_decode_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/arch/rv64_decode_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/arch/rv64_decode_test.c $(LIB_AR) -o $@ # test-emu: emulator unit tests. The rv64 lane builds a tiny in-memory rv64 # ELF and asserts the lifted/JIT path exits through the syscall handler with @@ -138,7 +138,7 @@ test-emu: $(EMU_RV64_TEST_BIN) $(EMU_RV64_TEST_BIN): test/emu/rv64_smoke_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/emu/rv64_smoke_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/emu/rv64_smoke_test.c $(LIB_AR) -o $@ CG_API_TEST_BIN = build/test/cg_api_test CG_SWITCH_TEST_BIN = build/test/cg_switch_test @@ -151,15 +151,15 @@ test-cg-api: $(CG_API_TEST_BIN) $(CG_SWITCH_TEST_BIN) $(ABI_CLASSIFY_TEST_BIN) $(CG_API_TEST_BIN): test/api/cg_type_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/api/cg_type_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/api/cg_type_test.c $(LIB_AR) -o $@ $(CG_SWITCH_TEST_BIN): test/api/cg_switch_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/api/cg_switch_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/api/cg_switch_test.c $(LIB_AR) -o $@ $(ABI_CLASSIFY_TEST_BIN): test/api/abi_classify_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/api/abi_classify_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/api/abi_classify_test.c $(LIB_AR) -o $@ test-toy: bin @CFREE=$(abspath $(BIN)) test/toy/run.sh @@ -176,7 +176,7 @@ test-aa64-inline: $(AA64_INLINE_TEST_BIN) $(AA64_INLINE_TEST_BIN): test/arch/aa64_inline_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/arch/aa64_inline_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/arch/aa64_inline_test.c $(LIB_AR) -o $@ # rv64 inline-asm backend unit test — parallel to test-aa64-inline. # Drives rv_asm_block directly with hand-rolled Operand arrays and @@ -188,7 +188,7 @@ test-rv64-inline: $(RV64_INLINE_TEST_BIN) $(RV64_INLINE_TEST_BIN): test/arch/rv64_inline_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/arch/rv64_inline_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/arch/rv64_inline_test.c $(LIB_AR) -o $@ # rv64 JIT smoke test. Builds a tiny rv64 ELF .o in memory, runs it # through cfree_link_session in JIT-output mode, and skips native execution @@ -206,7 +206,7 @@ test-rv64-jit: $(RV64_JIT_TEST_BIN) $(RV64_JIT_TEST_BIN): test/link/rv64_jit_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) test/link/rv64_jit_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) test/link/rv64_jit_test.c $(LIB_AR) -o $@ # x86_64 peer of test-aa64-inline (doc/INLINEASM.md). Drives x_asm_block # (CGTarget vtable) directly with hand-rolled Operand arrays and asserts @@ -219,7 +219,7 @@ test-x64-inline: $(X64_INLINE_TEST_BIN) $(X64_INLINE_TEST_BIN): test/arch/x64_inline_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/arch/x64_inline_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/arch/x64_inline_test.c $(LIB_AR) -o $@ X64_DBG_TEST_BIN = build/test/x64_dbg_test @@ -228,7 +228,7 @@ test-x64-dbg: $(X64_DBG_TEST_BIN) $(X64_DBG_TEST_BIN): test/arch/x64_dbg_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/arch/x64_dbg_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/arch/x64_dbg_test.c $(LIB_AR) -o $@ RT_HEADER_TEST_TARGETS = \ aarch64-linux-gnu \ @@ -367,7 +367,7 @@ test-opt: bin $(OPT_TEST_BIN) $(OPT_TEST_BIN): test/opt/opt_test.c $(LIB_AR) @mkdir -p $(dir $@) - $(CC) $(DRIVER_CFLAGS) -Isrc test/opt/opt_test.c $(LIB_AR) -o $@ + $(CC) $(TEST_HOST_CFLAGS) -Isrc test/opt/opt_test.c $(LIB_AR) -o $@ test-parse: lib rt $(PARSE_RUNNER) $(ROUNDTRIP_BIN) $(LINK_EXE_RUNNER) $(JIT_RUNNER) bash test/parse/run.sh