kit

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

commit c2f9575135399104652d2be75470b74f696cf9a1
parent ed38bc5b19bb021847602b73dd62d26f79772cf9
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 25 May 2026 16:51:56 -0700

Add compile-time component knobs

Diffstat:
MMakefile | 174+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mdriver/main.c | 223+++++++++++++++++++++++++++++++++++++------------------------------------------
Minclude/cfree/config.h | 54+++++++++++++++++++++++++++++++++++++++++++++++-------
Mmk/config.mk | 26++++++++++++++++++++++++++
Asrc/api/config_stubs.c | 800+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/api/lang_registry.c | 13++++++-------
Msrc/api/object_detect.c | 9+++++++++
Msrc/api/object_file.c | 13++++---------
Dsrc/api/stubs.c | 18------------------
Msrc/arch/aa64/arch.c | 6+-----
Msrc/arch/cgtarget.c | 13+++++++++++--
Asrc/arch/dbg_stubs.c | 5+++++
Asrc/arch/disasm_stubs.c | 18++++++++++++++++++
Asrc/arch/dwarf.c | 16++++++++++++++++
Asrc/arch/emu_stubs.c | 3+++
Asrc/arch/link_stubs.c | 5+++++
Msrc/arch/rv64/arch.c | 6+-----
Msrc/arch/wasm/internal.h | 5++---
Msrc/arch/x64/arch.c | 6+-----
Msrc/core/config_assert.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Asrc/obj/archive_stubs.c | 23+++++++++++++++++++++++
Asrc/obj/emu_stubs.c | 3+++
Asrc/obj/link_stubs.c | 28++++++++++++++++++++++++++++
Msrc/obj/obj.h | 1-
Msrc/obj/registry.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++--------------
25 files changed, 1414 insertions(+), 214 deletions(-)

diff --git a/Makefile b/Makefile @@ -82,19 +82,23 @@ TEST_HOST_CFLAGS = $(HOST_CFLAGS) -Iinclude -Ilang include mk/config.mk -# Non-arch lib sources: everything under src/ except gated component -# directories/files. Shared arch/obj/abi infrastructure stays unconditional. -LIB_SRCS_NONARCH = $(shell find src -name '*.c' \ - -not -path 'src/arch/aa64/*' \ - -not -path 'src/arch/x64/*' \ - -not -path 'src/arch/rv64/*' \ - -not -path 'src/arch/wasm/*' \ - -not -path 'src/arch/c_target/*' \ - -not -path 'src/obj/elf/*' \ - -not -path 'src/obj/macho/*' \ - -not -path 'src/obj/coff/*' \ - -not -path 'src/opt/*' \ - -not -path 'src/abi/abi_*.c') +# Core lib sources. Optional subsystems, backend directories, object format +# directories, and ABI implementations are added below from their own groups. +LIB_SRCS_ABI_CORE = src/abi/abi.c src/abi/registry.c +LIB_SRCS_API_CORE = $(filter-out src/api/archive.c src/api/disasm.c \ + src/api/link.c src/api/stubs.c,$(wildcard src/api/*.c)) +LIB_SRCS_ARCH_CORE = $(filter-out src/arch/%_stubs.c,$(wildcard src/arch/*.c)) +LIB_SRCS_ASM_CORE = $(wildcard src/asm/*.c) +LIB_SRCS_CG_CORE = $(wildcard src/cg/*.c) +LIB_SRCS_CORE = $(wildcard src/core/*.c) +LIB_SRCS_OBJ_CORE = $(filter-out src/obj/%_stubs.c,$(wildcard src/obj/*.c)) +LIB_SRCS_NONARCH = $(LIB_SRCS_ABI_CORE) \ + $(LIB_SRCS_API_CORE) \ + $(LIB_SRCS_ARCH_CORE) \ + $(LIB_SRCS_ASM_CORE) \ + $(LIB_SRCS_CG_CORE) \ + $(LIB_SRCS_CORE) \ + $(LIB_SRCS_OBJ_CORE) LIB_SRCS_ARCH_AA64 = $(shell find src/arch/aa64 -name '*.c' 2>/dev/null) LIB_SRCS_ARCH_X64 = $(shell find src/arch/x64 -name '*.c' 2>/dev/null) @@ -106,12 +110,61 @@ LIB_SRCS_ARCH_AA64 := $(filter-out %/opt_coord.c,$(LIB_SRCS_ARCH_AA64)) LIB_SRCS_ARCH_X64 := $(filter-out %/opt_coord.c,$(LIB_SRCS_ARCH_X64)) LIB_SRCS_ARCH_RV64 := $(filter-out %/opt_coord.c,$(LIB_SRCS_ARCH_RV64)) endif +ifneq ($(CFREE_DISASM_ENABLED),1) +LIB_SRCS_ARCH_AA64 := $(filter-out %/disasm.c,$(LIB_SRCS_ARCH_AA64)) +LIB_SRCS_ARCH_X64 := $(filter-out %/disasm.c,$(LIB_SRCS_ARCH_X64)) +LIB_SRCS_ARCH_RV64 := $(filter-out %/disasm.c,$(LIB_SRCS_ARCH_RV64)) +LIB_SRCS_NONARCH += src/arch/disasm_stubs.c +endif +ifneq ($(CFREE_LINK_ENABLED),1) +LIB_SRCS_ARCH_AA64 := $(filter-out %/link.c,$(LIB_SRCS_ARCH_AA64)) +LIB_SRCS_ARCH_X64 := $(filter-out %/link.c,$(LIB_SRCS_ARCH_X64)) +LIB_SRCS_ARCH_RV64 := $(filter-out %/link.c,$(LIB_SRCS_ARCH_RV64)) +LIB_SRCS_NONARCH += src/arch/link_stubs.c +endif +ifneq ($(CFREE_DBG_ENABLED),1) +LIB_SRCS_ARCH_AA64 := $(filter-out %/dbg.c,$(LIB_SRCS_ARCH_AA64)) +LIB_SRCS_ARCH_X64 := $(filter-out %/dbg.c,$(LIB_SRCS_ARCH_X64)) +LIB_SRCS_ARCH_RV64 := $(filter-out %/dbg.c,$(LIB_SRCS_ARCH_RV64)) +LIB_SRCS_NONARCH += src/arch/dbg_stubs.c +endif +ifneq ($(CFREE_EMU_ENABLED),1) +LIB_SRCS_ARCH_RV64 := $(filter-out %/emu.c,$(LIB_SRCS_ARCH_RV64)) +LIB_SRCS_NONARCH += src/arch/emu_stubs.c +endif LIB_SRCS_OBJ_ELF = $(shell find src/obj/elf -name '*.c' 2>/dev/null) LIB_SRCS_OBJ_MACHO = $(shell find src/obj/macho -name '*.c' 2>/dev/null) LIB_SRCS_OBJ_COFF = $(shell find src/obj/coff -name '*.c' 2>/dev/null) +ifneq ($(CFREE_LINK_ENABLED),1) +LIB_SRCS_OBJ_ELF := $(filter-out %/link.c %/link_dyn.c,$(LIB_SRCS_OBJ_ELF)) +LIB_SRCS_OBJ_MACHO := $(filter-out %/link.c,$(LIB_SRCS_OBJ_MACHO)) +LIB_SRCS_OBJ_COFF := $(filter-out %/link.c,$(LIB_SRCS_OBJ_COFF)) +LIB_SRCS_NONARCH += src/obj/link_stubs.c +endif +ifneq ($(CFREE_EMU_ENABLED),1) +LIB_SRCS_OBJ_ELF := $(filter-out %/emu_load.c,$(LIB_SRCS_OBJ_ELF)) +LIB_SRCS_NONARCH += src/obj/emu_stubs.c +endif +ifneq ($(CFREE_AR_ENABLED),1) +LIB_SRCS_OBJ_COFF := $(filter-out %/archive.c,$(LIB_SRCS_OBJ_COFF)) +LIB_SRCS_NONARCH += src/obj/archive_stubs.c +endif LIB_SRCS_OPT = $(shell find src/opt -name '*.c' 2>/dev/null) +LIB_SRCS_WASM_CORE = $(shell find src/wasm -name '*.c' 2>/dev/null) +LIB_SRCS_API_AR = src/api/archive.c +LIB_SRCS_API_DISASM = src/api/disasm.c +LIB_SRCS_API_LINK = src/api/link.c +LIB_SRCS_DEBUG = $(shell find src/debug -name '*.c' 2>/dev/null) +LIB_SRCS_DBG = $(shell find src/dbg -name '*.c' 2>/dev/null) +LIB_SRCS_EMU = $(shell find src/emu -name '*.c' 2>/dev/null) \ + $(shell find src/os -name '*.c' 2>/dev/null) +LIB_SRCS_LINK = $(shell find src/link -name '*.c' 2>/dev/null) +ifneq ($(CFREE_JIT_ENABLED),1) +LIB_SRCS_LINK := $(filter-out %/link_jit.c,$(LIB_SRCS_LINK)) +endif +LIB_SRCS_JIT_ASM = $(shell find src/jit -name '*.S' 2>/dev/null) LIB_SRC_ABI_AAPCS64 = src/abi/abi_aapcs64.c LIB_SRC_ABI_APPLE_ARM64 = src/abi/abi_apple_arm64.c @@ -125,6 +178,24 @@ LIB_SRCS = $(LIB_SRCS_NONARCH) ifeq ($(CFREE_OPT_ENABLED),1) LIB_SRCS += $(LIB_SRCS_OPT) endif +ifeq ($(CFREE_AR_ENABLED),1) +LIB_SRCS += $(LIB_SRCS_API_AR) +endif +ifeq ($(CFREE_DISASM_ENABLED),1) +LIB_SRCS += $(LIB_SRCS_API_DISASM) +endif +ifeq ($(CFREE_DWARF_ENABLED),1) +LIB_SRCS += $(LIB_SRCS_DEBUG) +endif +ifeq ($(CFREE_LINK_ENABLED),1) +LIB_SRCS += $(LIB_SRCS_API_LINK) $(LIB_SRCS_LINK) +endif +ifeq ($(CFREE_DBG_ENABLED),1) +LIB_SRCS += $(LIB_SRCS_DBG) +endif +ifeq ($(CFREE_EMU_ENABLED),1) +LIB_SRCS += $(LIB_SRCS_EMU) +endif ifeq ($(CFREE_ARCH_AA64_ENABLED),1) LIB_SRCS += $(LIB_SRCS_ARCH_AA64) endif @@ -140,6 +211,9 @@ endif ifeq ($(CFREE_ARCH_C_TARGET_ENABLED),1) LIB_SRCS += $(LIB_SRCS_ARCH_C_TARGET) endif +ifneq ($(filter 1,$(CFREE_ARCH_WASM_ENABLED) $(CFREE_OBJ_WASM_ENABLED) $(CFREE_LANG_WASM_ENABLED)),) +LIB_SRCS += $(LIB_SRCS_WASM_CORE) +endif ifeq ($(CFREE_OBJ_ELF_ENABLED),1) LIB_SRCS += $(LIB_SRCS_OBJ_ELF) endif @@ -199,17 +273,83 @@ ifeq ($(CFREE_LANG_TOY_ENABLED),1) LANG_OBJS += $(patsubst lang/toy/%.c,$(BUILD_DIR)/lang/toy/%.o,$(LANG_TOY_SRCS)) endif -LIB_ASMS = $(shell find src -name '*.S') +LIB_ASMS = +ifeq ($(CFREE_JIT_ENABLED),1) +LIB_ASMS += $(LIB_SRCS_JIT_ASM) +endif LIB_OBJS = $(patsubst src/%.c,$(BUILD_DIR)/lib/%.o,$(LIB_SRCS)) \ $(LANG_OBJS) \ $(patsubst src/%.S,$(BUILD_DIR)/lib/%.o,$(LIB_ASMS)) LIB_DEPS = $(LIB_OBJS:.o=.d) LIB_RELOC_OBJ = $(BUILD_DIR)/libcfree.o -DRIVER_SRCS = $(wildcard driver/*.c) -ifneq ($(CFREE_LANG_CPP_ENABLED),1) -DRIVER_SRCS := $(filter-out driver/cpp.c,$(DRIVER_SRCS)) +DRIVER_SRCS = driver/main.c driver/env.c driver/target.c +DRIVER_TOOL_SRCS = +ifeq ($(CFREE_TOOL_CC_ENABLED),1) +DRIVER_TOOL_SRCS += driver/cc.c +endif +ifeq ($(CFREE_TOOL_CHECK_ENABLED),1) +DRIVER_TOOL_SRCS += driver/cc.c +endif +ifeq ($(CFREE_TOOL_CPP_ENABLED),1) +DRIVER_TOOL_SRCS += driver/cpp.c +endif +ifeq ($(CFREE_TOOL_AS_ENABLED),1) +DRIVER_TOOL_SRCS += driver/as.c +endif +ifeq ($(CFREE_TOOL_LD_ENABLED),1) +DRIVER_TOOL_SRCS += driver/ld.c +endif +ifeq ($(CFREE_TOOL_AR_ENABLED),1) +DRIVER_TOOL_SRCS += driver/ar.c +endif +ifeq ($(CFREE_TOOL_RANLIB_ENABLED),1) +DRIVER_TOOL_SRCS += driver/ranlib.c +endif +ifeq ($(CFREE_TOOL_STRIP_ENABLED),1) +DRIVER_TOOL_SRCS += driver/strip.c +endif +ifeq ($(CFREE_TOOL_OBJCOPY_ENABLED),1) +DRIVER_TOOL_SRCS += driver/objcopy.c +endif +ifeq ($(CFREE_TOOL_OBJDUMP_ENABLED),1) +DRIVER_TOOL_SRCS += driver/objdump.c +endif +ifeq ($(CFREE_TOOL_DBG_ENABLED),1) +DRIVER_TOOL_SRCS += driver/dbg.c +endif +ifeq ($(CFREE_TOOL_RUN_ENABLED),1) +DRIVER_TOOL_SRCS += driver/run.c +endif +ifeq ($(CFREE_TOOL_EMU_ENABLED),1) +DRIVER_TOOL_SRCS += driver/emu.c +endif +ifeq ($(CFREE_TOOL_NM_ENABLED),1) +DRIVER_TOOL_SRCS += driver/nm.c +endif +ifeq ($(CFREE_TOOL_SIZE_ENABLED),1) +DRIVER_TOOL_SRCS += driver/size.c +endif +ifeq ($(CFREE_TOOL_ADDR2LINE_ENABLED),1) +DRIVER_TOOL_SRCS += driver/addr2line.c +endif +DRIVER_SRCS += $(sort $(DRIVER_TOOL_SRCS)) +ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_CPP_ENABLED) $(CFREE_TOOL_AS_ENABLED) $(CFREE_TOOL_DBG_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) +DRIVER_SRCS += driver/cflags.c +endif +ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_LD_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) +DRIVER_SRCS += driver/lib_resolve.c +endif +ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) +DRIVER_SRCS += driver/hosted.c +endif +ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED)),) +DRIVER_SRCS += driver/runtime.c +endif +ifneq ($(filter 1,$(CFREE_TOOL_AR_ENABLED) $(CFREE_TOOL_RANLIB_ENABLED) $(CFREE_TOOL_STRIP_ENABLED) $(CFREE_TOOL_DBG_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) +DRIVER_SRCS += driver/inputs.c endif +DRIVER_SRCS := $(sort $(DRIVER_SRCS)) DRIVER_OBJS = $(patsubst driver/%.c,$(BUILD_DIR)/driver/%.o,$(DRIVER_SRCS)) DRIVER_DEPS = $(DRIVER_OBJS:.o=.d) diff --git a/driver/main.c b/driver/main.c @@ -4,112 +4,113 @@ /* Multi-call dispatch. Looks at argv[0]'s basename for a tool name; if argv[0] * is the bare "cfree" binary, falls back to argv[1]. - * Preprocessor-only mode is `cc -E`. * - * Help routing is layered on top of dispatch: - * - * - `cfree` → driver_help_top() - * - `cfree -h | --help | -help` - * → driver_help_top() - * - `cfree help` → driver_help_top() - * - `cfree help <tool>` → driver_help_<tool>() - * - any tool entry sees no args, --help, or -h (objdump excepted) - * → driver_help_<tool>() and return 0. - * - * Each tool gates its own entry on argc < 2 / driver_argv_wants_help so - * the same handling applies regardless of whether the user invoked the - * multi-call form (`cfree cc --help`) or the symlinked form (`cc --help`). + * Tool availability is centralized here. The Makefile uses the same + * CFREE_TOOL_*_ENABLED flags to drop driver/<tool>.c objects, so disabled + * tools do not need #if checks scattered through each tool implementation. */ +typedef int (*DriverToolMain)(int argc, char** argv); +typedef void (*DriverToolHelp)(void); + +typedef struct DriverToolDesc { + const char* name; + DriverToolMain main; + DriverToolHelp help; + const char* summary; +} DriverToolDesc; + +static const DriverToolDesc driver_tools[] = { +#if CFREE_TOOL_CC_ENABLED + {"cc", driver_cc, driver_help_cc, + "Compile (and link) C sources, with cpp / dep-emit / -shared modes"}, +#endif +#if CFREE_TOOL_CHECK_ENABLED + {"check", driver_check, driver_help_check, + "Run C frontend checks without emitting code"}, +#endif +#if CFREE_TOOL_CPP_ENABLED + {"cpp", driver_cpp, driver_help_cpp, + "Standalone C preprocessor (alias for `cc -E` minus link scaffold)"}, +#endif +#if CFREE_TOOL_AS_ENABLED + {"as", driver_as, driver_help_as, + "Assemble a GAS-subset text source into a relocatable object"}, +#endif +#if CFREE_TOOL_LD_ENABLED + {"ld", driver_ld, driver_help_ld, + "Link objects/archives into an executable or shared library"}, +#endif +#if CFREE_TOOL_AR_ENABLED + {"ar", driver_ar, driver_help_ar, + "Create / modify / list / extract POSIX `ar` archives"}, +#endif +#if CFREE_TOOL_RANLIB_ENABLED + {"ranlib", driver_ranlib, driver_help_ranlib, + "Refresh the symbol index of an `ar` archive"}, +#endif +#if CFREE_TOOL_STRIP_ENABLED + {"strip", driver_strip, driver_help_strip, + "Drop debug sections and/or symbols from a .o or .a"}, +#endif +#if CFREE_TOOL_OBJCOPY_ENABLED + {"objcopy", driver_objcopy, driver_help_objcopy, + "Copy and transform an object file (rename / remove / format)"}, +#endif +#if CFREE_TOOL_OBJDUMP_ENABLED + {"objdump", driver_objdump, driver_help_objdump, + "Dump sections, symbols, disassembly, hex, and relocations"}, +#endif +#if CFREE_TOOL_RUN_ENABLED + {"run", driver_run, driver_help_run, + "JIT-compile inputs and invoke the entry symbol in-process"}, +#endif +#if CFREE_TOOL_DBG_ENABLED + {"dbg", driver_dbg, driver_help_dbg, + "Interactive JIT debugger (REPL on top of the JIT image)"}, +#endif +#if CFREE_TOOL_EMU_ENABLED + {"emu", driver_emu, driver_help_emu, + "Run a guest user-mode ELF (aarch64/riscv64) on the host"}, +#endif +#if CFREE_TOOL_NM_ENABLED + {"nm", driver_nm, driver_help_nm, "List symbols from object files"}, +#endif +#if CFREE_TOOL_SIZE_ENABLED + {"size", driver_size, driver_help_size, + "Display section sizes of object files"}, +#endif +#if CFREE_TOOL_ADDR2LINE_ENABLED + {"addr2line", driver_addr2line, driver_help_addr2line, + "Translate addresses to file:line using debug info"}, +#endif + {NULL, NULL, NULL, NULL}, +}; + +static unsigned driver_tool_count(void) { + return (unsigned)(sizeof driver_tools / sizeof driver_tools[0]) - 1u; +} + +static const DriverToolDesc* find_tool(const char* name) { + unsigned i; + for (i = 0; i < driver_tool_count(); ++i) { + if (driver_streq(name, driver_tools[i].name)) return &driver_tools[i]; + } + return NULL; +} + static int dispatch(const char* name, int argc, char** argv) { - if (driver_streq(name, "cc")) return driver_cc(argc, argv); - if (driver_streq(name, "check")) return driver_check(argc, argv); -#if CFREE_LANG_CPP_ENABLED - if (driver_streq(name, "cpp")) return driver_cpp(argc, argv); -#endif - if (driver_streq(name, "as")) return driver_as(argc, argv); - if (driver_streq(name, "ld")) return driver_ld(argc, argv); - if (driver_streq(name, "ar")) return driver_ar(argc, argv); - if (driver_streq(name, "ranlib")) return driver_ranlib(argc, argv); - if (driver_streq(name, "strip")) return driver_strip(argc, argv); - if (driver_streq(name, "objcopy")) return driver_objcopy(argc, argv); - if (driver_streq(name, "objdump")) return driver_objdump(argc, argv); - if (driver_streq(name, "dbg")) return driver_dbg(argc, argv); - if (driver_streq(name, "run")) return driver_run(argc, argv); - if (driver_streq(name, "emu")) return driver_emu(argc, argv); - if (driver_streq(name, "nm")) return driver_nm(argc, argv); - if (driver_streq(name, "size")) return driver_size(argc, argv); - if (driver_streq(name, "addr2line")) return driver_addr2line(argc, argv); + const DriverToolDesc* tool = find_tool(name); + if (tool) return tool->main(argc, argv); return -1; } /* If `name` matches a tool, print its help and return 0. Otherwise return * non-zero (caller reports the error). */ static int print_tool_help(const char* name) { - if (driver_streq(name, "cc")) { - driver_help_cc(); - return 0; - } - if (driver_streq(name, "check")) { - driver_help_check(); - return 0; - } -#if CFREE_LANG_CPP_ENABLED - if (driver_streq(name, "cpp")) { - driver_help_cpp(); - return 0; - } -#endif - if (driver_streq(name, "as")) { - driver_help_as(); - return 0; - } - if (driver_streq(name, "ld")) { - driver_help_ld(); - return 0; - } - if (driver_streq(name, "ar")) { - driver_help_ar(); - return 0; - } - if (driver_streq(name, "ranlib")) { - driver_help_ranlib(); - return 0; - } - if (driver_streq(name, "strip")) { - driver_help_strip(); - return 0; - } - if (driver_streq(name, "objcopy")) { - driver_help_objcopy(); - return 0; - } - if (driver_streq(name, "objdump")) { - driver_help_objdump(); - return 0; - } - if (driver_streq(name, "dbg")) { - driver_help_dbg(); - return 0; - } - if (driver_streq(name, "run")) { - driver_help_run(); - return 0; - } - if (driver_streq(name, "emu")) { - driver_help_emu(); - return 0; - } - if (driver_streq(name, "nm")) { - driver_help_nm(); - return 0; - } - if (driver_streq(name, "size")) { - driver_help_size(); - return 0; - } - if (driver_streq(name, "addr2line")) { - driver_help_addr2line(); + const DriverToolDesc* tool = find_tool(name); + if (tool) { + tool->help(); return 0; } return -1; @@ -134,9 +135,8 @@ int driver_argv_wants_help(int argc, char** argv, int accept_short_h) { } void driver_help_top(void) { + unsigned i; driver_printf( - "%.*s", - CFREE_SLICE_ARG(CFREE_SLICE_LIT( "cfree — freestanding C compiler toolchain\n" "\n" "USAGE\n" @@ -145,26 +145,11 @@ void driver_help_top(void) { "symlink\n" " cfree help [<tool>] this help, or per-tool help\n" "\n" - "TOOLS\n" - " cc Compile (and link) C sources, with cpp / dep-emit / -shared " - "modes\n" - " check Run C frontend checks without emitting code\n" - " cpp Standalone C preprocessor (alias for `cc -E` minus link " - "scaffold)\n" - " as Assemble a GAS-subset text source into a relocatable " - "object\n" - " ld Link objects/archives into an executable or shared library\n" - " ar Create / modify / list / extract POSIX `ar` archives\n" - " ranlib Refresh the symbol index of an `ar` archive\n" - " strip Drop debug sections and/or symbols from a .o or .a\n" - " objcopy Copy and transform an object file (rename / remove / format)\n" - " objdump Dump sections, symbols, disassembly, hex, and relocations\n" - " run JIT-compile inputs and invoke the entry symbol in-process\n" - " dbg Interactive JIT debugger (REPL on top of the JIT image)\n" - " emu Run a guest user-mode ELF (aarch64/riscv64) on the host\n" - " nm List symbols from object files\n" - " size Display section sizes of object files\n" - " addr2line Translate addresses to file:line using debug info\n" + "TOOLS\n"); + for (i = 0; i < driver_tool_count(); ++i) { + driver_printf(" %-9s %s\n", driver_tools[i].name, driver_tools[i].summary); + } + driver_printf( "\n" "GETTING HELP\n" " cfree <tool> --help full per-tool help (also -h, except " @@ -176,7 +161,7 @@ void driver_help_top(void) { "EXIT CODES\n" " 0 success\n" " 1 tool-reported error (compile, link, I/O, ...)\n" - " 2 bad command-line usage\n"))); + " 2 bad command-line usage\n"); } int driver_main(int argc, char** argv) { diff --git a/include/cfree/config.h b/include/cfree/config.h @@ -3,11 +3,13 @@ /* Build-time component configuration for libcfree and the cfree driver. * - * Four independent axes are gated here: + * Component axes are gated here: * - Backend architectures * - Object/image formats * - Language frontends * - Optional optimizer pipeline + * - Optional library subsystems + * - cfree driver tools * * ABIs are derived from (arch x obj-format) and are pulled in automatically * when both sides are enabled (see src/abi/). @@ -35,13 +37,16 @@ #define CFREE_OBJ_COFF_ENABLED 1 #define CFREE_OBJ_WASM_ENABLED 1 -/* Language frontends. The assembler frontend is unconditional: it lives - * inside libcfree as part of the codegen substrate. +/* Language frontends. * - * CFREE_LANG_CPP_ENABLED gates the C preprocessor (lang/cpp/). The C - * frontend depends on it; enabling CFREE_LANG_C_ENABLED without - * CFREE_LANG_CPP_ENABLED is a build-time error. The preprocessor can - * be enabled standalone (e.g. for `cfree cpp` only). */ + * CFREE_LANG_ASM_ENABLED only gates automatic registration of the asm + * frontend. The assembler parser/emitter substrate is still core today + * because inline/file-scope asm and the C frontend can depend on it. + * + * CFREE_LANG_CPP_ENABLED gates the C preprocessor (lang/cpp/). The C frontend + * depends on it; enabling CFREE_LANG_C_ENABLED without CFREE_LANG_CPP_ENABLED + * is a build-time error. The preprocessor can be enabled standalone. */ +#define CFREE_LANG_ASM_ENABLED 1 #define CFREE_LANG_CPP_ENABLED 1 #define CFREE_LANG_C_ENABLED 1 #define CFREE_LANG_TOY_ENABLED 1 @@ -51,4 +56,39 @@ * require this flag and the matching src/opt sources. */ #define CFREE_OPT_ENABLED 1 +/* Optional library subsystems. These are kept separate from driver tool flags: + * libcfree embedders care mostly about whether a public subsystem and its + * registry/vtables are present; the cfree binary additionally chooses which + * CLI entry points to compile and advertise. + * + * Some implementation directories are still shared by historically coupled + * subsystems. The build asserts the dependencies that are required by the + * current layout. */ +#define CFREE_AR_ENABLED 1 +#define CFREE_DISASM_ENABLED 1 +#define CFREE_DWARF_ENABLED 1 +#define CFREE_LINK_ENABLED 1 +#define CFREE_JIT_ENABLED 1 +#define CFREE_DBG_ENABLED 1 +#define CFREE_EMU_ENABLED 1 + +/* cfree multi-call driver tools. These flags control both dispatch/help and + * the driver/<tool>.c objects included in the cfree binary. */ +#define CFREE_TOOL_CC_ENABLED 1 +#define CFREE_TOOL_CHECK_ENABLED 1 +#define CFREE_TOOL_CPP_ENABLED 1 +#define CFREE_TOOL_AS_ENABLED 1 +#define CFREE_TOOL_LD_ENABLED 1 +#define CFREE_TOOL_AR_ENABLED 1 +#define CFREE_TOOL_RANLIB_ENABLED 1 +#define CFREE_TOOL_STRIP_ENABLED 1 +#define CFREE_TOOL_OBJCOPY_ENABLED 1 +#define CFREE_TOOL_OBJDUMP_ENABLED 1 +#define CFREE_TOOL_DBG_ENABLED 1 +#define CFREE_TOOL_RUN_ENABLED 1 +#define CFREE_TOOL_EMU_ENABLED 1 +#define CFREE_TOOL_NM_ENABLED 1 +#define CFREE_TOOL_SIZE_ENABLED 1 +#define CFREE_TOOL_ADDR2LINE_ENABLED 1 + #endif /* CFREE_CONFIG_H */ diff --git a/mk/config.mk b/mk/config.mk @@ -16,9 +16,35 @@ CFREE_OBJ_MACHO_ENABLED := $(call cfg_flag,CFREE_OBJ_MACHO_ENABLED) CFREE_OBJ_COFF_ENABLED := $(call cfg_flag,CFREE_OBJ_COFF_ENABLED) CFREE_OBJ_WASM_ENABLED := $(call cfg_flag,CFREE_OBJ_WASM_ENABLED) +CFREE_LANG_ASM_ENABLED := $(call cfg_flag,CFREE_LANG_ASM_ENABLED) CFREE_LANG_CPP_ENABLED := $(call cfg_flag,CFREE_LANG_CPP_ENABLED) CFREE_LANG_C_ENABLED := $(call cfg_flag,CFREE_LANG_C_ENABLED) CFREE_LANG_TOY_ENABLED := $(call cfg_flag,CFREE_LANG_TOY_ENABLED) CFREE_LANG_WASM_ENABLED := $(call cfg_flag,CFREE_LANG_WASM_ENABLED) CFREE_OPT_ENABLED := $(call cfg_flag,CFREE_OPT_ENABLED) + +CFREE_AR_ENABLED := $(call cfg_flag,CFREE_AR_ENABLED) +CFREE_DISASM_ENABLED := $(call cfg_flag,CFREE_DISASM_ENABLED) +CFREE_DWARF_ENABLED := $(call cfg_flag,CFREE_DWARF_ENABLED) +CFREE_LINK_ENABLED := $(call cfg_flag,CFREE_LINK_ENABLED) +CFREE_JIT_ENABLED := $(call cfg_flag,CFREE_JIT_ENABLED) +CFREE_DBG_ENABLED := $(call cfg_flag,CFREE_DBG_ENABLED) +CFREE_EMU_ENABLED := $(call cfg_flag,CFREE_EMU_ENABLED) + +CFREE_TOOL_CC_ENABLED := $(call cfg_flag,CFREE_TOOL_CC_ENABLED) +CFREE_TOOL_CHECK_ENABLED := $(call cfg_flag,CFREE_TOOL_CHECK_ENABLED) +CFREE_TOOL_CPP_ENABLED := $(call cfg_flag,CFREE_TOOL_CPP_ENABLED) +CFREE_TOOL_AS_ENABLED := $(call cfg_flag,CFREE_TOOL_AS_ENABLED) +CFREE_TOOL_LD_ENABLED := $(call cfg_flag,CFREE_TOOL_LD_ENABLED) +CFREE_TOOL_AR_ENABLED := $(call cfg_flag,CFREE_TOOL_AR_ENABLED) +CFREE_TOOL_RANLIB_ENABLED := $(call cfg_flag,CFREE_TOOL_RANLIB_ENABLED) +CFREE_TOOL_STRIP_ENABLED := $(call cfg_flag,CFREE_TOOL_STRIP_ENABLED) +CFREE_TOOL_OBJCOPY_ENABLED := $(call cfg_flag,CFREE_TOOL_OBJCOPY_ENABLED) +CFREE_TOOL_OBJDUMP_ENABLED := $(call cfg_flag,CFREE_TOOL_OBJDUMP_ENABLED) +CFREE_TOOL_DBG_ENABLED := $(call cfg_flag,CFREE_TOOL_DBG_ENABLED) +CFREE_TOOL_RUN_ENABLED := $(call cfg_flag,CFREE_TOOL_RUN_ENABLED) +CFREE_TOOL_EMU_ENABLED := $(call cfg_flag,CFREE_TOOL_EMU_ENABLED) +CFREE_TOOL_NM_ENABLED := $(call cfg_flag,CFREE_TOOL_NM_ENABLED) +CFREE_TOOL_SIZE_ENABLED := $(call cfg_flag,CFREE_TOOL_SIZE_ENABLED) +CFREE_TOOL_ADDR2LINE_ENABLED := $(call cfg_flag,CFREE_TOOL_ADDR2LINE_ENABLED) diff --git a/src/api/config_stubs.c b/src/api/config_stubs.c @@ -0,0 +1,800 @@ +#include <cfree/archive.h> +#include <cfree/config.h> +#include <cfree/dbg.h> +#include <cfree/disasm.h> +#include <cfree/dwarf.h> +#include <cfree/emu.h> +#include <cfree/jit.h> +#include <cfree/link.h> + +#include "core/core.h" +#include "debug/debug.h" +#include "link/link.h" + +#if !CFREE_AR_ENABLED +CfreeStatus cfree_ar_write(CfreeWriter* out, const CfreeArInput* members, + uint32_t nmembers, const CfreeArWriteOptions* opts) { + (void)out; + (void)members; + (void)nmembers; + (void)opts; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_ar_list(const CfreeSlice* archive, CfreeWriter* out) { + (void)archive; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_ar_iter_new(const CfreeContext* ctx, + const CfreeSlice* archive, CfreeArIter** out) { + (void)ctx; + (void)archive; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_ar_iter_next(CfreeArIter* it, CfreeArMember* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_ar_iter_free(CfreeArIter* it) { (void)it; } +#endif + +#if !CFREE_DISASM_ENABLED +CfreeStatus cfree_disasm_iter_new(const CfreeDisasmContext* dctx, + const uint8_t* bytes, size_t len, + uint64_t vaddr, + const CfreeObjFile* annotations, + CfreeDisasmIter** out) { + (void)dctx; + (void)bytes; + (void)len; + (void)vaddr; + (void)annotations; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_disasm_iter_next(CfreeDisasmIter* it, CfreeInsn* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_disasm_iter_free(CfreeDisasmIter* it) { (void)it; } + +CfreeStatus cfree_disasm_obj(const CfreeContext* ctx, const CfreeObjFile* obj, + CfreeWriter* out) { + (void)ctx; + (void)obj; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_disasm_obj_bytes(const CfreeContext* ctx, + const CfreeSlice* bytes, CfreeWriter* out) { + (void)ctx; + (void)bytes; + (void)out; + return CFREE_UNSUPPORTED; +} +#endif + +#if !CFREE_DWARF_ENABLED +Debug* debug_new(Compiler* c, ObjBuilder* ob) { + (void)c; + (void)ob; + return NULL; +} + +void debug_free(Debug* d) { (void)d; } +u32 debug_file(Debug* d, u32 source_file_id) { + (void)d; + (void)source_file_id; + return 0; +} + +DebugTypeId debug_type_base(Debug* d, Sym name, DebugBaseEncoding enc, + u32 byte_size) { + (void)d; + (void)name; + (void)enc; + (void)byte_size; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_void(Debug* d) { + (void)d; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_ptr(Debug* d, DebugTypeId pointee) { + (void)d; + (void)pointee; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_array(Debug* d, DebugTypeId elem, u32 count) { + (void)d; + (void)elem; + (void)count; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_const(Debug* d, DebugTypeId base) { + (void)d; + (void)base; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_volatile(Debug* d, DebugTypeId base) { + (void)d; + (void)base; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_restrict(Debug* d, DebugTypeId base) { + (void)d; + (void)base; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_typedef(Debug* d, Sym name, DebugTypeId base) { + (void)d; + (void)name; + (void)base; + return DEBUG_TYPE_NONE; +} + +DebugTypeId debug_type_func(Debug* d, DebugTypeId ret, + const DebugTypeId* params, u32 nparams, + int variadic) { + (void)d; + (void)ret; + (void)params; + (void)nparams; + (void)variadic; + return DEBUG_TYPE_NONE; +} + +DebugTypeBuilder* debug_type_record_begin(Debug* d, Sym tag, int is_union, + u32 byte_size, u32 align) { + (void)d; + (void)tag; + (void)is_union; + (void)byte_size; + (void)align; + return NULL; +} + +void debug_type_record_field(DebugTypeBuilder* b, Sym name, DebugTypeId type, + u32 byte_offset) { + (void)b; + (void)name; + (void)type; + (void)byte_offset; +} + +void debug_type_record_bitfield(DebugTypeBuilder* b, Sym name, DebugTypeId type, + u32 byte_offset, u16 bit_offset, + u16 bit_width) { + (void)b; + (void)name; + (void)type; + (void)byte_offset; + (void)bit_offset; + (void)bit_width; +} + +DebugTypeId debug_type_record_end(DebugTypeBuilder* b) { + (void)b; + return DEBUG_TYPE_NONE; +} + +DebugEnumBuilder* debug_type_enum_begin(Debug* d, Sym tag, DebugTypeId base) { + (void)d; + (void)tag; + (void)base; + return NULL; +} + +void debug_type_enum_value(DebugEnumBuilder* b, Sym name, i64 value) { + (void)b; + (void)name; + (void)value; +} + +DebugTypeId debug_type_enum_end(DebugEnumBuilder* b) { + (void)b; + return DEBUG_TYPE_NONE; +} + +void debug_func_begin(Debug* d, ObjSymId sym, DebugTypeId fn_type, + SrcLoc decl) { + (void)d; + (void)sym; + (void)fn_type; + (void)decl; +} + +void debug_func_pc_range(Debug* d, ObjSecId text_section_id, u32 begin_ofs, + u32 end_ofs) { + (void)d; + (void)text_section_id; + (void)begin_ofs; + (void)end_ofs; +} + +void debug_func_end(Debug* d) { (void)d; } +void debug_scope_begin(Debug* d, SrcLoc loc) { + (void)d; + (void)loc; +} +void debug_scope_end(Debug* d, SrcLoc loc) { + (void)d; + (void)loc; +} + +void debug_param(Debug* d, Sym name, DebugTypeId type, SrcLoc loc, u32 idx, + DebugVarLoc var_loc) { + (void)d; + (void)name; + (void)type; + (void)loc; + (void)idx; + (void)var_loc; +} + +void debug_local(Debug* d, Sym name, DebugTypeId type, SrcLoc loc, + DebugVarLoc var_loc) { + (void)d; + (void)name; + (void)type; + (void)loc; + (void)var_loc; +} + +void debug_line(Debug* d, ObjSecId text_section_id, u32 text_offset, SrcLoc loc, + int is_stmt) { + (void)d; + (void)text_section_id; + (void)text_offset; + (void)loc; + (void)is_stmt; +} + +void debug_set_pending_loc(Debug* d, SrcLoc loc) { + (void)d; + (void)loc; +} + +void debug_emit_row(Debug* d, ObjSecId text_section_id, u32 text_offset, + SrcLoc loc) { + (void)d; + (void)text_section_id; + (void)text_offset; + (void)loc; +} + +u32 debug_loclist_new(Debug* d) { + (void)d; + return 0; +} + +void debug_loclist_add(Debug* d, u32 id, u32 begin_pc, u32 end_pc, + DebugVarLoc loc) { + (void)d; + (void)id; + (void)begin_pc; + (void)end_pc; + (void)loc; +} + +void debug_emit(Debug* d) { (void)d; } + +CfreeStatus cfree_dwarf_open(const CfreeContext* ctx, const CfreeObjFile* obj, + CfreeDebugInfo** out) { + (void)ctx; + (void)obj; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +void cfree_dwarf_free(CfreeDebugInfo* d) { (void)d; } + +CfreeStatus cfree_dwarf_addr_to_line(CfreeDebugInfo* d, uint64_t pc, + CfreeSlice* file_out, uint32_t* line_out, + uint32_t* col_out) { + (void)d; + (void)pc; + (void)file_out; + (void)line_out; + (void)col_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_line_to_addr(CfreeDebugInfo* d, CfreeSlice file, + uint32_t line, uint64_t* pc_out) { + (void)d; + (void)file; + (void)line; + (void)pc_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_line_to_addr_all(CfreeDebugInfo* d, CfreeSlice file, + uint32_t line, + CfreeDwarfLineMatch* out, uint32_t cap, + uint32_t* n_out) { + (void)d; + (void)file; + (void)line; + (void)out; + (void)cap; + if (n_out) *n_out = 0; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_func_at(CfreeDebugInfo* d, uint64_t pc, + CfreeSlice* name_out, uint64_t* low_pc_out, + uint64_t* high_pc_out) { + (void)d; + (void)pc; + (void)name_out; + (void)low_pc_out; + (void)high_pc_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_subprogram_at(CfreeDebugInfo* d, uint64_t pc, + CfreeDwarfSubprogram* out) { + (void)d; + (void)pc; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_subprogram_named(CfreeDebugInfo* d, CfreeSlice name, + CfreeDwarfSubprogram* out) { + (void)d; + (void)name; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_unwind_step(CfreeDebugInfo* d, + CfreeUnwindFrame* frame) { + (void)d; + (void)frame; + return CFREE_UNSUPPORTED; +} + +CfreeDwarfTypeInfo cfree_dwarf_type_info(const CfreeDwarfType* t) { + CfreeDwarfTypeInfo info; + (void)t; + info.kind = CFREE_DT_VOID; + info.byte_size = 0; + info.name = CFREE_SLICE_NULL; + info.element_count = 0; + info.inner = NULL; + return info; +} + +CfreeStatus cfree_dwarf_field_iter_new(CfreeDebugInfo* d, + const CfreeDwarfType* t, + CfreeDwarfFieldIter** out) { + (void)d; + (void)t; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_dwarf_field_iter_next(CfreeDwarfFieldIter* it, + CfreeDwarfField* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_dwarf_field_iter_free(CfreeDwarfFieldIter* it) { (void)it; } + +CfreeStatus cfree_dwarf_enum_iter_new(CfreeDebugInfo* d, + const CfreeDwarfType* t, + CfreeDwarfEnumIter** out) { + (void)d; + (void)t; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_dwarf_enum_iter_next(CfreeDwarfEnumIter* it, + CfreeDwarfEnumVal* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_dwarf_enum_iter_free(CfreeDwarfEnumIter* it) { (void)it; } + +CfreeStatus cfree_dwarf_var_at(CfreeDebugInfo* d, uint64_t pc, CfreeSlice name, + CfreeDwarfVarLoc* out) { + (void)d; + (void)pc; + (void)name; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_loc_read(CfreeDebugInfo* d, const CfreeDwarfVarLoc* loc, + const CfreeUnwindFrame* frame, + CfreeDwarfReadMemFn read_mem, void* read_user, + void* dst, size_t cap, size_t* read_out) { + (void)d; + (void)loc; + (void)frame; + (void)read_mem; + (void)read_user; + (void)dst; + (void)cap; + if (read_out) *read_out = 0; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_vars_at_new(CfreeDebugInfo* d, uint64_t pc, + uint32_t role_mask, + CfreeDwarfVarIter** out) { + (void)d; + (void)pc; + (void)role_mask; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_dwarf_vars_at_next(CfreeDwarfVarIter* it, + CfreeDwarfVar* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_dwarf_vars_at_free(CfreeDwarfVarIter* it) { (void)it; } + +CfreeStatus cfree_dwarf_param_iter_new(CfreeDebugInfo* d, uint64_t pc, + CfreeDwarfParamIter** out) { + (void)d; + (void)pc; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_dwarf_param_iter_new_named(CfreeDebugInfo* d, CfreeSlice name, + CfreeDwarfParamIter** out) { + (void)d; + (void)name; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_dwarf_param_iter_next(CfreeDwarfParamIter* it, + CfreeDwarfVar* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_dwarf_param_iter_free(CfreeDwarfParamIter* it) { (void)it; } +#endif + +#if !CFREE_LINK_ENABLED +CfreeStatus cfree_link_script_parse(const CfreeContext* ctx, CfreeSlice text, + CfreeLinkScript** out) { + (void)ctx; + (void)text; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +void cfree_link_script_free(const CfreeContext* ctx, CfreeLinkScript* s) { + (void)ctx; + (void)s; +} + +CfreeStatus cfree_link_session_new(CfreeCompiler* c, + const CfreeLinkSessionOptions* opts, + CfreeLinkSession** out) { + (void)c; + (void)opts; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_add_obj(CfreeLinkSession* s, + CfreeObjBuilder* ob) { + (void)s; + (void)ob; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_add_obj_bytes(CfreeLinkSession* s, + CfreeSlice name, + const CfreeSlice* bytes) { + (void)s; + (void)name; + (void)bytes; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_add_archive_bytes( + CfreeLinkSession* s, const CfreeLinkArchiveInput* archive) { + (void)s; + (void)archive; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_add_dso_bytes(CfreeLinkSession* s, + CfreeSlice name, + const CfreeSlice* bytes) { + (void)s; + (void)name; + (void)bytes; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_resolve(CfreeLinkSession* s) { + (void)s; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_emit(CfreeLinkSession* s, CfreeWriter* out) { + (void)s; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_link_session_jit(CfreeLinkSession* s, CfreeJit** out_jit) { + (void)s; + if (out_jit) *out_jit = NULL; + return CFREE_UNSUPPORTED; +} + +void cfree_link_session_free(CfreeLinkSession* s) { (void)s; } +#endif + +#if !CFREE_JIT_ENABLED +CfreeJit* cfree_jit_from_image(LinkImage* img) { + (void)img; + return NULL; +} + +const CfreeExecMem* cfree_jit_image_execmem(CfreeJit* jit) { + (void)jit; + return NULL; +} + +int cfree_jit_image_contains(CfreeJit* jit, uint64_t runtime_addr) { + (void)jit; + (void)runtime_addr; + return 0; +} + +CfreeArchKind cfree_jit_image_arch(CfreeJit* jit) { + (void)jit; + return CFREE_ARCH_X86_64; +} + +Compiler* cfree_jit_compiler(CfreeJit* jit) { + (void)jit; + return NULL; +} + +void cfree_jit_free(CfreeJit* jit) { (void)jit; } + +void* cfree_jit_lookup(CfreeJit* jit, CfreeSlice name) { + (void)jit; + (void)name; + return NULL; +} + +uint64_t cfree_jit_generation(CfreeJit* jit) { + (void)jit; + return 0; +} + +void cfree_jit_run_dtors(CfreeJit* jit) { (void)jit; } + +CfreeStatus cfree_jit_publish(CfreeJit* jit, const CfreeJitPublishOptions* opts, + CfreeJitPublishResult* result) { + (void)jit; + (void)opts; + (void)result; + return CFREE_UNSUPPORTED; +} + +const CfreeObjFile* cfree_jit_view(CfreeJit* jit) { + (void)jit; + return NULL; +} + +CfreeStatus cfree_jit_addr_to_sym(CfreeJit* jit, uint64_t addr, + CfreeSlice* name_out, uint64_t* off_out) { + (void)jit; + (void)addr; + (void)name_out; + (void)off_out; + return CFREE_UNSUPPORTED; +} + +uint64_t cfree_jit_runtime_to_image(CfreeJit* jit, uint64_t runtime_pc) { + (void)jit; + (void)runtime_pc; + return 0; +} + +uint64_t cfree_jit_image_to_runtime(CfreeJit* jit, uint64_t image_vaddr) { + (void)jit; + (void)image_vaddr; + return 0; +} + +CfreeStatus cfree_jit_sym_iter_new(CfreeJit* jit, CfreeJitSymIter** out) { + (void)jit; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeIterResult cfree_jit_sym_iter_next(CfreeJitSymIter* it, CfreeJitSym* out) { + (void)it; + (void)out; + return CFREE_ITER_ERROR; +} + +void cfree_jit_sym_iter_free(CfreeJitSymIter* it) { (void)it; } +#endif + +#if !CFREE_DBG_ENABLED +CfreeStatus cfree_jit_session_new(CfreeJit* jit, const CfreeDbgHost* host, + CfreeJitSession** out) { + (void)jit; + (void)host; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +void cfree_jit_session_free(CfreeJitSession* s) { (void)s; } + +CfreeStatus cfree_jit_session_attach_dwarf(CfreeJitSession* s, + CfreeDebugInfo* dwarf) { + (void)s; + (void)dwarf; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_call(CfreeJitSession* s, void* entry, + CfreeEntryKind kind, int argc, char** argv, + CfreeStopInfo* stop_out) { + (void)s; + (void)entry; + (void)kind; + (void)argc; + (void)argv; + (void)stop_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_call_u64(CfreeJitSession* s, void* entry, + const uint64_t* args, uint32_t nargs, + uint64_t* ret_out, + CfreeStopInfo* stop_out) { + (void)s; + (void)entry; + (void)args; + (void)nargs; + (void)ret_out; + (void)stop_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_resume(CfreeJitSession* s, CfreeResumeMode mode, + CfreeStopInfo* stop_out) { + (void)s; + (void)mode; + (void)stop_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_interrupt(CfreeJitSession* s) { + (void)s; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_read_mem(CfreeJitSession* s, uint64_t addr, + void* dst, size_t n) { + (void)s; + (void)addr; + (void)dst; + (void)n; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_write_mem(CfreeJitSession* s, uint64_t addr, + const void* src, size_t n) { + (void)s; + (void)addr; + (void)src; + (void)n; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_get_regs(CfreeJitSession* s, + CfreeUnwindFrame* out) { + (void)s; + (void)out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_set_regs(CfreeJitSession* s, + const CfreeUnwindFrame* in) { + (void)s; + (void)in; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_breakpoint_set(CfreeJitSession* s, uint64_t addr, + uint32_t* bp_id_out) { + (void)s; + (void)addr; + (void)bp_id_out; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_breakpoint_clear(CfreeJitSession* s, + uint32_t bp_id) { + (void)s; + (void)bp_id; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_jit_session_breakpoint_set_spec( + CfreeJitSession* s, const CfreeBreakpointSpec* spec, uint32_t* bp_id_out) { + (void)s; + (void)spec; + (void)bp_id_out; + return CFREE_UNSUPPORTED; +} +#endif + +#if !CFREE_EMU_ENABLED +CfreeStatus cfree_emu_run(CfreeCompiler* c, const CfreeEmuOptions* opts, + int* out_exit_code) { + (void)c; + (void)opts; + (void)out_exit_code; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_emu_new(CfreeCompiler* c, const CfreeEmuOptions* opts, + CfreeEmu** out) { + (void)c; + (void)opts; + if (out) *out = NULL; + return CFREE_UNSUPPORTED; +} + +CfreeStatus cfree_emu_step(CfreeEmu* e, uint32_t nblocks) { + (void)e; + (void)nblocks; + return CFREE_UNSUPPORTED; +} + +void* cfree_emu_lookup(CfreeEmu* e, uint64_t guest_pc) { + (void)e; + (void)guest_pc; + return NULL; +} + +void cfree_emu_free(CfreeEmu* e) { (void)e; } +#endif diff --git a/src/api/lang_registry.c b/src/api/lang_registry.c @@ -6,10 +6,8 @@ * compile/pipeline paths can dispatch by CfreeLanguage without any * host-side bootstrap. * - * The asm frontend is unconditional and registered here too; there is - * no fallback in frontend_for_language(), so an embedder that doesn't - * want asm can drop the slot after compiler construction with - * cfree_register_frontend(c, CFREE_LANG_ASM, NULL). + * The asm frontend lives inside the codegen substrate, but automatic + * registration is gated by CFREE_LANG_ASM_ENABLED. * * Third parties may still call cfree_register_frontend() to install or * override any slot after construction; that public API is unchanged. @@ -21,14 +19,13 @@ #include "cfree/config.h" -_Static_assert(!CFREE_LANG_C_ENABLED || CFREE_LANG_CPP_ENABLED, - "CFREE_LANG_C_ENABLED requires CFREE_LANG_CPP_ENABLED"); - /* Defined in src/api/compile.c, alongside the asm frontend's * new/compile/free functions. Treated as part of the codegen substrate * (no per-frontend lang/ directory), so its declaration lives here * rather than in a public header. */ +#if CFREE_LANG_ASM_ENABLED extern const CfreeFrontendVTable cfree_asm_frontend_vtable; +#endif #if CFREE_LANG_C_ENABLED #include "c/c.h" @@ -41,7 +38,9 @@ extern const CfreeFrontendVTable cfree_asm_frontend_vtable; #endif void lang_registry_init(CfreeCompiler* c) { +#if CFREE_LANG_ASM_ENABLED (void)cfree_register_frontend(c, CFREE_LANG_ASM, &cfree_asm_frontend_vtable); +#endif #if CFREE_LANG_C_ENABLED (void)cfree_register_frontend(c, CFREE_LANG_C, &cfree_c_frontend_vtable); #endif diff --git a/src/api/object_detect.c b/src/api/object_detect.c @@ -1,5 +1,6 @@ /* Binary format and target detection from object header bytes. */ +#include <cfree/config.h> #include <cfree/object.h> #include "core/core.h" @@ -244,12 +245,19 @@ CfreeStatus cfree_detect_target(const uint8_t* data, size_t len, if (!data || !out) return CFREE_INVALID; bin = cfree_detect_fmt(data, len); switch (bin) { +#if CFREE_OBJ_ELF_ENABLED case CFREE_BIN_ELF: return detect_elf(data, len, out); +#endif +#if CFREE_OBJ_COFF_ENABLED case CFREE_BIN_COFF: return detect_coff(data, len, out); +#endif +#if CFREE_OBJ_MACHO_ENABLED case CFREE_BIN_MACHO: return detect_macho(data, len, out); +#endif +#if CFREE_OBJ_WASM_ENABLED case CFREE_BIN_WASM: { CfreeTarget t; t.big_endian = 0; @@ -263,6 +271,7 @@ CfreeStatus cfree_detect_target(const uint8_t* data, size_t len, *out = t; return CFREE_OK; } +#endif default: return CFREE_UNSUPPORTED; } diff --git a/src/api/object_file.c b/src/api/object_file.c @@ -24,17 +24,11 @@ struct CfreeObjFile { u32 sec_data_n; }; -static ObjBuilder* obj_read_bytes(Compiler* c, const char* name, const u8* data, - size_t len, ObjFmt fmt) { - const ObjFormatImpl* impl = obj_format_lookup(fmt); - if (!impl || !impl->read) return NULL; - return impl->read(c, name, data, len); -} - CfreeStatus cfree_obj_open(const CfreeContext* ctx, CfreeSlice name, const CfreeSlice* input, CfreeObjFile** out) { Heap* h; CfreeObjFile* f; + const ObjFormatImpl* impl; CfreeTarget target; CfreeStatus st; @@ -45,6 +39,8 @@ CfreeStatus cfree_obj_open(const CfreeContext* ctx, CfreeSlice name, st = cfree_detect_target(input->data, input->len, &target); if (st != CFREE_OK) return st; + impl = obj_format_lookup(target.obj); + if (!impl || !impl->read) return CFREE_UNSUPPORTED; h = ctx->heap; f = (CfreeObjFile*)h->alloc(h, sizeof(*f), _Alignof(CfreeObjFile)); @@ -61,8 +57,7 @@ CfreeStatus cfree_obj_open(const CfreeContext* ctx, CfreeSlice name, h->free(h, f, sizeof(*f)); return CFREE_MALFORMED; } - f->ob = obj_read_bytes(&f->compiler, name.s, input->data, input->len, - target.obj); + f->ob = impl->read(&f->compiler, name.s, input->data, input->len); if (!f->ob) { compiler_fini(&f->compiler); h->free(h, f, sizeof(*f)); diff --git a/src/api/stubs.c b/src/api/stubs.c @@ -1,18 +0,0 @@ -/* Stub implementations for libcfree subsystems not yet implemented. */ - -#include "core/core.h" -#include "core/slice.h" -#include "obj/obj.h" - -static _Noreturn void unimplemented(Compiler* c, const char* what) { - SrcLoc loc = {0, 0, 0}; - compiler_panic(c, loc, "subsystem not implemented: %.*s", - SLICE_ARG(slice_from_cstr(what))); -} - -ObjBuilder* read_wasm(Compiler* c, const char* n, const u8* d, size_t l) { - (void)n; - (void)d; - (void)l; - unimplemented(c, "read_wasm"); -} diff --git a/src/arch/aa64/arch.c b/src/arch/aa64/arch.c @@ -11,6 +11,7 @@ extern const LinkArchDesc link_arch_aa64; extern const ArchDbgOps aa64_dbg_ops; +extern const ArchDwarfOps aa64_dwarf_ops; static int aa64_register_at_public(uint32_t idx, CfreeArchReg* out) { const char* nm = NULL; @@ -29,11 +30,6 @@ static void aa64_wr_u64_target(Compiler* c, u8* p, u64 v) { } } -static const ArchDwarfOps aa64_dwarf_ops = { - .min_inst_len = 4u, - .max_ops_per_inst = 1u, -}; - static int aa64_apply_label_fixup(Compiler* c, const ArchLabelFixup* fx) { const Section* s; u8 cur[4]; diff --git a/src/arch/cgtarget.c b/src/arch/cgtarget.c @@ -3,6 +3,7 @@ * The lifecycle helpers (cgtarget_finalize, cgtarget_free) are arch-agnostic * shims over the vtable. */ +#include <cfree/config.h> #include <string.h> #include "arch/arch.h" @@ -31,14 +32,15 @@ void cgtarget_free(CGTarget* t) { } CfreeStatus cg_mc_debug_new(Compiler* c, ObjBuilder* o, - const CfreeCodeOptions* opts, - MCEmitter** out_mc, Debug** out_debug) { + const CfreeCodeOptions* opts, MCEmitter** out_mc, + Debug** out_debug) { MCEmitter* mc; Debug* debug = NULL; *out_mc = NULL; *out_debug = NULL; mc = mc_new(c, o); if (!mc) return CFREE_NOMEM; +#if CFREE_DWARF_ENABLED if (opts && opts->debug_info) { debug = debug_new(c, o); if (!debug) { @@ -47,6 +49,13 @@ CfreeStatus cg_mc_debug_new(Compiler* c, ObjBuilder* o, } mc->debug = debug; } +#else + (void)o; + if (opts && opts->debug_info) { + mc_free(mc); + return CFREE_UNSUPPORTED; + } +#endif *out_mc = mc; *out_debug = debug; return CFREE_OK; diff --git a/src/arch/dbg_stubs.c b/src/arch/dbg_stubs.c @@ -0,0 +1,5 @@ +#include "arch/arch.h" + +const ArchDbgOps aa64_dbg_ops = {0}; +const ArchDbgOps x64_dbg_ops = {0}; +const ArchDbgOps rv64_dbg_ops = {0}; diff --git a/src/arch/disasm_stubs.c b/src/arch/disasm_stubs.c @@ -0,0 +1,18 @@ +#include "arch/arch.h" + +ArchDisasm* aa64_disasm_new(Compiler* c) { + (void)c; + return NULL; +} + +ArchDisasm* x64_disasm_new(Compiler* c) { + (void)c; + return NULL; +} + +ArchDisasm* rv64_disasm_new(Compiler* c) { + (void)c; + return NULL; +} + +const ArchDecodeOps rv64_decode_ops = {0}; diff --git a/src/arch/dwarf.c b/src/arch/dwarf.c @@ -0,0 +1,16 @@ +#include "arch/arch.h" + +const ArchDwarfOps aa64_dwarf_ops = { + .min_inst_len = 4u, + .max_ops_per_inst = 1u, +}; + +const ArchDwarfOps x64_dwarf_ops = { + .min_inst_len = 1u, + .max_ops_per_inst = 1u, +}; + +const ArchDwarfOps rv64_dwarf_ops = { + .min_inst_len = 4u, + .max_ops_per_inst = 1u, +}; diff --git a/src/arch/emu_stubs.c b/src/arch/emu_stubs.c @@ -0,0 +1,3 @@ +#include "arch/arch.h" + +const ArchEmuOps rv64_emu_ops = {0}; diff --git a/src/arch/link_stubs.c b/src/arch/link_stubs.c @@ -0,0 +1,5 @@ +#include "link/link_arch.h" + +const LinkArchDesc link_arch_aa64 = {0}; +const LinkArchDesc link_arch_x64 = {0}; +const LinkArchDesc link_arch_rv64 = {0}; diff --git a/src/arch/rv64/arch.c b/src/arch/rv64/arch.c @@ -11,11 +11,7 @@ extern const LinkArchDesc link_arch_rv64; extern const ArchDbgOps rv64_dbg_ops; extern const ArchEmuOps rv64_emu_ops; - -static const ArchDwarfOps rv64_dwarf_ops = { - .min_inst_len = 4u, - .max_ops_per_inst = 1u, -}; +extern const ArchDwarfOps rv64_dwarf_ops; static int rv64_register_at_public(uint32_t idx, CfreeArchReg* out) { const char* nm = NULL; diff --git a/src/arch/wasm/internal.h b/src/arch/wasm/internal.h @@ -26,9 +26,8 @@ #include "core/core.h" #include "obj/obj.h" -/* Forward references into lang/wasm. We use the existing in-memory module - * representation rather than rebuilding one, so emit_wasm can reuse - * wasm_encode unchanged. */ +/* Forward references into the shared src/wasm module representation. The + * target reuses that model so emit_wasm can flush through wasm_encode. */ struct WasmModule; struct WasmFunc; diff --git a/src/arch/x64/arch.c b/src/arch/x64/arch.c @@ -10,11 +10,7 @@ extern const LinkArchDesc link_arch_x64; extern const ArchDbgOps x64_dbg_ops; - -static const ArchDwarfOps x64_dwarf_ops = { - .min_inst_len = 1u, - .max_ops_per_inst = 1u, -}; +extern const ArchDwarfOps x64_dwarf_ops; static int x64_apply_label_fixup(Compiler* c, const ArchLabelFixup* fx) { (void)c; diff --git a/src/core/config_assert.c b/src/core/config_assert.c @@ -4,15 +4,108 @@ #include "cfree/config.h" _Static_assert(CFREE_ARCH_AA64_ENABLED + CFREE_ARCH_X64_ENABLED + - CFREE_ARCH_RV64_ENABLED + + CFREE_ARCH_RV64_ENABLED + CFREE_ARCH_WASM_ENABLED + CFREE_ARCH_C_TARGET_ENABLED >= 1, "at least one backend architecture must be enabled"); _Static_assert(CFREE_OBJ_ELF_ENABLED + CFREE_OBJ_MACHO_ENABLED + - CFREE_OBJ_COFF_ENABLED >= + CFREE_OBJ_COFF_ENABLED + CFREE_OBJ_WASM_ENABLED >= 1, "at least one object/image format must be enabled"); +#define CFREE_ASSERT_BOOL(flag) \ + _Static_assert((flag) == 0 || (flag) == 1, #flag " must be 0 or 1") + +CFREE_ASSERT_BOOL(CFREE_ARCH_AA64_ENABLED); +CFREE_ASSERT_BOOL(CFREE_ARCH_X64_ENABLED); +CFREE_ASSERT_BOOL(CFREE_ARCH_RV64_ENABLED); +CFREE_ASSERT_BOOL(CFREE_ARCH_WASM_ENABLED); +CFREE_ASSERT_BOOL(CFREE_ARCH_C_TARGET_ENABLED); +CFREE_ASSERT_BOOL(CFREE_OBJ_ELF_ENABLED); +CFREE_ASSERT_BOOL(CFREE_OBJ_MACHO_ENABLED); +CFREE_ASSERT_BOOL(CFREE_OBJ_COFF_ENABLED); +CFREE_ASSERT_BOOL(CFREE_OBJ_WASM_ENABLED); +CFREE_ASSERT_BOOL(CFREE_LANG_ASM_ENABLED); +CFREE_ASSERT_BOOL(CFREE_LANG_CPP_ENABLED); +CFREE_ASSERT_BOOL(CFREE_LANG_C_ENABLED); +CFREE_ASSERT_BOOL(CFREE_LANG_TOY_ENABLED); +CFREE_ASSERT_BOOL(CFREE_LANG_WASM_ENABLED); _Static_assert(CFREE_OPT_ENABLED == 0 || CFREE_OPT_ENABLED == 1, "CFREE_OPT_ENABLED must be 0 or 1"); +CFREE_ASSERT_BOOL(CFREE_AR_ENABLED); +CFREE_ASSERT_BOOL(CFREE_DISASM_ENABLED); +CFREE_ASSERT_BOOL(CFREE_DWARF_ENABLED); +CFREE_ASSERT_BOOL(CFREE_LINK_ENABLED); +CFREE_ASSERT_BOOL(CFREE_JIT_ENABLED); +CFREE_ASSERT_BOOL(CFREE_DBG_ENABLED); +CFREE_ASSERT_BOOL(CFREE_EMU_ENABLED); + +CFREE_ASSERT_BOOL(CFREE_TOOL_CC_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_CHECK_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_CPP_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_AS_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_LD_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_AR_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_RANLIB_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_STRIP_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_OBJCOPY_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_OBJDUMP_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_DBG_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_RUN_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_EMU_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_NM_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_SIZE_ENABLED); +CFREE_ASSERT_BOOL(CFREE_TOOL_ADDR2LINE_ENABLED); + +#undef CFREE_ASSERT_BOOL + +_Static_assert(!CFREE_LANG_C_ENABLED || CFREE_LANG_CPP_ENABLED, + "CFREE_LANG_C_ENABLED requires CFREE_LANG_CPP_ENABLED"); +_Static_assert(!CFREE_ARCH_WASM_ENABLED || CFREE_OBJ_WASM_ENABLED, + "CFREE_ARCH_WASM_ENABLED requires CFREE_OBJ_WASM_ENABLED"); + +_Static_assert(!CFREE_JIT_ENABLED || CFREE_LINK_ENABLED, + "CFREE_JIT_ENABLED requires CFREE_LINK_ENABLED"); +_Static_assert(!CFREE_DBG_ENABLED || (CFREE_JIT_ENABLED && CFREE_DWARF_ENABLED), + "CFREE_DBG_ENABLED requires CFREE_JIT_ENABLED and " + "CFREE_DWARF_ENABLED"); +_Static_assert(!CFREE_EMU_ENABLED || + (CFREE_JIT_ENABLED && CFREE_LINK_ENABLED && + CFREE_DISASM_ENABLED && CFREE_OBJ_ELF_ENABLED), + "CFREE_EMU_ENABLED requires JIT, link, disasm, and ELF " + "support"); + +_Static_assert(!CFREE_TOOL_CC_ENABLED || + (CFREE_LANG_C_ENABLED && CFREE_LINK_ENABLED && + CFREE_AR_ENABLED), + "CFREE_TOOL_CC_ENABLED requires C, link, and ar support"); +_Static_assert(!CFREE_TOOL_CHECK_ENABLED || CFREE_LANG_C_ENABLED, + "CFREE_TOOL_CHECK_ENABLED requires C support"); +_Static_assert(!CFREE_TOOL_CPP_ENABLED || CFREE_LANG_CPP_ENABLED, + "CFREE_TOOL_CPP_ENABLED requires C preprocessor support"); +_Static_assert(!CFREE_TOOL_LD_ENABLED || CFREE_LINK_ENABLED, + "CFREE_TOOL_LD_ENABLED requires link support"); +_Static_assert(!CFREE_TOOL_AR_ENABLED || CFREE_AR_ENABLED, + "CFREE_TOOL_AR_ENABLED requires ar support"); +_Static_assert(!CFREE_TOOL_RANLIB_ENABLED || CFREE_AR_ENABLED, + "CFREE_TOOL_RANLIB_ENABLED requires ar support"); +_Static_assert(!CFREE_TOOL_STRIP_ENABLED || CFREE_AR_ENABLED, + "CFREE_TOOL_STRIP_ENABLED requires ar support"); +_Static_assert(!CFREE_TOOL_OBJCOPY_ENABLED || CFREE_AR_ENABLED, + "CFREE_TOOL_OBJCOPY_ENABLED requires ar support"); +_Static_assert(!CFREE_TOOL_OBJDUMP_ENABLED || CFREE_DISASM_ENABLED, + "CFREE_TOOL_OBJDUMP_ENABLED requires disasm support"); +_Static_assert(!CFREE_TOOL_RUN_ENABLED || + (CFREE_JIT_ENABLED && CFREE_LINK_ENABLED), + "CFREE_TOOL_RUN_ENABLED requires JIT and link support"); +_Static_assert(!CFREE_TOOL_DBG_ENABLED || CFREE_DBG_ENABLED, + "CFREE_TOOL_DBG_ENABLED requires debugger support"); +_Static_assert(!CFREE_TOOL_EMU_ENABLED || CFREE_EMU_ENABLED, + "CFREE_TOOL_EMU_ENABLED requires emulator support"); +_Static_assert(!CFREE_TOOL_NM_ENABLED || CFREE_AR_ENABLED, + "CFREE_TOOL_NM_ENABLED requires ar support"); +_Static_assert(!CFREE_TOOL_SIZE_ENABLED || CFREE_AR_ENABLED, + "CFREE_TOOL_SIZE_ENABLED requires ar support"); +_Static_assert(!CFREE_TOOL_ADDR2LINE_ENABLED || CFREE_DWARF_ENABLED, + "CFREE_TOOL_ADDR2LINE_ENABLED requires DWARF support"); diff --git a/src/obj/archive_stubs.c b/src/obj/archive_stubs.c @@ -0,0 +1,23 @@ +#include "obj/format.h" + +int obj_format_classify_obj_input_disabled(Compiler* c, ObjBuilder* ob, + Sym* soname_out) { + (void)c; + (void)ob; + if (soname_out) *soname_out = 0; + return 0; +} + +Sym obj_format_archive_hint_disabled(Compiler* c, const char* archive_name) { + (void)c; + (void)archive_name; + return 0; +} + +ObjFormatArchiveAction obj_format_archive_member_disabled( + Compiler* c, const ObjFormatArchiveMember* mem, ObjBuilder** out) { + (void)c; + (void)mem; + if (out) *out = NULL; + return OBJ_FORMAT_ARCHIVE_KEEP; +} diff --git a/src/obj/emu_stubs.c b/src/obj/emu_stubs.c @@ -0,0 +1,3 @@ +#include "obj/format.h" + +const ObjFormatEmuOps elf_emu_ops = {0}; diff --git a/src/obj/link_stubs.c b/src/obj/link_stubs.c @@ -0,0 +1,28 @@ +#include "core/core.h" +#include "obj/format.h" + +void obj_format_link_emit_disabled(LinkImage* img, Writer* w) { + (void)img; + (void)w; +} + +void obj_format_layout_dyn_disabled(Linker* l, LinkImage* img) { + (void)l; + (void)img; +} + +void obj_format_free_dyn_disabled(LinkImage* img) { (void)img; } + +void obj_format_macho_stub_disabled(u8* dst, u64 stub_vaddr, + u64 got_slot_vaddr) { + (void)dst; + (void)stub_vaddr; + (void)got_slot_vaddr; +} + +void obj_format_coff_stub_disabled(u8* dst, u64 stub_vaddr, + u64 iat_slot_vaddr) { + (void)dst; + (void)stub_vaddr; + (void)iat_slot_vaddr; +} diff --git a/src/obj/obj.h b/src/obj/obj.h @@ -724,6 +724,5 @@ ObjBuilder* read_macho_dso(Compiler*, const char* name, const u8* data, * The arch string ("arm64" or "x86_64") comes from Compiler.target. */ ObjBuilder* read_tbd(Compiler*, const char* name, const u8* data, size_t len, Sym* install_name_out); -ObjBuilder* read_wasm(Compiler*, const char* name, const u8* data, size_t len); #endif diff --git a/src/obj/registry.c b/src/obj/registry.c @@ -8,30 +8,58 @@ #include "obj/macho/macho.h" #include "obj/obj.h" +#if CFREE_LINK_ENABLED void link_emit_elf(LinkImage*, Writer*); void link_emit_macho(LinkImage*, Writer*); void link_emit_coff(LinkImage*, Writer*); - -#if CFREE_OBJ_ELF_ENABLED void layout_dyn(Linker*, LinkImage*); void link_dyn_state_free(LinkImage*); -extern const ObjFormatEmuOps elf_emu_ops; +#define OBJ_LINK_EMIT_ELF link_emit_elf +#define OBJ_LINK_EMIT_MACHO link_emit_macho +#define OBJ_LINK_EMIT_COFF link_emit_coff +#define OBJ_LAYOUT_DYN layout_dyn +#define OBJ_FREE_DYN link_dyn_state_free +#else +void obj_format_link_emit_disabled(LinkImage*, Writer*); +void obj_format_layout_dyn_disabled(Linker*, LinkImage*); +void obj_format_free_dyn_disabled(LinkImage*); +#define OBJ_LINK_EMIT_ELF obj_format_link_emit_disabled +#define OBJ_LINK_EMIT_MACHO obj_format_link_emit_disabled +#define OBJ_LINK_EMIT_COFF obj_format_link_emit_disabled +#define OBJ_LAYOUT_DYN obj_format_layout_dyn_disabled +#define OBJ_FREE_DYN obj_format_free_dyn_disabled #endif -#if CFREE_OBJ_COFF_ENABLED +extern const ObjFormatEmuOps elf_emu_ops; + +#if CFREE_AR_ENABLED int coff_classify_obj_input(Compiler*, ObjBuilder*, Sym* soname_out); Sym coff_archive_hint(Compiler*, const char* archive_name); ObjFormatArchiveAction coff_archive_member(Compiler*, const ObjFormatArchiveMember*, ObjBuilder** out); +#else +int obj_format_classify_obj_input_disabled(Compiler*, ObjBuilder*, + Sym* soname_out); +Sym obj_format_archive_hint_disabled(Compiler*, const char* archive_name); +ObjFormatArchiveAction obj_format_archive_member_disabled( + Compiler*, const ObjFormatArchiveMember*, ObjBuilder** out); +#define coff_classify_obj_input obj_format_classify_obj_input_disabled +#define coff_archive_hint obj_format_archive_hint_disabled +#define coff_archive_member obj_format_archive_member_disabled #endif -#if CFREE_ARCH_AA64_ENABLED +#if CFREE_LINK_ENABLED void aa64_emit_macho_stub(u8* dst, u64 stub_vaddr, u64 got_slot_vaddr); void aa64_emit_coff_iat_stub(u8* dst, u64 stub_vaddr, u64 iat_slot_vaddr); -#endif -#if CFREE_ARCH_X64_ENABLED void x64_emit_coff_iat_stub(u8* dst, u64 stub_vaddr, u64 iat_slot_vaddr); +#else +void obj_format_macho_stub_disabled(u8* dst, u64 stub_vaddr, + u64 got_slot_vaddr); +void obj_format_coff_stub_disabled(u8* dst, u64 stub_vaddr, u64 iat_slot_vaddr); +#define aa64_emit_macho_stub obj_format_macho_stub_disabled +#define aa64_emit_coff_iat_stub obj_format_coff_stub_disabled +#define x64_emit_coff_iat_stub obj_format_coff_stub_disabled #endif #if CFREE_OBJ_ELF_ENABLED @@ -206,17 +234,22 @@ static const ObjCoffArchOps* obj_coff_machine(u16 machine) { } #endif +#if CFREE_OBJ_WASM_ENABLED static const ObjFormatImpl obj_format_impl_wasm = { .kind = CFREE_OBJ_WASM, .bin_fmt = CFREE_BIN_WASM, .name = "wasm", - .read_name = "read_wasm", + /* Wasm core modules are frontend inputs. A linkable Wasm object reader + * needs tool-conventions `linking` / `reloc.*` support and is still + * pending, so do not advertise a generic object reader here. */ + .read_name = NULL, .read_dso_name = NULL, .emit = emit_wasm, - .read = read_wasm, + .read = NULL, .read_dso = NULL, .link_emit = NULL, }; +#endif #if CFREE_OBJ_ELF_ENABLED static const ObjFormatImpl obj_format_impl_elf = { @@ -228,9 +261,9 @@ static const ObjFormatImpl obj_format_impl_elf = { .emit = emit_elf, .read = read_elf, .read_dso = read_elf_dso, - .link_emit = link_emit_elf, - .layout_dyn = layout_dyn, - .free_dyn = link_dyn_state_free, + .link_emit = OBJ_LINK_EMIT_ELF, + .layout_dyn = OBJ_LAYOUT_DYN, + .free_dyn = OBJ_FREE_DYN, .emu = &elf_emu_ops, .elf_arch = obj_elf_arch, .elf_machine = obj_elf_machine, @@ -247,7 +280,7 @@ static const ObjFormatImpl obj_format_impl_macho = { .emit = emit_macho, .read = read_macho, .read_dso = read_macho_dso, - .link_emit = link_emit_macho, + .link_emit = OBJ_LINK_EMIT_MACHO, .macho_arch = obj_macho_arch, .macho_cputype = obj_macho_cputype, }; @@ -263,7 +296,7 @@ static const ObjFormatImpl obj_format_impl_coff = { .emit = emit_coff, .read = read_coff, .read_dso = read_coff_dso, - .link_emit = link_emit_coff, + .link_emit = OBJ_LINK_EMIT_COFF, .coff_arch = obj_coff_arch, .coff_machine = obj_coff_machine, .classify_obj_input = coff_classify_obj_input, @@ -282,7 +315,9 @@ static const ObjFormatImpl* const obj_format_impls[] = { #if CFREE_OBJ_MACHO_ENABLED &obj_format_impl_macho, #endif +#if CFREE_OBJ_WASM_ENABLED &obj_format_impl_wasm, +#endif }; const ObjFormatImpl* obj_format_lookup(ObjFmt fmt) {