kit

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

commit e461b84e8baeee4238c130f0cd23f09cd8b95a81
parent 9102a9951e9c68f81a05ac78565d71a43c3a337d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue,  9 Jun 2026 15:48:08 -0700

wasm: kit-entry custom section for auto-detecting entry in kit run

build-exe for wasm now embeds a kit-entry custom section (section id=0,
name="kit-entry") containing the entry function name. kit run reads this
section from the .wasm file header via a lightweight binary scanner and
uses it as the default entry, so `kit run out.wasm` works without -e.

Diffstat:
Mdriver/cmd/build.c | 2++
Mdriver/cmd/run.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/kit/object.h | 2++
Msrc/obj/wasm/emit.c | 20++++++++++++++++++++
Mtest/buildcmds/run.sh | 3+++
Mtest/wasm/run.sh | 2++
6 files changed, 102 insertions(+), 0 deletions(-)

diff --git a/driver/cmd/build.c b/driver/cmd/build.c @@ -1881,6 +1881,8 @@ static int build_run_wasm_exe(BuildOptions* o, KitCompiler* compiler, driver_errf(o->tool, "build-exe: LTO finish failed"); goto out; } + kit_obj_builder_wasm_add_custom(objs[0], KIT_SLICE_LIT("kit-entry"), + kit_slice_cstr(entry_name)); } if (build_open_output(ctx, env, o->tool, o->output_path, &out_w) != 0) goto out; diff --git a/driver/cmd/run.c b/driver/cmd/run.c @@ -461,6 +461,57 @@ static int run_path_is_wasm_source(const char* path) { return driver_has_suffix(path, ".wat") || driver_has_suffix(path, ".wasm"); } +/* Scan raw wasm bytes for a custom section named `want`. + * On success sets *len_out and returns a pointer into `p`; returns NULL on + * miss or malformed input. The returned pointer is valid only while `p` is. */ +static const char* wasm_scan_custom(const uint8_t* p, size_t total, + const char* want, uint32_t* len_out) { + const uint8_t* end = p + total; + uint8_t id; + uint32_t size, shift; + const uint8_t* sec_end; + if (total < 8) return NULL; + p += 8; /* skip magic + version */ + while (p < end) { + uint8_t b; + id = *p++; + size = 0; shift = 0; + for (;;) { + if (p >= end) return NULL; + b = *p++; + size |= (uint32_t)(b & 0x7f) << shift; + if (!(b & 0x80)) break; + shift += 7; + if (shift > 28) return NULL; + } + if ((uint32_t)(end - p) < size) return NULL; + sec_end = p + size; + if (id == 0) { + uint32_t nlen = 0; + shift = 0; + for (;;) { + if (p >= sec_end) { p = sec_end; goto next_section; } + b = *p++; + nlen |= (uint32_t)(b & 0x7f) << shift; + if (!(b & 0x80)) break; + shift += 7; + if (shift > 28) { p = sec_end; goto next_section; } + } + if ((uint32_t)(sec_end - p) >= nlen) { + size_t wlen = driver_strlen(want); + if (nlen == (uint32_t)wlen && memcmp(p, want, wlen) == 0) { + p += nlen; + *len_out = (uint32_t)(sec_end - p); + return (const char*)p; + } + } + } + next_section: + p = sec_end; + } + return NULL; +} + static int run_inputs_have_wasm_source(const DriverInputs* in) { uint32_t i; for (i = 0; i < in->nsources; ++i) @@ -714,6 +765,28 @@ static int run_parse(int argc, char** argv, RunOptions* o) { "sandboxed wasm run does not support mixed native inputs"); return 1; } + if (!o->entry && run_inputs_have_wasm_source(&o->inputs) && + !run_inputs_have_non_wasm(&o->inputs) && + o->inputs.nsources == 1) { + DriverLoad lf = {0}; + KitSlice bytes = {0}; + if (driver_load_bytes(&o->env->file_io, RUN_TOOL, + o->inputs.sources[0], &lf, &bytes) == 0) { + uint32_t elen = 0; + const char* ep = wasm_scan_custom((const uint8_t*)bytes.s, + (size_t)bytes.len, + "kit-entry", &elen); + if (ep && elen > 0 && elen < 256) { + char* buf = (char*)o->env->heap->alloc(o->env->heap, elen + 1u, 1); + if (buf) { + memcpy(buf, ep, elen); + buf[elen] = '\0'; + o->entry = buf; + } + } + driver_release_bytes(&o->env->file_io, &lf); + } + } if (!o->entry) o->entry = "main"; if (run_apply_hosted_profile(o) != 0) return 1; diff --git a/include/kit/object.h b/include/kit/object.h @@ -216,6 +216,8 @@ KIT_API KitStatus kit_obj_builder_symbol_set_vis(KitObjBuilder*, KitObjSymbol, KitSymVis); KIT_API KitStatus kit_obj_builder_find_symbol(const KitObjBuilder*, KitSym, KitObjSymbol* out); +KIT_API KitStatus kit_obj_builder_wasm_add_custom(KitObjBuilder*, KitSlice name, + KitSlice data); KIT_API KitStatus kit_obj_builder_section_replace_bytes(KitObjBuilder*, KitObjSection, const void* data, diff --git a/src/obj/wasm/emit.c b/src/obj/wasm/emit.c @@ -11,6 +11,26 @@ #include "obj/wasm/wasm.h" #include "wasm/wasm.h" +KitStatus kit_obj_builder_wasm_add_custom(KitObjBuilder* b, KitSlice name, + KitSlice data) { + ObjBuilder* ob = (ObjBuilder*)b; + Compiler* c = obj_compiler(ob); + WasmModule* m = (WasmModule*)obj_ext_get(ob, OBJ_EXT_WASM); + WasmCustom* cs; + if (!m || !c) return KIT_NOT_FOUND; + cs = wasm_add_custom(c, m); + if (!cs) return KIT_NOMEM; + cs->name = wasm_strdup(m->heap, name.s, (size_t)name.len); + if (!cs->name) return KIT_NOMEM; + if (data.len) { + cs->data = (uint8_t*)m->heap->alloc(m->heap, (size_t)data.len, 1); + if (!cs->data) return KIT_NOMEM; + memcpy(cs->data, data.s, (size_t)data.len); + cs->len = (uint32_t)data.len; + } + return KIT_OK; +} + void emit_wasm(Compiler* c, ObjBuilder* o, Writer* w) { WasmModule* m = (WasmModule*)obj_ext_get(o, OBJ_EXT_WASM); if (m) { diff --git a/test/buildcmds/run.sh b/test/buildcmds/run.sh @@ -248,6 +248,9 @@ run_ok be-wasm-exe-default-name "$KIT" build-exe -target wasm32-none \ wexe_main.c wexe_add.c -e test_main assert_file_exists be-wasm-exe-default-name-file a.wasm +# kit run without -e reads the kit-entry custom section from the module. +run_ok be-wasm-exe-autoentry "$KIT" run wexe.wasm + # Unknown entry symbol is rejected with a clear diagnostic. run_fail be-wasm-exe-bad-entry "$KIT" build-exe -target wasm32-none \ wexe_main.c wexe_add.c -e no_such_fn -o bad_entry.wasm diff --git a/test/wasm/run.sh b/test/wasm/run.sh @@ -400,6 +400,8 @@ EOF "$KIT_BIN" run -e test_main "$_wasm_exe" [ "$RUN_N" -eq 1 ] && wf_rc_interp "wasm-exe/N" 0 \ "$KIT_BIN" run --no-jit -e test_main "$_wasm_exe" + [ "$RUN_D" -eq 1 ] && wf_rc "wasm-exe/D-autoentry" 0 \ + "$KIT_BIN" run "$_wasm_exe" else kit_fail "wasm-exe/build" "build-exe failed" fi