1/* @ajax/wasm-interp: runs WebAssembly modules.
2 *
3 * wasm_compile bytes -> a compiled module (decoded, validated, lowered), shareable by threads
4 * wasm_instantiate a compiled module + host functions + limits -> an instance (one thread's)
5 * wasm_call calls a function of an instance; a trap is returned, never longjmp'd
6 *
7 * What the engine does, as meshd's wasmtime engine is configured (alpha-rust-mesh
8 * mesh-host/src/wasm.rs `engine()`): every arithmetic NaN is canonical (@ajax/wasm-numeric);
9 * no signal handlers (every memory and table access is bounds-checked); interrupts by epoch: an
10 * instance given an epoch counter and a deadline traps with WASM_TRAP_INTERRUPT at the next loop
11 * header or function entry once the counter reaches the deadline. Store limits as wasmtime's
12 * StoreLimits: a memory may not grow past `memory_bytes` (memory.grow returns -1; a module whose
13 * initial memory is larger fails to instantiate), at most `tables` tables and `memories`
14 * memories. Proposals: the MVP, mutable globals, sign extension, saturating float-to-int,
15 * multi-value, reference types, bulk memory, extended constant expressions (WASM_F_INTERP); not
16 * SIMD, threads, multi-memory or memory64. */
17#ifndef WASM_INTERP_H
18#define WASM_INTERP_H
1920#include "wasm/module.h"
21#include "wasm/numeric.h"
2223#include <stdatomic.h>
24#include <stdbool.h>
25#include <stddef.h>
26#include <stdint.h>
2728typedef struct wasm_compiled wasm_compiled;
29typedef struct wasm_instance wasm_instance;
3031/* A host function: args in io[0..nparams), results to io[0..nresults) (i32/f32 in the low 32 bits).
32 * Returns WASM_NUM_OK, or a trap code to trap the calling wasm. */
33typedef int (*wasm_host_fn)(wasm_instance *inst, void *ctx, uint64_t *io);
3435typedef struct {
36 const char *module, *name;
37 const char *sig; /* "ii>i" over i l f d */
38 wasm_host_fn fn;
39 void *ctx;
40} wasm_host_func;
4142typedef struct {
43 uint64_t memory_bytes; /* 0: no limit beyond the module's own maximum */
44 uint32_t tables; /* 0: no limit */
45 uint32_t memories; /* 0: no limit */
46 uint32_t stack_slots; /* value stack, 64-bit slots; 0: 128 Ki */
47 uint32_t call_depth; /* frames; 0: 10 000 */
48} wasm_store_limits;
4950/* Decodes, validates (under `features`, which must be within WASM_F_INTERP to run) and lowers.
51 * The bytes are copied. NULL with err ("jit: ..." is left to the caller) on any failure. */
52wasm_compiled *wasm_compile(const uint8_t *bytes, size_t len, wasm_features features, char *err, size_t errlen);
53void wasm_compiled_free(wasm_compiled *c);
54const wasm_module *wasm_compiled_module(const wasm_compiled *c);
5556/* Resolves imports by module, name and signature (wasmtime's messages: "unknown import: `m::n`
57 * has not been defined", "incompatible import type for `m::n`"), applies limits, initialises
58 * globals, tables, memory and segments, runs the start function. NULL with err on failure. */
59wasm_instance *wasm_instantiate(const wasm_compiled *c, const wasm_host_func *imports, size_t nimports,
60 const wasm_store_limits *limits, void *user, char *err, size_t errlen);
61void wasm_instance_free(wasm_instance *inst);
62void *wasm_instance_user(const wasm_instance *inst);
63const wasm_compiled *wasm_instance_compiled(const wasm_instance *inst);
6465/* The exported function `name`, checked against sig: its index, or -1 with err (wasmtime-like:
66 * "failed to find function export `name`", "type mismatch with parameters"). */
67int64_t wasm_instance_func(const wasm_instance *inst, const char *name, const char *sig, char *err, size_t errlen);
6869/* Calls function `func` (imports first): io holds its args and receives its results. WASM_NUM_OK
70 * or the trap code (wasm/numeric.h). After a trap the instance must not be called again (its
71 * state may be anywhere mid-call; meshd makes a fresh one). */
72int wasm_call(wasm_instance *inst, uint32_t func, uint64_t *io);
7374/* The instance's memory 0: its bytes and size (both change when it grows); NULL without one. */
75uint8_t *wasm_memory(const wasm_instance *inst, uint64_t *size);
7677/* Interrupts: trap at the next check once *epoch >= deadline. NULL epoch: never. */
78void wasm_set_epoch(wasm_instance *inst, const _Atomic uint64_t *epoch);
79void wasm_set_deadline(wasm_instance *inst, uint64_t deadline);
80uint64_t wasm_deadline(const wasm_instance *inst);
8182#endif