kit

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

commit 500614de42f086b4c4190fc9d736d50e28ec7b23
parent bf6d1df8204f07146354dce4f52030f65135cf08
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu, 14 May 2026 10:15:47 -0700

Remove src include path from C frontend build

Diffstat:
MMakefile | 2+-
Mlang/c/c.c | 2+-
Dlang/c/debug/c_debug.c | 252-------------------------------------------------------------------------------
Dlang/c/debug/c_debug.h | 23-----------------------
Mlang/c/parse/parse.c | 3+--
Mlang/c/parse/parse.h | 4+---
Mlang/c/parse/parse_priv.h | 1-
7 files changed, 4 insertions(+), 283 deletions(-)

diff --git a/Makefile b/Makefile @@ -68,7 +68,7 @@ build/lib/%.o: src/%.c build/lang/c/%.o: lang/c/%.c @mkdir -p $(dir $@) - $(CC) $(CFLAGS_COMMON) -ffreestanding -Iinclude -Ilang/c -Isrc $(DEPFLAGS) -c $< -o $@ + $(CC) $(CFLAGS_COMMON) -ffreestanding -Iinclude -Ilang/c $(DEPFLAGS) -c $< -o $@ build/lib/%.o: src/%.S @mkdir -p $(dir $@) diff --git a/lang/c/c.c b/lang/c/c.c @@ -170,7 +170,7 @@ int cfree_c_compile(CfreeCompiler* c, const CfreeCompileOptions* opts, c_apply_pp_options(pp, &opts->pp); pp_push_input(pp, lex); - parse_c(c, pp, decls, cg, NULL); + parse_c(c, pp, decls, cg); cfree_cg_free(cg); decl_free(decls); diff --git a/lang/c/debug/c_debug.c b/lang/c/debug/c_debug.c @@ -1,252 +0,0 @@ -/* C-type → DebugTypeId adapter. - * - * Walks the C `Type*` chain, calling debug_type_* on the language-neutral - * Debug surface and caching the result keyed by Type* identity. - * - * Identity contract (see c_debug.h): the cache is per-Debug; equal Type* - * (canonical pool pointer) → equal DebugTypeId. Recursive shapes (a - * struct containing a pointer to itself) work because: - * - We allocate the record DIE id first via debug_type_record_begin / - * end and store the id in the cache *before* descending into fields. - * Cyclic references through a pointer get a fresh ptr-DIE that points - * back to the (now-known) record id. - * - Direct cycles (a struct containing itself by value) are illegal in - * C anyway. */ - -#include "debug/c_debug.h" - -#include <string.h> - -#include "core/core.h" -#include "core/heap.h" -#include "core/pool.h" -#include "core/vec.h" -#include "abi/c_abi.h" -#include "debug/debug.h" -#include "debug/debug_internal.h" - -/* Cache: Type* → DebugTypeId. - * - * We attach the cache to the Debug instance via a void* slot. Since - * DebugTypeId is u32 and we use a u64-keyed hashmap (PtrToU32 from the - * internal header), the cache survives the lifetime of one Debug. - * - * The cache is created lazily on first lookup so producers that don't - * use c_debug_type pay nothing. */ - -typedef struct CDebugCache { - PtrToU32 map; /* (u64)(uintptr_t)Type* → DebugTypeId */ -} CDebugCache; - -/* The Debug struct doesn't have a slot for the cache. Rather than - * touching debug.h, we keep a single (Debug* → cache) tiny association - * list. In practice exactly one Debug exists per TU; this list rarely - * grows past 1. */ - -typedef struct CDebugCacheEntry { - Debug* d; - CDebugCache* cache; -} CDebugCacheEntry; - -static CDebugCacheEntry* g_caches = NULL; -static u32 g_caches_n = 0; -static u32 g_caches_cap = 0; - -static CDebugCache* cache_for(Debug* d) { - u32 i; - Heap* h; - for (i = 0; i < g_caches_n; ++i) { - if (g_caches[i].d == d) return g_caches[i].cache; - } - h = (Heap*)d->c->env->heap; - if (VEC_GROW(h, g_caches, g_caches_cap, g_caches_n + 1)) return NULL; - { - CDebugCacheEntry* slot = &g_caches[g_caches_n++]; - slot->d = d; - slot->cache = - (CDebugCache*)h->alloc(h, sizeof(CDebugCache), _Alignof(CDebugCache)); - if (!slot->cache) { - g_caches_n--; - return NULL; - } - PtrToU32_init(&slot->cache->map, h); - return slot->cache; - } -} - -static DebugTypeId cache_get(CDebugCache* c, const Type* t) { - u32* v = PtrToU32_get(&c->map, (u64)(uintptr_t)t); - return v ? *v : DEBUG_TYPE_NONE; -} - -static void cache_put(CDebugCache* c, const Type* t, DebugTypeId id) { - PtrToU32_set(&c->map, (u64)(uintptr_t)t, id); -} - -/* ---- recursive type walk ---- */ - -static DebugTypeId walk(Debug* d, TargetABI* abi, const Type* t, - CDebugCache* cache); - -static Sym intern_cstr(Debug* d, const char* s) { - return pool_intern_cstr(d->c->global, s); -} - -static DebugTypeId base_id(Debug* d, TargetABI* abi, const Type* t, - const char* name, DebugBaseEncoding enc) { - return debug_type_base(d, intern_cstr(d, name), enc, c_abi_sizeof(abi, t)); -} - -static DebugTypeId walk_unqual(Debug* d, TargetABI* abi, const Type* t, - CDebugCache* cache) { - switch ((TypeKind)t->kind) { - case TY_VOID: - return debug_type_void(d); - case TY_BOOL: - return base_id(d, abi, t, "_Bool", DEBUG_BE_BOOL); - case TY_CHAR: - return base_id(d, abi, t, "char", DEBUG_BE_SIGNED_CHAR); - case TY_SCHAR: - return base_id(d, abi, t, "signed char", DEBUG_BE_SIGNED_CHAR); - case TY_UCHAR: - return base_id(d, abi, t, "unsigned char", DEBUG_BE_UNSIGNED_CHAR); - case TY_SHORT: - return base_id(d, abi, t, "short", DEBUG_BE_SIGNED); - case TY_USHORT: - return base_id(d, abi, t, "unsigned short", DEBUG_BE_UNSIGNED); - case TY_INT: - return base_id(d, abi, t, "int", DEBUG_BE_SIGNED); - case TY_UINT: - return base_id(d, abi, t, "unsigned int", DEBUG_BE_UNSIGNED); - case TY_LONG: - return base_id(d, abi, t, "long", DEBUG_BE_SIGNED); - case TY_ULONG: - return base_id(d, abi, t, "unsigned long", DEBUG_BE_UNSIGNED); - case TY_LLONG: - return base_id(d, abi, t, "long long", DEBUG_BE_SIGNED); - case TY_ULLONG: - return base_id(d, abi, t, "unsigned long long", DEBUG_BE_UNSIGNED); - case TY_INT128: - return base_id(d, abi, t, "__int128", DEBUG_BE_SIGNED); - case TY_UINT128: - return base_id(d, abi, t, "unsigned __int128", DEBUG_BE_UNSIGNED); - case TY_FLOAT: - return base_id(d, abi, t, "float", DEBUG_BE_FLOAT); - case TY_DOUBLE: - return base_id(d, abi, t, "double", DEBUG_BE_FLOAT); - case TY_LDOUBLE: - return base_id(d, abi, t, "long double", DEBUG_BE_FLOAT); - case TY_PTR: { - DebugTypeId pointee = walk(d, abi, t->ptr.pointee, cache); - return debug_type_ptr(d, pointee); - } - case TY_ARRAY: { - DebugTypeId elem = walk(d, abi, t->arr.elem, cache); - return debug_type_array(d, elem, t->arr.incomplete ? 0 : t->arr.count); - } - case TY_FUNC: { - DebugTypeId ret = walk(d, abi, t->fn.ret, cache); - DebugTypeId* params = NULL; - DebugTypeId result; - u32 i; - Heap* h = (Heap*)d->c->env->heap; - if (t->fn.nparams) { - params = (DebugTypeId*)h->alloc(h, sizeof(DebugTypeId) * t->fn.nparams, - _Alignof(DebugTypeId)); - if (!params) return DEBUG_TYPE_NONE; - for (i = 0; i < t->fn.nparams; ++i) { - params[i] = walk(d, abi, t->fn.params[i], cache); - } - } - result = debug_type_func(d, ret, params, t->fn.nparams, t->fn.variadic); - if (params) h->free(h, params, sizeof(DebugTypeId) * t->fn.nparams); - return result; - } - case TY_STRUCT: - case TY_UNION: { - const ABIRecordLayout* layout; - DebugTypeBuilder* b; - DebugTypeId id; - u32 i; - if (t->rec.incomplete) { - /* Emit an opaque record: zero size, no fields. */ - b = debug_type_record_begin(d, t->rec.tag, t->kind == TY_UNION, 0, 0); - return debug_type_record_end(b); - } - layout = c_abi_record_layout(abi, t); - b = debug_type_record_begin(d, t->rec.tag, t->kind == TY_UNION, - layout ? layout->size : 0, - layout ? layout->align : 0); - /* Pre-publish the cache entry pointing at the in-progress builder - * id so cycles via pointer fields resolve. We don't have a builder - * id yet; allocate one early via the record_end-then-walk strategy - * is safer. To keep things simple here, we cache after end_record. - * Self-referential pointers must therefore be expressed via a - * `Type*` that points to a *forward-declared* incomplete record - * (handled above), then refined later. For now no test path hits - * this. */ - for (i = 0; i < t->rec.nfields; ++i) { - const Field* f = &t->rec.fields[i]; - DebugTypeId ftype = walk(d, abi, f->type, cache); - u32 byte_ofs = layout ? layout->fields[i].offset : 0; - if (f->flags & FIELD_BITFIELD) { - u16 bit_ofs = layout ? layout->fields[i].bit_offset : 0; - debug_type_record_bitfield(b, f->name, ftype, byte_ofs, bit_ofs, - f->bitfield_width); - } else { - debug_type_record_field(b, f->name, ftype, byte_ofs); - } - } - id = debug_type_record_end(b); - return id; - } - case TY_ENUM: { - DebugTypeId base = walk(d, abi, t->enm.base, cache); - DebugEnumBuilder* b = debug_type_enum_begin(d, t->enm.tag, base); - /* Type doesn't carry enum members directly; we'd need a registry - * lookup keyed by tag_id. Leave empty — consumers see an enum - * with no enumerators. */ - return debug_type_enum_end(b); - } - } - return DEBUG_TYPE_NONE; -} - -static DebugTypeId walk(Debug* d, TargetABI* abi, const Type* t, - CDebugCache* cache) { - DebugTypeId cached; - DebugTypeId base_id_; - DebugTypeId result; - if (!t) return DEBUG_TYPE_NONE; - cached = cache_get(cache, t); - if (cached != DEBUG_TYPE_NONE) return cached; - - /* Strip and re-apply qualifiers. The unqualified type goes into the - * pool as one DIE; const/volatile/restrict layer DIEs around it. */ - if (t->qual) { - /* Build the unqualified core, then layer qualifiers. We can't simply - * re-pool a Type with qual=0 because we don't have a pool here. - * Instead walk fields directly and synthesize. */ - /* Synthesize unqualified DIE from the same shape. We construct a - * shallow Type with qual=0 and recurse via walk_unqual. */ - Type tmp = *t; - tmp.qual = 0; - base_id_ = walk_unqual(d, abi, &tmp, cache); - result = base_id_; - if (t->qual & Q_CONST) result = debug_type_const(d, result); - if (t->qual & Q_VOLATILE) result = debug_type_volatile(d, result); - if (t->qual & Q_RESTRICT) result = debug_type_restrict(d, result); - } else { - result = walk_unqual(d, abi, t, cache); - } - cache_put(cache, t, result); - return result; -} - -DebugTypeId c_debug_type(Debug* d, TargetABI* abi, const Type* t) { - CDebugCache* cache; - if (!d || !t) return DEBUG_TYPE_NONE; - cache = cache_for(d); - if (!cache) return DEBUG_TYPE_NONE; - return walk(d, abi, t, cache); -} diff --git a/lang/c/debug/c_debug.h b/lang/c/debug/c_debug.h @@ -1,23 +0,0 @@ -#ifndef CFREE_C_DEBUG_H -#define CFREE_C_DEBUG_H - -#include "core/core.h" -#include "debug/debug.h" -#include "type/type.h" - -/* C-specific adapter over the language-neutral Debug type DIE API. - * - * Walks a `const Type*` and emits the corresponding tree of debug_type_* - * calls, returning a DebugTypeId that the C frontend (parse / cg) can - * pass to debug_param, debug_local, debug_func_begin, etc. Used only by - * the C frontend; the core Debug module does not depend on `Type`. - * - * Identity: this adapter interns by Type* pointer. CG owns a per-TU - * cache so repeated lookups for the same Type* yield the same id without - * re-walking the chain. The cache lives for the duration of the TU (i.e. - * until debug_emit / debug_free) and is invalidated automatically when - * Debug is freed. */ - -DebugTypeId c_debug_type(Debug*, TargetABI*, const Type*); - -#endif diff --git a/lang/c/parse/parse.c b/lang/c/parse/parse.c @@ -1033,7 +1033,7 @@ static void parse_translation_unit(Parser* p) { * Entry point * ============================================================ */ -void parse_c(Compiler* c, Pp* pp, DeclTable* decls, CG* cg, Debug* debug) { +void parse_c(Compiler* c, Pp* pp, DeclTable* decls, CG* cg) { Parser p; CKw i; @@ -1042,7 +1042,6 @@ void parse_c(Compiler* c, Pp* pp, DeclTable* decls, CG* cg, Debug* debug) { p.pp = pp; p.decls = decls; p.cg = cg; - p.debug = debug; p.abi = c->abi; p.pool = c->global; diff --git a/lang/c/parse/parse.h b/lang/c/parse/parse.h @@ -5,10 +5,8 @@ #include "parse/cg_public_compat.h" #include "pp/pp.h" -typedef struct Debug Debug; - /* C11 frontend. Reads preprocessed tokens, records C declarations, and drives * the public CG API for executable code and object data. */ -void parse_c(Compiler*, Pp*, DeclTable*, CG*, Debug*); +void parse_c(Compiler*, Pp*, DeclTable*, CG*); #endif diff --git a/lang/c/parse/parse_priv.h b/lang/c/parse/parse_priv.h @@ -162,7 +162,6 @@ typedef struct Parser { Pp* pp; DeclTable* decls; CG* cg; - Debug* debug; TargetABI* abi; Pool* pool;