kit

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

commit fe074537ddf0db080abc3cc1080993eaf382cc7d
parent 3cd976f9a92c23fee94ad15a98803084674e8990
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 25 May 2026 20:18:25 -0700

Disable native backends for C target cutover

Diffstat:
MMakefile | 6+++---
Minclude/cfree/config.h | 10+++++-----
Msrc/abi/registry.c | 29++++++++++++++++++++++-------
Msrc/arch/c_target/emit.c | 45+++++++++++++++++++++++++++++++++------------
Msrc/arch/c_target/target.c | 2++
Msrc/arch/registry.c | 6+++++-
Msrc/cg/session.c | 4++++
7 files changed, 74 insertions(+), 28 deletions(-)

diff --git a/Makefile b/Makefile @@ -222,7 +222,7 @@ endif ifeq ($(CFREE_OBJ_COFF_ENABLED),1) LIB_SRCS += $(LIB_SRCS_OBJ_COFF) endif -ifeq ($(CFREE_ARCH_AA64_ENABLED),1) +ifneq ($(filter 1,$(CFREE_ARCH_AA64_ENABLED) $(CFREE_ARCH_C_TARGET_ENABLED)),) ifneq ($(filter 1,$(CFREE_OBJ_ELF_ENABLED) $(CFREE_OBJ_MACHO_ENABLED) $(CFREE_OBJ_COFF_ENABLED)),) LIB_SRCS += $(LIB_SRC_ABI_AAPCS64) endif @@ -233,7 +233,7 @@ ifeq ($(CFREE_OBJ_COFF_ENABLED),1) LIB_SRCS += $(LIB_SRC_ABI_AAPCS64_WINDOWS) endif endif -ifeq ($(CFREE_ARCH_X64_ENABLED),1) +ifneq ($(filter 1,$(CFREE_ARCH_X64_ENABLED) $(CFREE_ARCH_C_TARGET_ENABLED)),) ifneq ($(filter 1,$(CFREE_OBJ_ELF_ENABLED) $(CFREE_OBJ_MACHO_ENABLED)),) LIB_SRCS += $(LIB_SRC_ABI_SYSV_X64) endif @@ -244,7 +244,7 @@ ifeq ($(CFREE_OBJ_COFF_ENABLED),1) LIB_SRCS += $(LIB_SRC_ABI_WIN64_X64) endif endif -ifeq ($(CFREE_ARCH_RV64_ENABLED),1) +ifneq ($(filter 1,$(CFREE_ARCH_RV64_ENABLED) $(CFREE_ARCH_C_TARGET_ENABLED)),) ifeq ($(CFREE_OBJ_ELF_ENABLED),1) LIB_SRCS += $(LIB_SRC_ABI_RV64) endif diff --git a/include/cfree/config.h b/include/cfree/config.h @@ -24,10 +24,10 @@ */ /* Backend architectures. */ -#define CFREE_ARCH_AA64_ENABLED 1 -#define CFREE_ARCH_X64_ENABLED 1 -#define CFREE_ARCH_RV64_ENABLED 1 -#define CFREE_ARCH_WASM_ENABLED 1 +#define CFREE_ARCH_AA64_ENABLED 0 +#define CFREE_ARCH_X64_ENABLED 0 +#define CFREE_ARCH_RV64_ENABLED 0 +#define CFREE_ARCH_WASM_ENABLED 0 #define CFREE_ARCH_C_TARGET_ENABLED 1 /* Object/image formats. Each gates emit + read + link-image paths and @@ -54,7 +54,7 @@ /* Optimizer pipeline. -O0/direct codegen is always available; -O1 and above * require this flag and the matching src/opt sources. */ -#define CFREE_OPT_ENABLED 1 +#define CFREE_OPT_ENABLED 0 /* Optional library subsystems. These are kept separate from driver tool flags: * libcfree embedders care mostly about whether a public subsystem and its diff --git a/src/abi/registry.c b/src/abi/registry.c @@ -10,31 +10,42 @@ typedef struct ABIImpl { const ABIVtable* vt; } ABIImpl; +#define CFREE_ABI_AA64_ENABLED \ + (CFREE_ARCH_AA64_ENABLED || CFREE_ARCH_C_TARGET_ENABLED) +#define CFREE_ABI_X64_ENABLED \ + (CFREE_ARCH_X64_ENABLED || CFREE_ARCH_C_TARGET_ENABLED) +#define CFREE_ABI_RV64_ENABLED \ + (CFREE_ARCH_RV64_ENABLED || CFREE_ARCH_C_TARGET_ENABLED) + static const ABIImpl abi_impls[] = { -#if CFREE_ARCH_AA64_ENABLED && CFREE_OBJ_ELF_ENABLED +#if CFREE_ABI_AA64_ENABLED && CFREE_OBJ_ELF_ENABLED {CFREE_ARCH_ARM_64, CFREE_OBJ_ELF, &aapcs64_vtable}, #endif -#if CFREE_ARCH_AA64_ENABLED && CFREE_OBJ_MACHO_ENABLED +#if CFREE_ABI_AA64_ENABLED && CFREE_OBJ_MACHO_ENABLED {CFREE_ARCH_ARM_64, CFREE_OBJ_MACHO, &apple_arm64_vtable}, #endif -#if CFREE_ARCH_AA64_ENABLED && CFREE_OBJ_COFF_ENABLED +#if CFREE_ABI_AA64_ENABLED && CFREE_OBJ_COFF_ENABLED {CFREE_ARCH_ARM_64, CFREE_OBJ_COFF, &aapcs64_windows_vtable}, #endif -#if CFREE_ARCH_X64_ENABLED && CFREE_OBJ_ELF_ENABLED +#if CFREE_ABI_X64_ENABLED && CFREE_OBJ_ELF_ENABLED {CFREE_ARCH_X86_64, CFREE_OBJ_ELF, &sysv_x64_vtable}, #endif -#if CFREE_ARCH_X64_ENABLED && CFREE_OBJ_MACHO_ENABLED +#if CFREE_ABI_X64_ENABLED && CFREE_OBJ_MACHO_ENABLED {CFREE_ARCH_X86_64, CFREE_OBJ_MACHO, &apple_x64_vtable}, #endif -#if CFREE_ARCH_X64_ENABLED && CFREE_OBJ_COFF_ENABLED +#if CFREE_ABI_X64_ENABLED && CFREE_OBJ_COFF_ENABLED {CFREE_ARCH_X86_64, CFREE_OBJ_COFF, &win64_x64_vtable}, #endif -#if CFREE_ARCH_RV64_ENABLED && CFREE_OBJ_ELF_ENABLED +#if CFREE_ABI_RV64_ENABLED && CFREE_OBJ_ELF_ENABLED {CFREE_ARCH_RV64, CFREE_OBJ_ELF, &rv64_vtable}, #endif #if CFREE_ARCH_WASM_ENABLED && CFREE_OBJ_WASM_ENABLED {CFREE_ARCH_WASM, CFREE_OBJ_WASM, &wasm32_vtable}, #endif +#if !CFREE_ABI_AA64_ENABLED && !CFREE_ABI_X64_ENABLED && \ + !CFREE_ABI_RV64_ENABLED && !CFREE_ARCH_WASM_ENABLED + {CFREE_ARCH_WASM, CFREE_OBJ_WASM, NULL}, +#endif }; const ABIVtable* abi_vtable_lookup(CfreeArchKind arch, CfreeObjFmt obj) { @@ -45,3 +56,7 @@ const ABIVtable* abi_vtable_lookup(CfreeArchKind arch, CfreeObjFmt obj) { } return NULL; } + +#undef CFREE_ABI_AA64_ENABLED +#undef CFREE_ABI_X64_ENABLED +#undef CFREE_ABI_RV64_ENABLED diff --git a/src/arch/c_target/emit.c b/src/arch/c_target/emit.c @@ -2059,6 +2059,35 @@ static void c_emit_call_arg(CTarget* t, const CGABIValue* v) { c_emit_operand(t, op); } +const char* c_tail_call_unrealizable_reason(CGTarget* T, + const CGCallDesc* d) { + CTarget* t = (CTarget*)T; + SrcLoc loc = t->cur_fn ? t->cur_fn->loc : (SrcLoc){0, 0, 0}; + const CgType* fty = cg_type_get(t->c, api_unalias_type(t->c, d->fn_type)); + if (!fty || fty->kind != CFREE_CG_TYPE_FUNC) { + compiler_panic(t->c, loc, "C target: tail call: bad fn_type"); + } + const CgType* caller = + t->cur_fn + ? cg_type_get(t->c, api_unalias_type(t->c, t->cur_fn->fn_type)) + : NULL; + if (!caller || caller->kind != CFREE_CG_TYPE_FUNC) { + compiler_panic(t->c, loc, "C target: tail call outside function"); + } + if (caller->func.abi_variadic) { + return "C target: caller variadic tail call not yet supported by clang " + "musttail"; + } + if (fty->func.abi_variadic) { + return "C target: variadic tail call not yet supported by clang musttail"; + } + if (caller->func.nparams != fty->func.nparams) { + return "C target: tail call with differing parameter counts not yet " + "supported by clang musttail"; + } + return NULL; +} + void c_call(CGTarget* T, const CGCallDesc* d) { CTarget* t = (CTarget*)T; SrcLoc loc = t->cur_fn ? t->cur_fn->loc : (SrcLoc){0, 0, 0}; @@ -2070,15 +2099,13 @@ void c_call(CGTarget* T, const CGCallDesc* d) { CfreeCgTypeId ret_type = fty->func.ret; int fn_returns = !cg_type_is_void(t->c, ret_type); int is_tail = (d->flags & CG_CALL_TAIL) != 0; - /* When a non-void function is tail-called, CG sets ret.storage to a void - * IMM (the caller will not consume the result). We still need to forward - * the callee's value with a `return` so the enclosing function returns - * something — gcc will tail-call-optimize it on its own. */ + /* When tail-called, CG sets ret.storage to a void IMM and will not emit a + * separate ret. Clang's C statement attribute gives us a checked musttail + * lowering while still spelling the source-level value forwarding exactly. */ /* === Emit the LHS / open the call statement === */ if (is_tail) { - cbuf_puts(&t->body, " "); - if (fn_returns) cbuf_puts(&t->body, "return "); + cbuf_puts(&t->body, " __attribute__((musttail)) return "); } else if (fn_returns) { Operand rs = d->ret.storage; if (rs.kind == OPK_REG) { @@ -2140,12 +2167,6 @@ void c_call(CGTarget* T, const CGCallDesc* d) { c_emit_reg_assign_close(t); } else { cbuf_puts(&t->body, ";\n"); - if (is_tail && !fn_returns) { - /* Void tail call. After this CG won't call ret, so add an explicit - * return so any non-void enclosing function still has a terminating - * statement. (For void-returning enclosing fns this is a no-op.) */ - cbuf_puts(&t->body, " return;\n"); - } } if (is_tail) t->last_was_terminator = 1; } diff --git a/src/arch/c_target/target.c b/src/arch/c_target/target.c @@ -24,6 +24,7 @@ void c_unop(CGTarget*, UnOp, Operand, Operand); void c_cmp(CGTarget*, CmpOp, Operand, Operand, Operand); void c_convert(CGTarget*, ConvKind, Operand, Operand); void c_call(CGTarget*, const CGCallDesc*); +const char* c_tail_call_unrealizable_reason(CGTarget*, const CGCallDesc*); void c_load(CGTarget*, Operand, Operand, MemAccess); void c_store(CGTarget*, Operand, Operand, MemAccess); void c_addr_of(CGTarget*, Operand, Operand); @@ -271,6 +272,7 @@ CGTarget* c_cgtarget_new(Compiler* c, ObjBuilder* o, CfreeWriter* w) { /* ---- calls / return ---- */ t->call = c_call; + t->tail_call_unrealizable_reason = c_tail_call_unrealizable_reason; t->plan_call = c_unimpl_plan_call; t->load_call_arg = c_unimpl_load_call_arg; t->store_call_arg = c_unimpl_store_call_arg; diff --git a/src/arch/registry.c b/src/arch/registry.c @@ -53,6 +53,10 @@ static const ArchImpl* const arch_impls[] = { #if CFREE_ARCH_WASM_ENABLED &arch_impl_wasm, #endif +#if !CFREE_ARCH_AA64_ENABLED && !CFREE_ARCH_X64_ENABLED && \ + !CFREE_ARCH_RV64_ENABLED && !CFREE_ARCH_WASM_ENABLED + NULL, +#endif }; static u32 arch_impls_count(void) { @@ -61,7 +65,7 @@ static u32 arch_impls_count(void) { const ArchImpl* arch_lookup(CfreeArchKind arch) { for (u32 i = 0; i < arch_impls_count(); ++i) { - if (arch_impls[i]->kind == arch) return arch_impls[i]; + if (arch_impls[i] && arch_impls[i]->kind == arch) return arch_impls[i]; } return NULL; } diff --git a/src/cg/session.c b/src/cg/session.c @@ -6,7 +6,9 @@ #include "opt/opt.h" #endif +#if CFREE_ARCH_WASM_ENABLED #include "arch/wasm/wasm_imports.h" +#endif static void cg_free_obj_state(CfreeCg* g) { Heap* h; @@ -202,9 +204,11 @@ CfreeCgSym cfree_cg_decl(CfreeCg* g, CfreeCgDecl decl) { * for other backends is one heap allocation that no one reads. */ if (decl.kind == CFREE_CG_DECL_FUNC && (decl.as.func.wasm_import_module || decl.as.func.wasm_import_name)) { +#if CFREE_ARCH_WASM_ENABLED wasm_imports_set(ob, (Sym)decl.linkage_name, (Sym)decl.as.func.wasm_import_module, (Sym)decl.as.func.wasm_import_name); +#endif } return (CfreeCgSym)sym; }