nx_wasm_call_operands_t143.nx
buildroot/runtime/nx_wasm_call_operands_t143.nx
about
nx_wasm.nx F618 wasm-SIMD FLIP (2026-07-21, landed from the proven rung-1 twin nx_wasm_v128.nx).
The fused v128 SAD intercept fires ONLY on calls to v128_sad16 (nx_vmotion.nx); any function without one emits byte-identical wasm.
THE INTERCEPT: a call to the scalar reference fn `v128_sad16(a,b)` (nx_vmotion.nx) is emitted
as an INLINE wasm-SIMD sequence (v128.load x2, sub_sat_u both ways, or -> bytewise |a-b|,
extadd_pairwise u8->u16->u32, 4x extract_lane+extend+add) instead of a call. Native + stock-wat
builds keep the scalar body = the bit-exact reference; this backend swaps ONLY the call sites.
Exact-integer equivalence: sub_sat_u(a,b)|sub_sat_u(b,a) == |a-b| per byte (one side is 0);
extadds are exact (max 16*255=4080 << u16/u32); the lane sum is the same integer as the scalar loop.
The inliner is OFF by default (opt_inline_module gate) so call sites always reach this emitter.
wasm.nx -- NishiLang port of wasm.c (WAT backend).
Lowers our SSA IR to WebAssembly Text format. The core challenge
WAT imposes is structured control flow: there are no arbitrary
branches, only block/loop/if scopes with break-to-label. Our IR
has free-form CFG edges, so we use the universal block-dispatch
pattern (`br_table` driven by a `$target` local) that encodes any
CFG at small constant cost.
Per-op semantics match wasm.c exactly; every Value gets a $vN
local, comparisons extend to i64 after the i32 WASM result, and
constants materialize inline as i64.const.
Functions are prefixed `wat_` so they don't collide with riscv.nx's
asm-side `rv_*` / `emit_*` naming when both libraries are imported
into a driver.
dependencies 5 imports · 2 importers
imports: nx_syscalls.nxnx_types.nxnx_ir.nxnx_outbuf.nxnx_wasm_data.nx
imported by: nx_compile_wat_call_operands_t143.nxnx_wasm_call_count_gate_t143.nx
structs
| none |
consts
| 843 | const WAT_MEM_PAGES_DEFAULT: i64 = 364 |
| 847 | const WAT_PAGES_SPEC_MAX: i64 = 65536 |
| 848 | const WAT_GLOBAL_STRIDE: i64 = 80 // Global slot stride -- matches ir_module_new's allocator |
| 865 | const WAT_UNLOWERABLE_MSG_CAP: i64 = 1024 |
functions
| 63 | func wat_push_operand(f: *Function, o: *OutBuf, ind: i64, v: i64) -> i64 |
| 87 | func wat_store_result(o: *OutBuf, ind: i64, v: i64) -> i64 |
| 97 | func wat_binop_mnem(op: i64, o: *OutBuf) -> i64 |
| 112 | func wat_cmp_mnem(op: i64, o: *OutBuf) -> i64 |
| 124 | func wat_emit_binop(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 134 | func wat_emit_cmp(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 149 | func wat_nameq(name: *u8, kw: *u8) -> i64 |
| 158 | func wat_call_is_sad16(i: *Instr) -> i64 |
| 177 | func wat_at_line(o: *OutBuf, ind: i64, s: *u8) -> i64 { out_indent(o, ind * 2); out_str(o, s); out_char(o, 0x0A); return 0 } |
| 190 | func wat_addr_narrow(o: *OutBuf, ind: i64) -> i64 |
| 197 | func wat_at_get_result(o: *OutBuf, ind: i64, i: *Instr) -> i64 { out_indent(o, ind * 2); out_str(o, "local.get $v"); out_i64(o, i.result); out_char(o, 0x0A); return 0 } |
| 198 | func wat_emit_atomic_op(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 269 | func wat_syscall_is_futex(f: *Function, i: *Instr) -> i64 |
| 282 | func wat_emit_futex(f: *Function, o: *OutBuf, ind: i64, i: *Instr, kind: i64) -> i64 |
| 300 | func wat_emit_v128sad(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 339 | func wat_call_preflight(i: *Instr) -> i64 |
| 354 | func wat_push_call_operands(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 364 | func wat_emit_call(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 386 | func wat_emit_return(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 397 | func wat_emit_branch(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 440 | func wat_emit_f32(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 482 | func wat_is_alloca(f: *Function, vid: i64) -> i64 |
| 490 | func wat_emit_load(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 514 | func wat_emit_store(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 534 | func wat_emit_gep(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 542 | func wat_emit_tail_call(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 568 | func wat_emit_instr(f: *Function, o: *OutBuf, ind: i64, i: *Instr) -> i64 |
| 671 | func wat_emit_function(f: *Function, o: *OutBuf) -> i64 |
| 866 | func wat_die_unlowerable(f: *Function, op: i64) -> i64 |
| 884 | func wat_die(msg: *u8) -> i64 |
| 892 | func wat_mem_pages(m: *Module) -> i64 |
| 933 | func wat_global_i64(m: *Module, want: *u8, found: *i64) -> i64 |
| 968 | func wat_mem_shared(m: *Module) -> i64 |
| 980 | func wat_mem_pages_max(m: *Module, pages: i64) -> i64 |
| 1000 | func wat_emit_module(m: *Module, o: *OutBuf) -> i64 |