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:
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);
}