commit 3081a4983d8aabaad0177a593a25c0491c1bd714
parent 41070170b1823155ec56a416ca5569adf3c5a456
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 27 May 2026 12:50:22 -0700
cg: clear diagnostic when target arch backend isn't built
cfree_cg_begin_obj returned CFREE_UNSUPPORTED when no CGBackend served the
request, which each frontend mislabeled on its own — the C frontend reported
"C compiler out of memory", emu "cfree_cg_new failed", etc. — so a build
compiled without a given arch's backend (CFREE_ARCH_<x>_ENABLED == 0) failed
with a misleading message.
Panic at the shared seam instead, naming the target and distinguishing the
two causes (disabled arch backend vs. disabled C-source backend). Consistent
with the existing opt_level config panics in the same function, so all
frontends get one accurate message:
CfreeCg: no code generator for target arch 'x86_64' — no backend enabled
in this build (CFREE_ARCH_*_ENABLED)
Adds arch_kind_name() to the arch registry — an enablement-independent name
table so a disabled target can still be named.
Diffstat:
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/arch/registry.c b/src/arch/registry.c
@@ -63,6 +63,19 @@ static u32 arch_impls_count(void) {
return (u32)(sizeof arch_impls / sizeof arch_impls[0]);
}
+const char* arch_kind_name(CfreeArchKind arch) {
+ switch (arch) {
+ case CFREE_ARCH_X86_32: return "x86_32";
+ case CFREE_ARCH_X86_64: return "x86_64";
+ case CFREE_ARCH_ARM_32: return "arm32";
+ case CFREE_ARCH_ARM_64: return "aarch64";
+ case CFREE_ARCH_RV32: return "riscv32";
+ case CFREE_ARCH_RV64: return "riscv64";
+ case CFREE_ARCH_WASM: return "wasm";
+ }
+ return "unknown";
+}
+
const ArchImpl* arch_lookup(CfreeArchKind arch) {
for (u32 i = 0; i < arch_impls_count(); ++i) {
if (arch_impls[i] && arch_impls[i]->kind == arch) return arch_impls[i];
diff --git a/src/cg/cgtarget.h b/src/cg/cgtarget.h
@@ -696,4 +696,8 @@ typedef struct CGBackend {
const CGBackend* cg_backend_for_session(const Compiler*,
const CfreeCodeOptions*);
+/* Human-readable arch name for diagnostics, independent of which backends
+ * are compiled in (so it can name a target whose backend is disabled). */
+const char* arch_kind_name(CfreeArchKind);
+
#endif
diff --git a/src/cg/session.c b/src/cg/session.c
@@ -103,7 +103,20 @@ CfreeStatus cfree_cg_begin_obj(CfreeCg* g, CfreeObjBuilder* out,
}
#endif
backend = cg_backend_for_session((Compiler*)c, opts);
- if (!backend) return CFREE_UNSUPPORTED;
+ if (!backend) {
+ /* No CGBackend serves this request in this build. Distinguish the two
+ * causes so the failure is actionable instead of surfacing as a generic
+ * codegen error in each frontend. Consistent with the opt_level config
+ * panics above. */
+ if (opts && opts->emit_c_source)
+ compiler_panic((Compiler*)c, api_no_loc(),
+ "CfreeCg: C-source backend not enabled in this build "
+ "(CFREE_ARCH_C_TARGET_ENABLED)");
+ compiler_panic((Compiler*)c, api_no_loc(),
+ "CfreeCg: no code generator for target arch '%s' — no "
+ "backend enabled in this build (CFREE_ARCH_*_ENABLED)",
+ arch_kind_name(cfree_compiler_target(c).arch));
+ }
target = backend->make((Compiler*)c, (ObjBuilder*)out, opts);
if (!target) return CFREE_UNSUPPORTED;
/* The backend's make() creates the DWARF producer when opts->debug_info