kit

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

commit b3ebd86493250b7a890baa07b4f2ad2106a9470f
parent a39ba2690ba6a6f5179187de2956cfa4df145657
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  1 Jun 2026 13:36:55 -0700

frontends: eliminate the C->src/abi phantom edge, tighten wasm to one boundary

The two documented "frontend reaches into src/" exceptions were asymmetric.

C was a phantom: lang/c builds with no -Isrc and reached nothing internal.
The only residue was `typedef CfreeCompiler TargetABI` in c_support.h, an
alias that borrowed the name of src/abi's struct and faked a coupling. Drop
the alias and use CfreeCompiler directly (param/field names keep the "abi"
hint). Its lang/c/abi/ module is frontend-local, built on the public CG API.

wasm cg.c reached src/wasm/wasm.h (the shared module model) plus core/arena.h
and core/heap.h. The latter two have public mirrors, so migrate them: Arena ->
CfreeArena via <cfree/support/arena.h>, Heap* -> CfreeHeap. OOM behavior is
unchanged (the public arena wraps the internal one). cg.c now reaches only the
one blessed boundary header.

The remaining src/wasm/wasm.h edge stays: it's a Tier-3 subsystem with three
peer consumers (lang/wasm, src/obj/wasm, src/arch/wasm), so it can't move into
the frontend and shouldn't be promoted to the public API. Reclassify it in
INTERFACES.md/FRONTENDS.md as a sanctioned shared-subsystem edge rather than an
exception to eliminate.

Diffstat:
Mdoc/FRONTENDS.md | 9+++++++++
Mdoc/INTERFACES.md | 44++++++++++++++++++++++++++++----------------
Mlang/c/abi/c_abi.c | 22+++++++++++-----------
Mlang/c/abi/c_abi.h | 22+++++++++++-----------
Mlang/c/c_support.h | 2--
Mlang/c/parse/parse_priv.h | 4++--
Mlang/c/parse/parse_type.c | 2+-
Mlang/wasm/cg.c | 82++++++++++++++++++++++++++++++++++++++++----------------------------------------
8 files changed, 103 insertions(+), 84 deletions(-)

diff --git a/doc/FRONTENDS.md b/doc/FRONTENDS.md @@ -302,3 +302,12 @@ module, then lowers it into the CG API (`cg.c`) and synthesizes the host-import ABI shims (`host_imports.c`). Like C and asm it carries no durable cross-compile state (`commit`/`abort` are NULL). The structure and the WAT/binary/lowering details live in [WASM.md](WASM.md). + +The wasm module model it parses into — `WasmModule` and the WAT/binary codec — +is `src/wasm/wasm.h`, a Tier-3 internal subsystem also used by the wasm object +format (`src/obj/wasm`) and codegen backend (`src/arch/wasm`). It is the one +place a frontend depends on `src/` rather than `include/cfree/`, and the reason +is structural: the module IR is large and unstable, so it is shared internally +rather than mirrored into the public API (whose `wasm.h` is the narrow +host-import binder). Everything else the frontend touches — codegen, arena, heap +— is public. See [INTERFACES.md](INTERFACES.md) for the boundary rationale. diff --git a/doc/INTERFACES.md b/doc/INTERFACES.md @@ -21,9 +21,9 @@ From the outside in (see [DESIGN.md](DESIGN.md) for the full narrative): driver/ CLI policy + host I/O. Built with -Iinclude only: │ the public surface is all it can reach. No -Isrc. └─ lang/ Frontends (c, cpp, toy, wasm). Compiled INTO libcfree. - │ API consumers in spirit; built with -Isrc, so they may - │ reach a few internal headers where the public API has - │ no equivalent (C ABI, wasm module model). + │ Public-API consumers: c/cpp/toy build with NO -Isrc and + │ reach nothing internal. Only wasm builds with -Isrc, to + │ reach the shared wasm module model (src/wasm/wasm.h). └─ include/cfree/ PUBLIC BOUNDARY. The library's entire external contract. └─ src/api/ Composition layer: public handles <-> internal subsystems. └─ src/ Internal subsystems. Share private headers; expose @@ -38,14 +38,25 @@ physically unreachable from it. That makes the driver the first true consumer of libcfree's public API and the thing that proves the public surface is sufficient. -Frontends in `lang/` are a softer boundary: they are built as part of -`libcfree.a` (with `-Isrc`), so the compiler does not stop them from including an -internal header. They are expected to live on `include/cfree/` and almost -entirely do; the deliberate exceptions are the C frontend reaching -`abi/c_abi.h` for C-specific ABI lowering and the wasm frontend reaching -`wasm/wasm.h` for the shared module model. New frontend code that reaches into -`src/` for anything else is a signal the public API is missing something — add it -to `include/cfree/`, don't widen the exception list. +Frontends in `lang/` are a softer boundary, but in practice they hold the public +line. The C, cpp, and toy frontends build with **no `-Isrc`** at all, so internal +headers are physically unreachable from them — they are pure `include/cfree/` +consumers, exactly like the driver. (The C frontend's ABI lowering lives in its +own `lang/c/abi/` module built on the public CG type API and `cfree_compiler_target`; +despite the `TargetABI`-flavored history it does not touch `src/abi/`.) + +The lone exception is the **wasm frontend**, which builds with `-Isrc` to reach +`src/wasm/wasm.h`. That is not a frontend punching above the public API: the wasm +module model is a Tier-3 shared internal subsystem with three peer consumers — +the frontend (`lang/wasm`), the wasm object format (`src/obj/wasm`), and the wasm +codegen backend (`src/arch/wasm`) — and the frontend reaches it through its single +boundary header, the same way the other two do. It stays internal rather than +public because the module IR is large and unstable; the public `wasm.h` is a +deliberately different, narrow surface (host-import binding). Everything else the +wasm frontend touches is public — e.g. `lang/wasm/cg.c` allocates through the +public `<cfree/support/arena.h>` mirror, not `src/core/arena.h`. Any *new* frontend +reach into `src/` beyond this one edge is a signal the public API is missing +something — add it to `include/cfree/`, don't grow the edge. **Invariants (keep them true):** - There is **no** whole-library umbrella `include/cfree.h`. Consumers include @@ -221,7 +232,7 @@ subsystems are allowed to include; the internal header is not. | dbg | `<cfree/dbg.h>` (public face) | `src/dbg/dbg.h` | JIT execution control; the real contract is the public header. | | asm | `src/asm/asm.h` (+ `asm_lex.h`) | `asm_helpers.h` shared | `asm_parse(Compiler, AsmLexer, MCEmitter)`; driver helpers. | | jit | `src/jit/tlv_thunk.h` | — | Mach-O TLV thunk; the rest of JIT runs through `LinkImage`. | -| wasm | `src/wasm/wasm.h` | — | Module model / codec / WAT / validate, in terms of public Cfree types. | +| wasm | `src/wasm/wasm.h` | — | Module model / codec / WAT / validate, in public Cfree types. Shared by three peers: the wasm frontend (`lang/wasm`), object format (`src/obj/wasm`), and codegen backend (`src/arch/wasm`). | | api | `src/api/lang_registry.h` | — | `lang_registry_init(Compiler)` wires the enabled frontends. | **Subsystem-tier notes:** @@ -287,14 +298,15 @@ single front door: `<cfree/frontend.h>` re-exports `cg.h`, `compile.h`, frontend TU includes just that one header. The remaining direct public includes are the ones *outside* the facade — `support/hashmap.h` for hashed tables, and `preprocess.h` / `jit.h` / `wasm.h` where a specific frontend or runner needs -them — plus the two documented internal exceptions noted in the boundary map. +them — plus the single documented frontend→subsystem edge noted in the boundary +map (the wasm frontend reaching `src/wasm/wasm.h`). | Frontend | Public entry | Notable internal headers | |----------|--------------|--------------------------| -| C (`lang/c/`) | `cfree_c_frontend_vtable` (`c.h`) | `type/`, `decl/`, `sem/`, `parse/parse.h`; reaches `abi/c_abi.h` for C ABI lowering | +| C (`lang/c/`) | `cfree_c_frontend_vtable` (`c.h`) | none in `src/` — `type/`, `decl/`, `sem/`, `parse/`, `abi/` are frontend-local modules over the public CG API | | cpp (`lang/cpp/`) | shared by C; `pp/pp.h`, `lex/lex.h` | `cpp_support.h`, `pp/pp_priv.h` | | toy (`lang/toy/`) | `cfree_toy_frontend_vtable` (`toy.h`) | `internal.h`, `lexer.h` | -| wasm (`lang/wasm/`) | `cfree_wasm_frontend_vtable` (`wasm.h`) | reaches `wasm/wasm.h` (shared module model) | +| wasm (`lang/wasm/`) | `cfree_wasm_frontend_vtable` (`wasm.h`) | `src/wasm/wasm.h` — the shared module-model subsystem; the one frontend→`src/` edge | **Frontend-tier notes:** - `lang/c/parse/cg_adapter.h` is the C parser's codegen adapter: it wraps `cg.h` @@ -317,7 +329,7 @@ lighter. - [ ] Header lives at the right tier; consumers at the correct layer can reach it. - [ ] No layering violation: the driver uses only `<cfree/*.h>`; subsystems don't include each other's `*_internal.h`; a frontend reaches into `src/` only - via the documented C-ABI / wasm-module exceptions. + via the one documented edge (the wasm frontend → `src/wasm/wasm.h`). - [ ] Format/arch/OS specifics stay behind their dispatch vtable (`ObjFormatImpl`, `ArchImpl`, the codegen `*Target` structs) — not leaked above it. diff --git a/lang/c/abi/c_abi.c b/lang/c/abi/c_abi.c @@ -19,7 +19,7 @@ static int c_type_is_signed_integer(const Type* t) { } } -ABITypeInfo c_abi_type_info(TargetABI* a, const Type* t) { +ABITypeInfo c_abi_type_info(CfreeCompiler* a, const Type* t) { CfreeCgTypeId id = type_cg_id(a, t); CfreeCgTypeKind kind = cfree_cg_type_kind(a, id); ABITypeInfo r; @@ -51,15 +51,15 @@ ABITypeInfo c_abi_type_info(TargetABI* a, const Type* t) { return r; } -u32 c_abi_sizeof(TargetABI* a, const Type* t) { +u32 c_abi_sizeof(CfreeCompiler* a, const Type* t) { return c_abi_type_info(a, t).size; } -u32 c_abi_alignof(TargetABI* a, const Type* t) { +u32 c_abi_alignof(CfreeCompiler* a, const Type* t) { return c_abi_type_info(a, t).align; } -const ABIRecordLayout* c_abi_record_layout(TargetABI* a, Pool* p, +const ABIRecordLayout* c_abi_record_layout(CfreeCompiler* a, Pool* p, const Type* t) { CfreeCgTypeId id = type_cg_id_in_pool(a, p, t); ABIRecordLayout* L; @@ -94,7 +94,7 @@ const ABIRecordLayout* c_abi_record_layout(TargetABI* a, Pool* p, return L; } -const ABIFuncInfo* c_abi_func_info(TargetABI* a, Pool* p, const Type* fn_type) { +const ABIFuncInfo* c_abi_func_info(CfreeCompiler* a, Pool* p, const Type* fn_type) { CfreeCgTypeId id = type_cg_id_in_pool(a, p, fn_type); ABIFuncInfo* info; uint32_t nparams; @@ -110,29 +110,29 @@ const ABIFuncInfo* c_abi_func_info(TargetABI* a, Pool* p, const Type* fn_type) { return info; } -static const Type* c_size_or_uintptr(TargetABI* a, Pool* p) { +static const Type* c_size_or_uintptr(CfreeCompiler* a, Pool* p) { CfreeTarget target = cfree_compiler_target(a); return target.ptr_size == 8 ? type_prim(p, TY_ULLONG) : type_prim(p, TY_UINT); } -const Type* c_abi_size_type(TargetABI* a, Pool* p) { +const Type* c_abi_size_type(CfreeCompiler* a, Pool* p) { return c_size_or_uintptr(a, p); } -const Type* c_abi_ptrdiff_type(TargetABI* a, Pool* p) { +const Type* c_abi_ptrdiff_type(CfreeCompiler* a, Pool* p) { CfreeTarget target = cfree_compiler_target(a); return target.ptr_size == 8 ? type_prim(p, TY_LLONG) : type_prim(p, TY_INT); } -const Type* c_abi_intptr_type(TargetABI* a, Pool* p) { +const Type* c_abi_intptr_type(CfreeCompiler* a, Pool* p) { return c_abi_ptrdiff_type(a, p); } -const Type* c_abi_uintptr_type(TargetABI* a, Pool* p) { +const Type* c_abi_uintptr_type(CfreeCompiler* a, Pool* p) { return c_size_or_uintptr(a, p); } -const Type* c_abi_va_list_type(TargetABI* a, Pool* p) { +const Type* c_abi_va_list_type(CfreeCompiler* a, Pool* p) { CfreeTarget target = cfree_compiler_target(a); switch (target.arch) { case CFREE_ARCH_X86_64: { diff --git a/lang/c/abi/c_abi.h b/lang/c/abi/c_abi.h @@ -44,16 +44,16 @@ typedef struct ABIFuncInfo { u16 nparams; } ABIFuncInfo; -ABITypeInfo c_abi_type_info(TargetABI*, const Type*); -u32 c_abi_sizeof(TargetABI*, const Type*); -u32 c_abi_alignof(TargetABI*, const Type*); -const ABIRecordLayout* c_abi_record_layout(TargetABI*, Pool*, const Type*); -const ABIFuncInfo* c_abi_func_info(TargetABI*, Pool*, const Type*); - -const Type* c_abi_size_type(TargetABI*, Pool*); -const Type* c_abi_ptrdiff_type(TargetABI*, Pool*); -const Type* c_abi_intptr_type(TargetABI*, Pool*); -const Type* c_abi_uintptr_type(TargetABI*, Pool*); -const Type* c_abi_va_list_type(TargetABI*, Pool*); +ABITypeInfo c_abi_type_info(CfreeCompiler*, const Type*); +u32 c_abi_sizeof(CfreeCompiler*, const Type*); +u32 c_abi_alignof(CfreeCompiler*, const Type*); +const ABIRecordLayout* c_abi_record_layout(CfreeCompiler*, Pool*, const Type*); +const ABIFuncInfo* c_abi_func_info(CfreeCompiler*, Pool*, const Type*); + +const Type* c_abi_size_type(CfreeCompiler*, Pool*); +const Type* c_abi_ptrdiff_type(CfreeCompiler*, Pool*); +const Type* c_abi_intptr_type(CfreeCompiler*, Pool*); +const Type* c_abi_uintptr_type(CfreeCompiler*, Pool*); +const Type* c_abi_va_list_type(CfreeCompiler*, Pool*); #endif diff --git a/lang/c/c_support.h b/lang/c/c_support.h @@ -7,8 +7,6 @@ #include "cpp_support.h" -typedef CfreeCompiler TargetABI; - typedef struct SrcRange { SrcLoc begin; SrcLoc end; diff --git a/lang/c/parse/parse_priv.h b/lang/c/parse/parse_priv.h @@ -204,7 +204,7 @@ typedef struct Parser { Pp* pp; DeclTable* decls; CG* cg; - TargetABI* abi; + CfreeCompiler* abi; Pool* pool; u8 default_visibility; /* SymVis */ @@ -499,7 +499,7 @@ int starts_type_name(const Parser* p, const Tok* t); int starts_attr(const Parser* p); Attr* parse_attribute_spec_list(Parser* p); void parse_and_discard_attributes(Parser* p); -int find_field(TargetABI* abi, Pool* pool, const Type* rec, Sym name, +int find_field(CfreeCompiler* abi, Pool* pool, const Type* rec, Sym name, const Type** out_type, u32* out_offset, const Field** out_field); u32 attrs_pick_aligned(const Attr* a); void attr_list_append(Attr** head, Attr* add); diff --git a/lang/c/parse/parse_type.c b/lang/c/parse/parse_type.c @@ -832,7 +832,7 @@ int parse_decl_specs(Parser* p, DeclSpecs* out) { * struct / union / enum * ============================================================ */ -int find_field(TargetABI* abi, Pool* pool, const Type* rec, Sym name, +int find_field(CfreeCompiler* abi, Pool* pool, const Type* rec, Sym name, const Type** out_type, u32* out_offset, const Field** out_field) { if (!rec || (rec->kind != TY_STRUCT && rec->kind != TY_UNION)) return 0; diff --git a/lang/wasm/cg.c b/lang/wasm/cg.c @@ -1,5 +1,4 @@ -#include "core/arena.h" -#include "core/heap.h" +#include <cfree/support/arena.h> #include "wasm/wasm.h" static CfreeCgTypeId wasm_cg_type(CfreeCompiler* c, CfreeCgBuiltinTypes b, @@ -260,7 +259,7 @@ static uint64_t wasm_cg_field_offset(CfreeCompiler* c, CfreeCgTypeId ty, static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b, const WasmModule* m, WasmCgRuntime* rt, - Arena* arena) { + CfreeArena* arena) { CfreeCgField memory_fields[4]; CfreeCgField func_import_fields[1]; CfreeCgField global_import_fields[1]; @@ -275,7 +274,7 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b, uint32_t instance_cap = m->nmemories + m->nfuncs + m->nfuncs + m->nglobals + 2u * m->ntables + m->ndata + 2u * m->nelems; CfreeCgField* instance_fields = - instance_cap ? arena_zarray(arena, CfreeCgField, instance_cap) : NULL; + instance_cap ? cfree_arena_zarray(arena, CfreeCgField, instance_cap) : NULL; uint32_t nfields = 0; uint32_t memory_field_idx[64]; uint32_t func_import_field_idx[64]; @@ -285,23 +284,23 @@ static void wasm_cg_build_runtime(CfreeCompiler* c, CfreeCgBuiltinTypes b, uint32_t table_entries_field_idx[64]; memset(rt, 0, sizeof *rt); rt->memory_field = - m->nmemories ? arena_zarray(arena, uint32_t, m->nmemories) : NULL; + m->nmemories ? cfree_arena_zarray(arena, uint32_t, m->nmemories) : NULL; rt->func_import_field = - m->nfuncs ? arena_zarray(arena, uint32_t, m->nfuncs) : NULL; + m->nfuncs ? cfree_arena_zarray(arena, uint32_t, m->nfuncs) : NULL; rt->func_ref_entry_field = - m->nfuncs ? arena_zarray(arena, uint32_t, m->nfuncs) : NULL; + m->nfuncs ? cfree_arena_zarray(arena, uint32_t, m->nfuncs) : NULL; rt->global_field = - m->nglobals ? arena_zarray(arena, uint32_t, m->nglobals) : NULL; + m->nglobals ? cfree_arena_zarray(arena, uint32_t, m->nglobals) : NULL; rt->table_field = - m->ntables ? arena_zarray(arena, uint32_t, m->ntables) : NULL; + m->ntables ? cfree_arena_zarray(arena, uint32_t, m->ntables) : NULL; rt->table_entries_field = - m->ntables ? arena_zarray(arena, uint32_t, m->ntables) : NULL; + m->ntables ? cfree_arena_zarray(arena, uint32_t, m->ntables) : NULL; rt->passive_data_field = - m->ndata ? arena_zarray(arena, uint32_t, m->ndata) : NULL; + m->ndata ? cfree_arena_zarray(arena, uint32_t, m->ndata) : NULL; rt->passive_elem_field = - m->nelems ? arena_zarray(arena, uint32_t, m->nelems) : NULL; + m->nelems ? cfree_arena_zarray(arena, uint32_t, m->nelems) : NULL; rt->passive_elem_storage_field = - m->nelems ? arena_zarray(arena, uint32_t, m->nelems) : NULL; + m->nelems ? cfree_arena_zarray(arena, uint32_t, m->nelems) : NULL; rt->i8_ptr_ty = cfree_cg_type_ptr(c, b.id[CFREE_CG_BUILTIN_I8], 0); rt->void_ptr_ty = rt->i8_ptr_ty; memset(memory_fields, 0, sizeof memory_fields); @@ -997,10 +996,10 @@ static void wasm_cg_call_func(CfreeCompiler* c, CfreeCg* cg, const WasmCgRuntime* rt, CfreeCgSym sym, CfreeCgTypeId func_type, CfreeCgLocal instance_local, uint32_t func_index, - int must_tail, CfreeSrcLoc loc, Arena* arena) { + int must_tail, CfreeSrcLoc loc, CfreeArena* arena) { CfreeCgLocalAttrs attrs; CfreeCgLocal* args = - f->nparams ? arena_array(arena, CfreeCgLocal, f->nparams) : NULL; + f->nparams ? cfree_arena_array(arena, CfreeCgLocal, f->nparams) : NULL; CfreeCgLocal callee = CFREE_CG_LOCAL_NONE; (void)loc; memset(&attrs, 0, sizeof attrs); @@ -1074,7 +1073,7 @@ static void wasm_cg_emit_host_import_metadata(CfreeCompiler* c, CfreeCg* cg, CfreeCgBuiltinTypes b, const WasmModule* m, const WasmCgRuntime* rt, - Arena* arena) { + CfreeArena* arena) { CfreeCgTypeId u32_ty = b.id[CFREE_CG_BUILTIN_I32]; CfreeCgTypeId u8_ty = b.id[CFREE_CG_BUILTIN_I8]; CfreeCgTypeId ptr_ty = rt->void_ptr_ty; @@ -1128,10 +1127,10 @@ static void wasm_cg_emit_host_import_metadata(CfreeCompiler* c, CfreeCg* cg, uint32_t local_typeidx; /* index into the emitted types array */ uint32_t slot_offset; } WasmImportEmit; - WasmImportEmit* descs = arena_zarray(arena, WasmImportEmit, nimports); + WasmImportEmit* descs = cfree_arena_zarray(arena, WasmImportEmit, nimports); uint32_t* type_remap = - arena_zarray(arena, uint32_t, m->ntypes ? m->ntypes : 1u); - uint32_t* local_to_module = arena_zarray(arena, uint32_t, nimports); + cfree_arena_zarray(arena, uint32_t, m->ntypes ? m->ntypes : 1u); + uint32_t* local_to_module = cfree_arena_zarray(arena, uint32_t, nimports); uint32_t ntypes = 0; uint32_t d = 0; for (i = 0; i < m->ntypes; ++i) type_remap[i] = UINT32_MAX; @@ -1173,17 +1172,17 @@ static void wasm_cg_emit_host_import_metadata(CfreeCompiler* c, CfreeCg* cg, * Each typeidx referenced by an import gets one entry. Param/result bytes * are emitted as interned const u8 arrays using raw WasmValType bytes. */ { - CfreeCgSym* param_syms = arena_zarray(arena, CfreeCgSym, ntypes); - CfreeCgSym* result_syms = arena_zarray(arena, CfreeCgSym, ntypes); + CfreeCgSym* param_syms = cfree_arena_zarray(arena, CfreeCgSym, ntypes); + CfreeCgSym* result_syms = cfree_arena_zarray(arena, CfreeCgSym, ntypes); uint32_t type_desc_size = 2u * ptr_size + 8u; CfreeCgTypeId types_array_ty = cfree_cg_type_array( c, u8_ty, (uint64_t)type_desc_size * (ntypes ? ntypes : 1u)); for (uint32_t k = 0; k < ntypes; ++k) { const WasmFuncType* t = &m->types[local_to_module[k]]; uint8_t* pbuf = - t->nparams ? arena_array(arena, uint8_t, t->nparams) : NULL; + t->nparams ? cfree_arena_array(arena, uint8_t, t->nparams) : NULL; uint8_t* rbuf = - t->nresults ? arena_array(arena, uint8_t, t->nresults) : NULL; + t->nresults ? cfree_arena_array(arena, uint8_t, t->nresults) : NULL; for (uint32_t p = 0; p < t->nparams; ++p) pbuf[p] = (uint8_t)t->params[p]; for (uint32_t r = 0; r < t->nresults; ++r) rbuf[r] = (uint8_t)t->results[r]; @@ -1659,20 +1658,21 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, wasm_error(c, wasm_loc(0, 0), "wasm: failed to initialize codegen"); CfreeCgBuiltinTypes b = cfree_cg_builtin_types(c); WasmCgRuntime rt; - /* Arena owns transient frontend-side codegen state — sym tables, func + /* A CfreeArena owns transient frontend-side codegen state — sym tables, func * types, per-function local arrays, instance-record field tables, call * argument arrays. Lives for the duration of wasm_emit_cg; no fixed cap * on functions, params, locals, or instance fields. */ - Arena arena; + CfreeArena* arena = NULL; CfreeCgSym init_sym = CFREE_CG_SYM_NONE; uint32_t i, j; - arena_init(&arena, (Heap*)cfree_compiler_context(c)->heap, 8192); + if (cfree_arena_new(cfree_compiler_context(c)->heap, 8192, &arena) != CFREE_OK) + wasm_error(c, wasm_loc(0, 0), "wasm: out of memory"); if (!cg) wasm_error(c, wasm_loc(0, 0), "wasm: failed to initialize codegen"); CfreeCgSym* syms = - m->nfuncs ? arena_zarray(&arena, CfreeCgSym, m->nfuncs) : NULL; + m->nfuncs ? cfree_arena_zarray(arena, CfreeCgSym, m->nfuncs) : NULL; CfreeCgTypeId* func_types = - m->nfuncs ? arena_zarray(&arena, CfreeCgTypeId, m->nfuncs) : NULL; - wasm_cg_build_runtime(c, b, m, &rt, &arena); + m->nfuncs ? cfree_arena_zarray(arena, CfreeCgTypeId, m->nfuncs) : NULL; + wasm_cg_build_runtime(c, b, m, &rt, arena); { CfreeCgFuncSig sig; CfreeCgDecl decl; @@ -1720,7 +1720,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, for (i = 0; i < m->nfuncs; ++i) { const WasmFunc* f = &m->funcs[i]; CfreeCgFuncParam* cg_params = - arena_zarray(&arena, CfreeCgFuncParam, f->nparams + 1u); + cfree_arena_zarray(arena, CfreeCgFuncParam, f->nparams + 1u); CfreeCgFuncSig sig; CfreeCgDecl decl; char local_name[40]; @@ -1980,14 +1980,14 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, wasm_cg_call_func(c, cg, b, &m->funcs[m->start_func], &rt, syms[m->start_func], func_types[m->start_func], instance_local, m->start_func, 0, m->start_field_loc, - &arena); + arena); cfree_cg_ret_void(cg); cfree_cg_func_end(cg); } /* Host-import resolution metadata: emit __cfree_wasm_nimports always, and * __cfree_wasm_imports / __cfree_wasm_types when the module declares at * least one function import. Read by cfree_wasm_bind_host_imports. */ - wasm_cg_emit_host_import_metadata(c, cg, b, m, &rt, &arena); + wasm_cg_emit_host_import_metadata(c, cg, b, m, &rt, arena); for (i = 0; i < m->nfuncs; ++i) { const WasmFunc* f = &m->funcs[i]; typedef struct WasmCgControl { @@ -2003,9 +2003,9 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, * we use a side heap realloc instead). */ CfreeCgLocal* locals = (f->nparams + f->nlocals) - ? arena_array(&arena, CfreeCgLocal, f->nparams + f->nlocals) + ? cfree_arena_array(arena, CfreeCgLocal, f->nparams + f->nlocals) : NULL; - Heap* heap = (Heap*)cfree_compiler_context(c)->heap; + CfreeHeap* heap = cfree_compiler_context(c)->heap; uint32_t control_cap = 16u; WasmCgControl* control = (WasmCgControl*)heap->alloc( heap, sizeof(WasmCgControl) * control_cap, _Alignof(WasmCgControl)); @@ -2139,7 +2139,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, if (in.ntargets == 0) wasm_error(c, in.loc, "wasm: bad br_table target count"); CfreeCgSwitchCase* cases = - arena_zarray(&arena, CfreeCgSwitchCase, in.ntargets); + cfree_arena_zarray(arena, CfreeCgSwitchCase, in.ntargets); for (uint32_t k = 0; k + 1u < in.ntargets; ++k) { uint32_t idx; if (in.targets[k] >= ncontrol) @@ -2252,7 +2252,7 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, wasm_cg_call_func(c, cg, b, &m->funcs[in.imm], &rt, syms[in.imm], func_types[in.imm], instance_local, (uint32_t)in.imm, in.kind == WASM_INSN_RETURN_CALL, - in.loc, &arena); + in.loc, arena); break; case WASM_INSN_CALL_INDIRECT: case WASM_INSN_RETURN_CALL_INDIRECT: { @@ -2260,11 +2260,11 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, CfreeCgLocalAttrs attrs; CfreeCgLocal selector, callee, result = CFREE_CG_LOCAL_NONE; CfreeCgLocal* args = - t->nparams ? arena_array(&arena, CfreeCgLocal, t->nparams) : NULL; + t->nparams ? cfree_arena_array(arena, CfreeCgLocal, t->nparams) : NULL; CfreeCgLabel ok; CfreeCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32); CfreeCgFuncParam* indirect_params = - arena_zarray(&arena, CfreeCgFuncParam, t->nparams + 1u); + cfree_arena_zarray(arena, CfreeCgFuncParam, t->nparams + 1u); CfreeCgFuncSig indirect_sig; CfreeCgTypeId indirect_func_type; memset(&attrs, 0, sizeof attrs); @@ -2393,12 +2393,12 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, CfreeCgLocalAttrs attrs; CfreeCgLocal callee_ref, callee, result = CFREE_CG_LOCAL_NONE; CfreeCgLocal* args = - t->nparams ? arena_array(&arena, CfreeCgLocal, t->nparams) : NULL; + t->nparams ? cfree_arena_array(arena, CfreeCgLocal, t->nparams) : NULL; CfreeCgLabel ok; CfreeCgMemAccess ref_mem = wasm_cg_mem_type(rt.void_ptr_ty); CfreeCgMemAccess i32_mem = wasm_cg_mem(c, b, WASM_VAL_I32); CfreeCgFuncParam* ref_params = - arena_zarray(&arena, CfreeCgFuncParam, t->nparams + 1u); + cfree_arena_zarray(arena, CfreeCgFuncParam, t->nparams + 1u); CfreeCgFuncSig ref_sig; CfreeCgTypeId ref_func_type; memset(&attrs, 0, sizeof attrs); @@ -3686,5 +3686,5 @@ void wasm_emit_cg(CfreeCompiler* c, const CfreeCodeOptions* code_opts, heap->free(heap, control, sizeof(WasmCgControl) * control_cap); } cfree_cg_free(cg); - arena_fini(&arena); + cfree_arena_free(arena); }