From 561fd08254c45eb228b649724963342bff9a8a9d Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Wed, 6 Aug 2025 14:21:25 +0100 Subject: [PATCH 01/57] Skeleton UrWASM docs --- .../build-on-urbit/wasm-walkthrough/README.md | 18 + .../wasm-walkthrough/examples/README.md | 20 + .../wasm-walkthrough/examples/agent.md | 3 + .../wasm-walkthrough/examples/generator.md | 3 + .../wasm-walkthrough/examples/thread.md | 4 + .../wasm-walkthrough/overview.md | 25 ++ .../wasm-walkthrough/reference/README.md | 25 ++ .../wasm-walkthrough/reference/data-types.md | 18 + .../wasm-walkthrough/reference/wasm-libs.md | 389 ++++++++++++++++++ 9 files changed, 505 insertions(+) create mode 100644 content/build-on-urbit/wasm-walkthrough/README.md create mode 100644 content/build-on-urbit/wasm-walkthrough/examples/README.md create mode 100644 content/build-on-urbit/wasm-walkthrough/examples/agent.md create mode 100644 content/build-on-urbit/wasm-walkthrough/examples/generator.md create mode 100644 content/build-on-urbit/wasm-walkthrough/examples/thread.md create mode 100644 content/build-on-urbit/wasm-walkthrough/overview.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/README.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/data-types.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md new file mode 100644 index 00000000..70f09e5f --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -0,0 +1,18 @@ +--- +description: "foobarbaz" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + +# WASM Walkthrough + +foobar diff --git a/content/build-on-urbit/wasm-walkthrough/examples/README.md b/content/build-on-urbit/wasm-walkthrough/examples/README.md new file mode 100644 index 00000000..d1d2bba1 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/examples/README.md @@ -0,0 +1,20 @@ +# UrWASM Examples + +foobar examples + +* What usage patterns are possible with UrWASM? + * WASM modules as libraries + * In generators + * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + * Stateless UrWASM: `+run-once` + * Tutorial: sort a list of 64-bit atoms + * In threads + * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + * Stateful UrWASM: `+run` + * Example: running Wasm in a thread + * In Gall agents + * You could do a Gall agent that tracks its state in the agent but delegates functionality to a JS library + * WASM calls as "userspace jets" + * I don’t think there’s an existing example for this + * Glicko-2 in JS or Python might be nice + * Would require finishing a Glicko-2 %telos which would be a pretty big job diff --git a/content/build-on-urbit/wasm-walkthrough/examples/agent.md b/content/build-on-urbit/wasm-walkthrough/examples/agent.md new file mode 100644 index 00000000..03fd04ff --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/examples/agent.md @@ -0,0 +1,3 @@ +# UrWASM Gall Agent Example + +foobar diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md new file mode 100644 index 00000000..a5ffb14f --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -0,0 +1,3 @@ +# UrWASM Generator Example + +foo diff --git a/content/build-on-urbit/wasm-walkthrough/examples/thread.md b/content/build-on-urbit/wasm-walkthrough/examples/thread.md new file mode 100644 index 00000000..b79756d6 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/examples/thread.md @@ -0,0 +1,4 @@ +# UrWASM Thread Example + +foo + diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md new file mode 100644 index 00000000..d6b8f759 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -0,0 +1,25 @@ +# UrWASM Overview + +### Why +* The point of UrWASM is to compensate for deficiencies in the system, so that Hoon devs can… + * Do stuff like userspace jets for stuff that’s criminally slow in Hoon (fuzzy-find, userpsace jets, Glicko-2, etc.) + * Leverage existing JS and Rust libraries for functionality that doesn’t exist in Hoon (encryption, ripgrep, etc.) + +### How +* Why didn’t Urbit do this already? +* How did we solve the problems? + * UrWASM + * [urwasm.md](https://gist.github.com/Quodss/a1aaa81941e61707843a75d45d901ea0) + * Introduction + * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + * WebAssembly primer + * UrWASM core structure + * Determinism solved by Lia + * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) + * Jetting + * Motivation + * Bespoke WASM interpreter that operates on nouns + * Serializer / deserializer in the jet + * Serializer / deserializer in the Hoon spec + * Higher level interpreting function + * Lia interpreter diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm-walkthrough/reference/README.md new file mode 100644 index 00000000..0be38fa7 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/README.md @@ -0,0 +1,25 @@ +# UrWASM Reference + +foobar + +Urwasm is structured as a series of nested cores: + +/sur/wasm/wasm/hoon :: Wasm types definition +/sur/wasm/engine/hoon :: Wasm interpreter types +/sur/wasm/lia/hoon :: Lia [Language for Invocation of (web)Assembly] types +/lib/wasm/parser/hoon :: Wasm parser +/lib/wasm/validator/hoon :: Wasm validator +/lib/wasm/runner/op-def/hoon :: Wasm operator definitions +/lib/wasm/runner/engine/hoon :: Wasm interpreter +/lib/wasm/lia/hoon :: Lia interpreter + +All cores except for the topmost, defined in /lib/wasm/lia/hoon are additionally wrapped in one-armed cores to manage the namespace: + +/sur/wasm/wasm/hoon -> wasm-sur +/sur/wasm/engine/hoon -> engine-sur +/sur/wasm/lia/hoon -> lia-sur +/lib/wasm/parser/hoon -> parser +/lib/wasm/validator/hoon -> validator +/lib/wasm/runner/op-def/hoon -> op-def +/lib/wasm/runner/engine/hoon -> engine + diff --git a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md new file mode 100644 index 00000000..54fa0420 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md @@ -0,0 +1,18 @@ +# UrWASM Data Types + +nested core structure + +/sur/wasm/wasm/hoon :: Wasm types definition +/sur/wasm/engine/hoon :: Wasm interpreter types +/sur/wasm/lia/hoon :: Lia [Language for Invocation of (web)Assembly] types + +foobar + +## /sur/wasm/wasm/hoon +Wasm types definition + +## /sur/wasm/engine/hoon +Wasm interpreter types + +## /sur/wasm/lia/hoon +Lia [Language for Invocation of (web)Assembly] types diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md new file mode 100644 index 00000000..00e7138e --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md @@ -0,0 +1,389 @@ +# UrWASM Library Reference + +nested core structure + +/lib/wasm/parser/hoon :: Wasm parser +/lib/wasm/validator/hoon :: Wasm validator +/lib/wasm/runner/op-def/hoon :: Wasm operator definitions +/lib/wasm/runner/engine/hoon :: Wasm interpreter +/lib/wasm/lia/hoon :: Lia interpreter + +foobar + + * Stateless UrWASM: `+run-once` + * Stateful UrWASM: `+run` + +*** + +## /lib/wasm/runner/engine + +++ engine + ++ get-types + ++ mint + ++ make-export-map + ++ find-func-id + ++ conv + ++ import-upd + ++ prep + ++ instantiate + ++ init-globals + ++ init-table + ++ init-elems + ++ init-mem + ++ init-data + ++ start + ++ wasm-need + ++ wasm-bind + ++ invoke + ++ invoke-id + ++ call + ++ eval + ++ dec-br + ++ apply + + +## /lib/wasm/runner/op-def + +++ op-def + ++ mayb + ++ sure + ++ torn + ++ lane-size + ++ fuse :: from \~paldev + ++ chap + ++ page-size ^\~((bex 16)) + ++ place + ++ lim-min + ++ lim-max + ++ lte-lim + ++ change + ++ to-si + ++ en-si + ++ sat + ++ coin-to-val + ++ val-to-coin + ++ snug + ++ shot + ++ buy + ++ grab + ++ func + ++ table + ++ memo + ++ glob + ++ mem-store + ++ mem-load + ++ kind + ++ fetch-gate + ++ fetch + ++ dbug + ++ print-tee + ++ select + ++ null + ++ unreachable + ++ nop |=(local-state +<) + ++ return + ++ drop + ++ ref + ++ ref-null + ++ ref-is-null + ++ ref-func + ++ load + ++ store + ++ const + ++ get + ++ set + ++ branch + ++ table + ++ table-get + ++ table-set + ++ table-init + ++ elem-drop + ++ table-copy + ++ table-grow + ++ table-size + ++ table-fill + ++ memo + ++ memory-size + ++ memory-grow + ++ memory-init + ++ data-drop + ++ memory-copy + ++ memory-fill + ++ unar + ++ clz + ++ ctz + ++ popcnt + ++ abs + ++ neg + ++ sqrt + ++ ceil + ++ floor + ++ trunc + ++ nearest + ++ eqz + ++ wrap + ++ extend + ++ convert + ++ demote + ++ promote + ++ reinterpret + ++ bina + ++ add + ++ sub + ++ mul + ++ div + ++ rem + ++ and + ++ or + ++ xor + ++ shl + ++ shr + ++ rotl + ++ rotr + ++ min + ++ max + ++ copysign + ++ eq + ++ ne + ++ lt + ++ gt + ++ le + ++ ge + ++ simd + ++ rope + ++ fetch-vec + ++ load + ++ load-lane + ++ store + ++ store-lane + ++ const + ++ shuffle + ++ extract + ++ replace + ++ plain + ++ kind + ++ vec-unar + ++ vec-bina + ++ get-op-unar + ++ get-op-bina + ++ get-size + +## /lib/wasm/lia + +++ run-once + ++ init +++ run + ++ init + +++ arrows +* [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + ++ m-sat (lia-state m-acc) + ++ call + ++ call-1 + ++ memread + ++ memwrite + ++ call-ext + ++ global-set + ++ global-get + ++ memory-size + ++ memory-grow :: returns old size in pages + ++ get-acc + ++ set-acc + ++ get-all-local-globals + ++ set-all-local-globals + +++ runnable (script (list lia-value) *) +++ cw-to-atom +++ types-atoms-to-coins +++ valtype-from-coin +++ page-size ^\~((bex 16)) +++ yield-need + +## /lib/wasm/parser + +++ parser + ++ main + ++ r + ++ womp + ++ bild + ++ bonk + ++ feel + ++ u-n + ++ s-n + ++ u32 (u-n 32) + ++ u64 (u-n 64) + ++ f32 + ++ f64 + ++ vec + ++ name (cook crip (vec next)) + ++ vec-u32 (vec u32) + ++ num-type + ++ vec-type (cold %v128 (just '\7b')) + ++ ref-type + ++ valtype + ++ func-type + ++ limits + ++ expr + ++ expr-pair + ++ end (just '\0b') + ++ else (just '\05') + ++ const-i32 (just '\41') + ++ const-i64 (just '\42') + ++ const-f32 (just '\43') + ++ const-f64 (just '\44') + ++ block-op (just '\02') + ++ loop-op (just '\03') + ++ if-op (just '\04') + ++ form-ranges + ++ instr + ++ select-vec + ++ br-table + ++ instr-zero (sear op-map next) + ++ block + ++ loop + ++ if + ++ block-type + ++ handle-one-arg-i32 + ++ handle-two-args-i32 + ++ handle-br-table + ++ handle-block + ++ get-valtype + ++ handle-loop + ++ handle-if + ++ handle-const-f64 + ++ handle-const-f32 + ++ handle-const-i32 + ++ handle-const-i64 + ++ fc + ++ zero-args (sear handle-zero u32) + ++ one-arg (sear handle-one ;\~(plug u32 u32)) + ++ two-args (sear handle-two ;\~(plug u32 u32 u32)) + ++ handle-zero + ++ handle-one + ++ handle-two + ++ fd + ++ memarg + ++ mem-lane + ++ const + ++ shuffle + ++ lane + ++ type-section + ++ import-section + ++ import + ++ import-desc + ++ import-func ;\~(plug (cold %func (just '\00')) u32) + ++ import-tabl ;\~(plug (cold %tabl (just '\01')) ref-type limits) + ++ import-memo ;\~(plug (cold %memo (just '\02')) limits) + ++ import-glob + ++ con-var + ++ function-section + ++ table-section + ++ table ;\~(plug ref-type limits) + ++ memory-section + ++ global-section + ++ global + ++ const-expr ;\~(sfix const-instr end) :: single instruction + ++ const-instr + ++ export-section + ++ export + ++ start-section + ++ elem-section + ++ elem + ++ elem-kind (just '\00') + ++ elem-0 + ++ elem-1 + ++ elem-2 + ++ elem-3 + ++ elem-4 + ++ elem-5 + ++ elem-6 + ++ elem-7 + ++ handle-elem-0 + ++ handle-elem-1 + ++ handle-elem-2 + ++ handle-elem-3 + ++ handle-elem-4 + ++ handle-elem-5 + ++ handle-elem-6 + ++ handle-elem-7 + ++ code-section + ++ code (bonk (vec next) ;\~(pfix u32 func)) + ++ func + ++ locals ;\~(plug u32 valtype) + ++ handle-locals + ++ data-section + ++ data + ++ to-octs + ++ datacnt-section + ++ module + ++ module-contents + ++ check + ++ customs + ++ magic (jest '\00asm') + ++ version + ++ op-map + ++ simd-map + ++ nearest + ++ sqrt + ++ div + ++ pmin + ++ pmax + ++ avgr + ++ ceil + ++ floor + ++ all-true + ++ bitmask + ++ narrow + ++ shl + ++ extadd + ++ convert + ++ mul + ++ splat + ++ eq + ++ ne + ++ abs + ++ neg + ++ trunc + ++ lt + ++ gt + ++ le + ++ ge + ++ shr + ++ min + ++ max + ++ add + ++ sub + ++ extend + ++ extmul + + +## /lib/wasm/validator + +++ validator + ++ output + ++ result-form + ++ result + ++ bind + ++ snug + ++ validate-module + ++ v-import-section + ++ validate-limits + ++ v-function-section + ++ v-table-section + ++ v-memory-section + ++ v-global-section + ++ v-export-section + ++ v-start-section + ++ v-elem-section + ++ v-datacnt-section + ++ v-code-section + ++ v-data-section + ++ validate-code + ++ validate-expr + ++ validate-instr + ++ get-type + ++ get-type-vec + ++ from-coin + ++ byte-width + ++ dim-lane + ++ unpack From 1c7bc0c9e4419c657332edef553728e9fd7f052f Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Wed, 6 Aug 2025 14:27:34 +0100 Subject: [PATCH 02/57] Draft intro --- content/build-on-urbit/wasm-walkthrough/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md index 70f09e5f..b47eb274 100644 --- a/content/build-on-urbit/wasm-walkthrough/README.md +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -15,4 +15,10 @@ layout: # WASM Walkthrough -foobar +Urbit's WASM affordances (collectively known as "UrWASM") enables Hoon developers to leverage pre-existing libraries from any WASM-compatible language like Rust and Go. Using QuickJS as a WASM module, they can also run Javascript on the Urbit ship. + +These docs cover: +- UrWASM overview +- UrWASM examples +- UrWASM types and API + From 568b7cb8e08209d51d88bcb2de721cc3418b6eef Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Thu, 7 Aug 2025 13:35:02 +0100 Subject: [PATCH 03/57] Draft overview --- .../build-on-urbit/wasm-walkthrough/README.md | 2 +- .../wasm-walkthrough/overview.md | 93 ++++++++++++++----- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md index b47eb274..b013741c 100644 --- a/content/build-on-urbit/wasm-walkthrough/README.md +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -15,7 +15,7 @@ layout: # WASM Walkthrough -Urbit's WASM affordances (collectively known as "UrWASM") enables Hoon developers to leverage pre-existing libraries from any WASM-compatible language like Rust and Go. Using QuickJS as a WASM module, they can also run Javascript on the Urbit ship. +Urbit's WebAssembly affordances (collectively known as "UrWASM") enables Hoon developers to leverage pre-existing libraries from any WASM-compatible language like Rust, Python, and Go. Using QuickJS as a WASM module, they can also run Javascript on the Urbit ship. These docs cover: - UrWASM overview diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index d6b8f759..d9f493f5 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -1,25 +1,74 @@ # UrWASM Overview -### Why -* The point of UrWASM is to compensate for deficiencies in the system, so that Hoon devs can… - * Do stuff like userspace jets for stuff that’s criminally slow in Hoon (fuzzy-find, userpsace jets, Glicko-2, etc.) - * Leverage existing JS and Rust libraries for functionality that doesn’t exist in Hoon (encryption, ripgrep, etc.) - -### How -* Why didn’t Urbit do this already? -* How did we solve the problems? - * UrWASM - * [urwasm.md](https://gist.github.com/Quodss/a1aaa81941e61707843a75d45d901ea0) - * Introduction - * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - * WebAssembly primer - * UrWASM core structure - * Determinism solved by Lia - * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) - * Jetting - * Motivation - * Bespoke WASM interpreter that operates on nouns - * Serializer / deserializer in the jet - * Serializer / deserializer in the Hoon spec - * Higher level interpreting function +Onboarding new developers onto Urbit necessarily involves teaching them [Hoon](../../hoon/why-hoon.md). Whatever Hoon's merits as a systems programming language, the time commitment to understanding the language enough to be productive is an obvious barrier to entry. + +Urbit allows developers to run server-side code in languages like Rust and Python by compiling that code to [WebAssembly](https://webassembly.org/) (WASM). They can run Javascript on the Urbit ship with a JS interpreter like QuickJS. Today this still involves some knowledge of Hoon, but the developer can mostly use the examples here as boilerplate. + +Trivially, Urbit's WASM affordances (collectively "UrWASM") enable Hoon developers to leverage pre-existing libraries for functionality that doesn't already exist in Hoon, or would be prohibitively slow without writing a C [runtime jet](../runtime/jetting.md). But one can imagine more ambitious use-cases like running complete Next.js or Rust apps on the Urbit ship. + +## WebAssembly + +WebAssembly is a small, hardware-independent assembly language for a stack-based virtual machine, primarily intended to be deployed on the web for client- and server-side applications that may be written in one of many programming languages other than Javascript. WASM is supported out-of-the-box in all mainstream browsers, and it uses Web APIs wherever possible, but WASM may be executed in other runtimes. + +Compiled WASM code (a `.wasm` file) is structured as a module, which consists of import and export declarations, function definitions, global variable and memory declarations, etc. A WASM module describes the starting state of a WASM virtual machine, whose state is modified by calling its functions, writing directly to the memory of the module, or what have you. + +As a low-level language, WASM's functions only return 32/64 bit integers and floating-point numbers. Higher-level information like structs and function signatures are stripped away during compliation and must be restored via "host language bindings", which reimplement the source code functions as wrappers around calls to the WASM VM. These may be generated automatically by the WASM compiler in addition to the `.wasm` module, usually in Javascript if the code is targeting a browser. + +For example, the following Rust code... + +```rust +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn process(input: String) -> String { + let output_string: String = input.chars().rev().collect(); + output_string +} +``` + +...will produce a `.wasm` module alongside the following language binding... + +```javascript +export function process(input) { + let deferred2_0; + let deferred2_1; + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + wasm.process(retptr, ptr0, len0); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + deferred2_0 = r0; + deferred2_1 = r1; + return getStringFromWasm0(r0, r1); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } +} +``` + +...which a web app could invoke like so: + +```javascript +import init, { process } from './our_wasm_module.js'; + +await init(); // init our_wasm_module.wasm +const result = process("hello world"); // run process() +console.log(result); // "dlrow olleh" +``` + +In our case, we'll have to write our own bindings manually in Hoon. We'll cover this later in these docs. + +## Lia + +The main theortical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWASM solves this by executing compiled WASM in Lia, a tiny interpreter that manages WASM's handful of nondeterministic edge-cases such that the same inputs to a WASM function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute WASM code at near-native speeds. + +* Determinism solved by Lia + * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) + * Jetting + * Motivation + * Higher level interpreting function * Lia interpreter + From 8e4f98de2fc6e63dccc3bf5d3be4dc2ef150628a Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Thu, 7 Aug 2025 14:21:49 +0100 Subject: [PATCH 04/57] Skeleton examples section --- .../wasm-walkthrough/examples/README.md | 22 ++++--------------- .../wasm-walkthrough/examples/agent.md | 4 ++++ .../wasm-walkthrough/examples/generator.md | 5 +++++ .../wasm-walkthrough/examples/thread.md | 4 ++++ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/examples/README.md b/content/build-on-urbit/wasm-walkthrough/examples/README.md index d1d2bba1..4bbdfc30 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/README.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/README.md @@ -1,20 +1,6 @@ # UrWASM Examples -foobar examples - -* What usage patterns are possible with UrWASM? - * WASM modules as libraries - * In generators - * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - * Stateless UrWASM: `+run-once` - * Tutorial: sort a list of 64-bit atoms - * In threads - * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - * Stateful UrWASM: `+run` - * Example: running Wasm in a thread - * In Gall agents - * You could do a Gall agent that tracks its state in the agent but delegates functionality to a JS library - * WASM calls as "userspace jets" - * I don’t think there’s an existing example for this - * Glicko-2 in JS or Python might be nice - * Would require finishing a Glicko-2 %telos which would be a pretty big job +What usage patterns are possible with WASM on Urbit? In this section we'll demonstrate several: +- WASM in a [generator](../../../hoon/generators.md). +- WASM in [threads](../../../urbit-os/base/threads/README.md). +- WASM in [Gall agents](../../app-school/README.md). diff --git a/content/build-on-urbit/wasm-walkthrough/examples/agent.md b/content/build-on-urbit/wasm-walkthrough/examples/agent.md index 03fd04ff..dbaf6fde 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/agent.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/agent.md @@ -1,3 +1,7 @@ # UrWASM Gall Agent Example foobar + +* In Gall agents + * You could do a Gall agent that tracks its state in the agent but delegates functionality to a JS library + diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index a5ffb14f..08834022 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -1,3 +1,8 @@ # UrWASM Generator Example foo + +* In generators + * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + * Stateless UrWASM: `+run-once` + * Tutorial: sort a list of 64-bit atoms diff --git a/content/build-on-urbit/wasm-walkthrough/examples/thread.md b/content/build-on-urbit/wasm-walkthrough/examples/thread.md index b79756d6..e0e66d4f 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/thread.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/thread.md @@ -2,3 +2,7 @@ foo +* [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + * Stateful UrWASM: `+run` + * Example: running Wasm in a thread + From 070de5de57ed14dbf85e6835c4e102a2d6d74b65 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Thu, 7 Aug 2025 15:08:43 +0100 Subject: [PATCH 05/57] Add UrWASM Structure to overview --- .../wasm-walkthrough/overview.md | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index d9f493f5..3fa8523a 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -63,7 +63,7 @@ In our case, we'll have to write our own bindings manually in Hoon. We'll cover ## Lia -The main theortical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWASM solves this by executing compiled WASM in Lia, a tiny interpreter that manages WASM's handful of nondeterministic edge-cases such that the same inputs to a WASM function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute WASM code at near-native speeds. +The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWASM solves this by executing compiled WASM in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages WASM's handful of nondeterministic edge-cases such that the same inputs to a WASM function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute WASM code at near-native speeds. * Determinism solved by Lia * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) @@ -72,3 +72,34 @@ The main theortical blocker to executing non-Hoon code on Urbit was that doing s * Higher level interpreting function * Lia interpreter +## UrWASM Structure + +UrWASM is structured as several nested cores, with each core in this list being in the [subject](../../hoon/why-hoon.md#subject-oriented-programming) of the core below. + +``` +/sur/wasm/wasm/hoon :: WASM types +/sur/wasm/engine/hoon :: WASM interpreter types +/sur/wasm/lia/hoon :: Lia types +/lib/wasm/parser/hoon :: WASM parser +/lib/wasm/validator/hoon :: WASM validator +/lib/wasm/runner/op-def/hoon :: WASM operator definitions +/lib/wasm/runner/engine/hoon :: WASM interpreter +/lib/wasm/lia/hoon :: Lia interpreter +``` + +All cores except `/lib/wasm/lia/hoon`, are additionally wrapped in one-armed cores for easy invocation: + +``` +/sur/wasm/wasm/hoon :: wasm-sur +/sur/wasm/engine/hoon :: engine-sur +/sur/wasm/lia/hoon :: lia-sur +/lib/wasm/parser/hoon :: parser +/lib/wasm/validator/hoon :: validator +/lib/wasm/runner/op-def/hoon :: op-def +/lib/wasm/runner/engine/hoon :: engine +``` + +Thus if you imported `/lib/wasm/lia/hoon` as `wasm`, you can get the core with Lia types as `lia-sur:wasm`. + +UrWASM's data types and functionality are covered in detail in the [reference](./reference/README.md) section. + From a06cc320c79108dcb85bced42a330edaaf74a250 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 14:52:10 +0100 Subject: [PATCH 06/57] Draft generator docs --- .../wasm-walkthrough/examples/generator.md | 279 +++++++++++++++++- 1 file changed, 274 insertions(+), 5 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index 08834022..df0a74de 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -1,8 +1,277 @@ # UrWASM Generator Example -foo +Let's use UrWASM to write a generator that can quickly sort a large list of 64-bit integers in ascending order. + +## Benchmark without UrWASM + +In pure Hoon, we would write something like this: + +```hoon +:: XX check this compiles and runs +|= lit=(list @G) +^- (list @G) +~> %bout +(sort lit lth) +``` + +Let's run this and see how long it takes. (`__~` in the Dojo discards the product of the given expression and returns `~`). + +``` +> =l (flop (gulf 0 1.000)) +> +took ms/63.434 +> __~ +run l +~ +``` + +## Building the WASM module + +Now let's sort the list using UrWasm, with the source code written in Rust. Initialize a new library cargo with `cargo new wasm_sort --lib` and edit `Cargo.toml`: + +```toml +[package] +name = "wasm_sort" +version = "0.1.0" +edition = "2024" + +[dependencies] +wasm-bindgen = "0.2" + +[lib] +crate-type = ["cdylib"] +``` + +Paste this source code into `sort.rs`: + +```rust +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn sort_u64(mut input: Vec) -> Vec { + input.sort(); + input +} +``` + +Run `wasm-pack build` and `wasm-pack` will compile the `wasm_sort.wasm` module from this file. The `wasm_bindgen` Rust library will be used to create a corresponding JS bindings file named something like `wasm_sort_bg.js`. + +## Writing Hoon bindings + +Let's see how the JS bindings file calls `sort_u64()`. Remember, this is a generated wrapper function that would be called from the web app. This wrapper function is what we'll have to reimplement in our new Hoon generator to call out to the compiled `wasm_sort.wasm` module. + +```javascript +// ... + +let WASM_VECTOR_LEN = 0; + +function passArray64ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 8, 8) >>> 0; + getBigUint64ArrayMemory0().set(arg, ptr / 8); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function getArrayU64FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getBigUint64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len); +} + +/** + * @param {BigUint64Array} input + * @returns {BigUint64Array} +**/ +export function sort_u64(input) { + const ptr0 = passArray64ToWasm0(input, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.sort_u64(ptr0, len0); + var v2 = getArrayU64FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 8, 8); + return v2; +} + +// ... +``` + +What's going on in this `sortu64()` wrapper function? We see that it does the following: +1. Allocates memory for the input vector by calling `__wbindgen_malloc`. +2. Writes the contents of the array to WASM memory. +3. Calls `sort_u64()` with the array pointer and length as parameters, which returns two values. +4. Uses those two values as the pointer and length of the resulting array, reads that from memory. +5. Frees the returned array from Wasm memory with `__wbindgen_free`. +6. Returns the sorted array. + +{TODO: better setup for yil-mold and acc-mold here.} + +We don't need to reimplement step 5, since the whole Wasm VM will be freed when we're done. + +Our generator with Hoon "bindings" will look like this in full. We'll examine each part in detail below. + +{% code title="/ted/sort.hoon" overflow="nowrap" lineNumbers="true" %} + +```hoon +/+ *wasm-lia +/* wasm-bin %wasm /sort/wasm +:: +:- %say +|= [* [lit=(list @G) ~] *] +:- %noun +^- (list @G) +~> %bout +:: +=> |% + +$ yil-mold (list @G) + +$ acc-mold * + -- +%- yield-need =< - +%^ (run-once yil-mold acc-mold) [wasm-bin [~ ~]] %$ +=/ m (script yil-mold acc-mold) +=/ arr (arrows acc-mold) +=, arr +=/ len-vec=@ (lent lit) +=/ len-bytes=@ (mul 8 len-vec) +=/ vec=@ (rep 6 lit) +:: +;< ptr=@ try:m (call-1 '__wbindgen_malloc' len-bytes 8 ~) +;< ~ try:m (memwrite ptr len-bytes vec) +;< ptr-len=(list @) try:m (call 'sort_u64' ptr len-vec ~) +;< vec-out=octs try:m (memread &1.ptr-len (mul 8 &2.ptr-len)) +:: +=/ lit-out=(list @) (rip 6 q.vec-out) +=/ lent-out=@ (lent lit-out) +?: =(len-vec lent-out) + (return:m lit-out) +%- return:m +%+ weld lit-out +(reap (sub len-vec lent-out) 0) +``` + +{% endcode %} + +What's going on here? + +First, we import the Lia interpreter and the `.wasm` module, which we've copied in to the root of our desk. (If you're working through this example, the `%base` desk on a fakeship would be fine.) + +```hoon +/+ *wasm-lia +/+ wasm-bin %wasm /sort/wasm +``` + +Mostly generator boilerplate, but note the `.lit` parameter and the output `(list @G)`. (That is, a `+list` of `@`s where `G` indicates a bitwidth of 64.) + +```hoon +:- %say +|= [* [lit=(list @G) ~] *] +:- %noun +^- (list @G) +``` + +We use the `%bout` runtime hint to time the computation that follows. + +```hoon +~> %bout +``` + +Now we'll define the types for our yield of the main script and the accumulator noun. We don't need the accumulator for this example but it's required for `+run-once`, so we'll just call it a noun `*`. + +{TODO: better intro to the yield concept} + +```hoon +=> |% + +$ yil-mold (list @G) :: type of the yield + +$ acc-mold * :: type of the accumulator + -- +``` + +Since Lia's `+run-once` returns a pair of \[yield accumulator], we grab the yield with [`=<`](../../../hoon/rune/tis.md#tisgal) to get the head (`-`) of the result. `+yield-need` is a Lia function that asserts that a yield is successful and returns the unwrapped result. The `%$` is where we'd specify a runtime hint like `%bout`, but we stub it out here as we don't need one. + +Below, we build Lia's `+run-once` gate and run it on our imported `.wasm-bin` module, which we give the empty initial state `[~ ~]`. (That is, a pair of the initial accumulator state and {foobar}). + +{TODO: not sure about this Lia `+run-once` verbiage above} + +{TODO: get clarity on (list coin-wasm) arg in wasm state} + +```hoon +:: run +yield-need on the head of the result +%- yield-need =< - +:: +:: build Lia's +run-once core with our .yil-mold +:: and .acc-mold and run it with our .wasm-bin, which +:: will be given the empty state [~ ~] +%^ (run-once yil-mold acc-mold) [wasm-bin [~ ~]] %$ +``` + +Some more boilerplate. Hoon developers will recognize `.m` by analogy to the `.m` from the boilerplate often seen in [threads](../../../urbit-os/base/threads/README.md). `.arrows` is our built `+arrows` core from Lia, and we expose that namespace with [`=,`](../../../hoon/rune/tis.md#tiscom) for convenient usage later. + +{TODO: link to `+arrows` documentation in the reference section once it exists} + +```hoon +:: define the monadic interface for the script +=/ m (script yil-mold acc-mold) +:: define basic operations +=/ arr (arrows acc-mold) +:: expose the .arr namespace +=, arr +``` + +We'll measure the input list and concatonate all of its elements into a single atom with [`+rep`](../../../hoon/stdlib/2c.md#rep). + +{TODO: amend generator code style and update all code blocks accordingly} + +```hoon +:: number of items in the list +=/ len-vec=@ (lent lit) +:: byte-length of the list +=/ len-bytes=@ (mul 8 len-vec) +:: 2^6 = 64 bits per list element +=/ vec=@ (rep 6 lit) +``` + +With that out of the way we can now interact with Wasm VM, replicating steps 1-4 of the JS binding we're using as a reference. We make heavy use of Hoon's [`;<`](../../../hoon/rune/mic.md#micgal) monadic pipeline builder, running expressions and piping the result directly into the one that follows. + +```hoon +:: allocate memory +;< ptr=@ try:m (call-1 '__wbindgen_malloc' len-bytes 8 ~) +:: write the input vector +;< ~ try:m (memwrite ptr len-bytes vec) +:: call the sort_u64 function in the module +;< ptr-len=(list @) try:m (call 'sort_u64' ptr len-vec ~) +:: read the resulting vector from memory +;< vec-out=octs try:m (memread &1.ptr-len (mul 8 &2.ptr-len)) +``` + +Now we split the resulting octets atom (`$octs`, a cell of byte length and data) into a list of 64-bit atoms with [`+rip`](../../../hoon/stdlib/2c.md) and add missing trailing zeroes if necessary. + +{TODO: why would trailing zeroes be missing?} + +```hoon +:: rip the octet stream into a list of 64-bit atoms +=/ lit-out=(list @) (rip 6 q.vec-out) +:: measure the length of the list +=/ lent-out=@ (lent lit-out) +:: +:: check if .lent-out equals the length of the +:: original list we passed into the generator +?: =(len-vec lent-out) + :: if so, return the output list + (return:m lit-out) +:: +:: if not, use +return from the .m +script core to +:: return the output list with enough trailing zeroes +:: to match the length of the input list +%- return:m +%+ weld lit-out +(reap (sub len-vec lent-out) 0) +``` + +Once you have the `sort.wasm` module and the `sort.hoon` generator in your `%base` desk, run `|commit %base` and run this generator in the Dojo, again timing it with the `%bout` in the generator. + +``` +took ms/5.012 +> __~ +sort l +~ +``` + +{TODO: get example data in there} + +A 10x speedup compared to pure Hoon for our test case (1.000 elements, reversed ordering). -* In generators - * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - * Stateless UrWASM: `+run-once` - * Tutorial: sort a list of 64-bit atoms From f0c65fa5ba782bd5b9d17b51f397cb2126c9797e Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 14:53:11 +0100 Subject: [PATCH 07/57] Add todo to generator --- content/build-on-urbit/wasm-walkthrough/examples/generator.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index df0a74de..b50170f9 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -7,13 +7,14 @@ Let's use UrWASM to write a generator that can quickly sort a large list of 64-b In pure Hoon, we would write something like this: ```hoon -:: XX check this compiles and runs |= lit=(list @G) ^- (list @G) ~> %bout (sort lit lth) ``` +{TODO: check the above compiles and runs} + Let's run this and see how long it takes. (`__~` in the Dojo discards the product of the given expression and returns `~`). ``` From 6bce6858eaab2072a2ab078d04c1a7bae63368d6 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 14:54:19 +0100 Subject: [PATCH 08/57] Change /ted to /gen --- content/build-on-urbit/wasm-walkthrough/examples/generator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index b50170f9..85d3ecec 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -107,7 +107,7 @@ We don't need to reimplement step 5, since the whole Wasm VM will be freed when Our generator with Hoon "bindings" will look like this in full. We'll examine each part in detail below. -{% code title="/ted/sort.hoon" overflow="nowrap" lineNumbers="true" %} +{% code title="/gen/sort.hoon" overflow="nowrap" lineNumbers="true" %} ```hoon /+ *wasm-lia From d046f444b462110d7e1c16e0acd41e9d2546b33d Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 15:20:40 +0100 Subject: [PATCH 09/57] Add l arg to dojo example --- content/build-on-urbit/wasm-walkthrough/examples/generator.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index 85d3ecec..cc9c512d 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -267,12 +267,12 @@ Now we split the resulting octets atom (`$octs`, a cell of byte length and data) Once you have the `sort.wasm` module and the `sort.hoon` generator in your `%base` desk, run `|commit %base` and run this generator in the Dojo, again timing it with the `%bout` in the generator. ``` +> =l (flop (gulf 0 1.000)) +> took ms/5.012 > __~ +sort l ~ ``` -{TODO: get example data in there} - A 10x speedup compared to pure Hoon for our test case (1.000 elements, reversed ordering). From 1dd8b0c1f8b4d39463b365e6f859f6eee3f1ba9b Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 15:43:05 +0100 Subject: [PATCH 10/57] Fix conclusion --- content/build-on-urbit/wasm-walkthrough/examples/generator.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index cc9c512d..9d140555 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -264,7 +264,7 @@ Now we split the resulting octets atom (`$octs`, a cell of byte length and data) (reap (sub len-vec lent-out) 0) ``` -Once you have the `sort.wasm` module and the `sort.hoon` generator in your `%base` desk, run `|commit %base` and run this generator in the Dojo, again timing it with the `%bout` in the generator. +Once you have the `sort.wasm` module and `/gen/sort.hoon` in your `%base` desk, run `|commit %base` and run this `+sort` generator in the Dojo; again we'll see the timed computation with `%bout`. ``` > =l (flop (gulf 0 1.000)) @@ -274,5 +274,5 @@ took ms/5.012 ~ ``` -A 10x speedup compared to pure Hoon for our test case (1.000 elements, reversed ordering). +This is a ~10x speedup compared to the pure Hoon implementation. From 81a8f7edd743e66b1c44e299145d629b935ea70a Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 15:57:45 +0100 Subject: [PATCH 11/57] UrWASM to UrWasm --- content/build-on-urbit/wasm-walkthrough/README.md | 8 ++++---- .../wasm-walkthrough/examples/README.md | 2 +- .../wasm-walkthrough/examples/agent.md | 2 +- .../wasm-walkthrough/examples/generator.md | 6 +++--- .../wasm-walkthrough/examples/thread.md | 4 ++-- content/build-on-urbit/wasm-walkthrough/overview.md | 12 ++++++------ .../wasm-walkthrough/reference/README.md | 2 +- .../wasm-walkthrough/reference/data-types.md | 2 +- .../wasm-walkthrough/reference/wasm-libs.md | 6 +++--- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md index b013741c..981b33bc 100644 --- a/content/build-on-urbit/wasm-walkthrough/README.md +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -15,10 +15,10 @@ layout: # WASM Walkthrough -Urbit's WebAssembly affordances (collectively known as "UrWASM") enables Hoon developers to leverage pre-existing libraries from any WASM-compatible language like Rust, Python, and Go. Using QuickJS as a WASM module, they can also run Javascript on the Urbit ship. +Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any WASM-compatible language like Rust, Python, and Go. Using QuickJS as a WASM module, they can also run Javascript on the Urbit ship. These docs cover: -- UrWASM overview -- UrWASM examples -- UrWASM types and API +- UrWasm overview +- UrWasm examples +- UrWasm types and API diff --git a/content/build-on-urbit/wasm-walkthrough/examples/README.md b/content/build-on-urbit/wasm-walkthrough/examples/README.md index 4bbdfc30..b313cac5 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/README.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/README.md @@ -1,4 +1,4 @@ -# UrWASM Examples +# UrWasm Examples What usage patterns are possible with WASM on Urbit? In this section we'll demonstrate several: - WASM in a [generator](../../../hoon/generators.md). diff --git a/content/build-on-urbit/wasm-walkthrough/examples/agent.md b/content/build-on-urbit/wasm-walkthrough/examples/agent.md index dbaf6fde..1bbf0ff7 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/agent.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/agent.md @@ -1,4 +1,4 @@ -# UrWASM Gall Agent Example +# UrWasm Gall Agent Example foobar diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index 9d140555..b0c7dd08 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -1,8 +1,8 @@ -# UrWASM Generator Example +# UrWasm Generator Example -Let's use UrWASM to write a generator that can quickly sort a large list of 64-bit integers in ascending order. +Let's use UrWasm to write a generator that can quickly sort a large list of 64-bit integers in ascending order. -## Benchmark without UrWASM +## Benchmark without UrWasm In pure Hoon, we would write something like this: diff --git a/content/build-on-urbit/wasm-walkthrough/examples/thread.md b/content/build-on-urbit/wasm-walkthrough/examples/thread.md index e0e66d4f..aed205ad 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/thread.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/thread.md @@ -1,8 +1,8 @@ -# UrWASM Thread Example +# UrWasm Thread Example foo * [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - * Stateful UrWASM: `+run` + * Stateful UrWasm: `+run` * Example: running Wasm in a thread diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index 3fa8523a..6e39c132 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -1,10 +1,10 @@ -# UrWASM Overview +# UrWasm Overview Onboarding new developers onto Urbit necessarily involves teaching them [Hoon](../../hoon/why-hoon.md). Whatever Hoon's merits as a systems programming language, the time commitment to understanding the language enough to be productive is an obvious barrier to entry. Urbit allows developers to run server-side code in languages like Rust and Python by compiling that code to [WebAssembly](https://webassembly.org/) (WASM). They can run Javascript on the Urbit ship with a JS interpreter like QuickJS. Today this still involves some knowledge of Hoon, but the developer can mostly use the examples here as boilerplate. -Trivially, Urbit's WASM affordances (collectively "UrWASM") enable Hoon developers to leverage pre-existing libraries for functionality that doesn't already exist in Hoon, or would be prohibitively slow without writing a C [runtime jet](../runtime/jetting.md). But one can imagine more ambitious use-cases like running complete Next.js or Rust apps on the Urbit ship. +Trivially, Urbit's WASM affordances (collectively "UrWasm") enable Hoon developers to leverage pre-existing libraries for functionality that doesn't already exist in Hoon, or would be prohibitively slow without writing a C [runtime jet](../runtime/jetting.md). But one can imagine more ambitious use-cases like running complete Next.js or Rust apps on the Urbit ship. ## WebAssembly @@ -63,7 +63,7 @@ In our case, we'll have to write our own bindings manually in Hoon. We'll cover ## Lia -The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWASM solves this by executing compiled WASM in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages WASM's handful of nondeterministic edge-cases such that the same inputs to a WASM function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute WASM code at near-native speeds. +The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWasm solves this by executing compiled WASM in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages WASM's handful of nondeterministic edge-cases such that the same inputs to a WASM function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute WASM code at near-native speeds. * Determinism solved by Lia * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) @@ -72,9 +72,9 @@ The main theoretical blocker to executing non-Hoon code on Urbit was that doing * Higher level interpreting function * Lia interpreter -## UrWASM Structure +## UrWasm Structure -UrWASM is structured as several nested cores, with each core in this list being in the [subject](../../hoon/why-hoon.md#subject-oriented-programming) of the core below. +UrWasm is structured as several nested cores, with each core in this list being in the [subject](../../hoon/why-hoon.md#subject-oriented-programming) of the core below. ``` /sur/wasm/wasm/hoon :: WASM types @@ -101,5 +101,5 @@ All cores except `/lib/wasm/lia/hoon`, are additionally wrapped in one-armed cor Thus if you imported `/lib/wasm/lia/hoon` as `wasm`, you can get the core with Lia types as `lia-sur:wasm`. -UrWASM's data types and functionality are covered in detail in the [reference](./reference/README.md) section. +UrWasm's data types and functionality are covered in detail in the [reference](./reference/README.md) section. diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm-walkthrough/reference/README.md index 0be38fa7..8187c7d6 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/README.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/README.md @@ -1,4 +1,4 @@ -# UrWASM Reference +# UrWasm Reference foobar diff --git a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md index 54fa0420..069eee74 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md @@ -1,4 +1,4 @@ -# UrWASM Data Types +# UrWasm Data Types nested core structure diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md index 00e7138e..2c63980e 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md @@ -1,4 +1,4 @@ -# UrWASM Library Reference +# UrWasm Library Reference nested core structure @@ -10,8 +10,8 @@ nested core structure foobar - * Stateless UrWASM: `+run-once` - * Stateful UrWASM: `+run` + * Stateless UrWasm: `+run-once` + * Stateful UrWasm: `+run` *** From ea76720fa2ecaf11d79544234934c3dfd6c893f8 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 8 Aug 2025 15:59:53 +0100 Subject: [PATCH 12/57] WASM to Wasm --- .../build-on-urbit/wasm-walkthrough/README.md | 4 ++-- .../wasm-walkthrough/examples/README.md | 8 +++---- .../wasm-walkthrough/examples/generator.md | 4 ++-- .../wasm-walkthrough/overview.md | 24 +++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md index 981b33bc..dd6e91fe 100644 --- a/content/build-on-urbit/wasm-walkthrough/README.md +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -13,9 +13,9 @@ layout: visible: true --- -# WASM Walkthrough +# Wasm Walkthrough -Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any WASM-compatible language like Rust, Python, and Go. Using QuickJS as a WASM module, they can also run Javascript on the Urbit ship. +Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any Wasm-compatible language like Rust, Python, and Go. Using QuickJS as a Wasm module, they can also run Javascript on the Urbit ship. These docs cover: - UrWasm overview diff --git a/content/build-on-urbit/wasm-walkthrough/examples/README.md b/content/build-on-urbit/wasm-walkthrough/examples/README.md index b313cac5..28c591c0 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/README.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/README.md @@ -1,6 +1,6 @@ # UrWasm Examples -What usage patterns are possible with WASM on Urbit? In this section we'll demonstrate several: -- WASM in a [generator](../../../hoon/generators.md). -- WASM in [threads](../../../urbit-os/base/threads/README.md). -- WASM in [Gall agents](../../app-school/README.md). +What usage patterns are possible with Wasm on Urbit? In this section we'll demonstrate several: +- Wasm in a [generator](../../../hoon/generators.md). +- Wasm in [threads](../../../urbit-os/base/threads/README.md). +- Wasm in [Gall agents](../../app-school/README.md). diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/examples/generator.md index b0c7dd08..fb6186dd 100644 --- a/content/build-on-urbit/wasm-walkthrough/examples/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/examples/generator.md @@ -25,7 +25,7 @@ took ms/63.434 ~ ``` -## Building the WASM module +## Building the Wasm module Now let's sort the list using UrWasm, with the source code written in Rust. Initialize a new library cargo with `cargo new wasm_sort --lib` and edit `Cargo.toml`: @@ -95,7 +95,7 @@ export function sort_u64(input) { What's going on in this `sortu64()` wrapper function? We see that it does the following: 1. Allocates memory for the input vector by calling `__wbindgen_malloc`. -2. Writes the contents of the array to WASM memory. +2. Writes the contents of the array to Wasm memory. 3. Calls `sort_u64()` with the array pointer and length as parameters, which returns two values. 4. Uses those two values as the pointer and length of the resulting array, reads that from memory. 5. Frees the returned array from Wasm memory with `__wbindgen_free`. diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index 6e39c132..db3eb53d 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -2,17 +2,17 @@ Onboarding new developers onto Urbit necessarily involves teaching them [Hoon](../../hoon/why-hoon.md). Whatever Hoon's merits as a systems programming language, the time commitment to understanding the language enough to be productive is an obvious barrier to entry. -Urbit allows developers to run server-side code in languages like Rust and Python by compiling that code to [WebAssembly](https://webassembly.org/) (WASM). They can run Javascript on the Urbit ship with a JS interpreter like QuickJS. Today this still involves some knowledge of Hoon, but the developer can mostly use the examples here as boilerplate. +Urbit allows developers to run server-side code in languages like Rust and Python by compiling that code to [WebAssembly](https://webassembly.org/) (Wasm). They can run Javascript on the Urbit ship with a JS interpreter like QuickJS. Today this still involves some knowledge of Hoon, but the developer can mostly use the examples here as boilerplate. -Trivially, Urbit's WASM affordances (collectively "UrWasm") enable Hoon developers to leverage pre-existing libraries for functionality that doesn't already exist in Hoon, or would be prohibitively slow without writing a C [runtime jet](../runtime/jetting.md). But one can imagine more ambitious use-cases like running complete Next.js or Rust apps on the Urbit ship. +Trivially, Urbit's Wasm affordances (collectively "UrWasm") enable Hoon developers to leverage pre-existing libraries for functionality that doesn't already exist in Hoon, or would be prohibitively slow without writing a C [runtime jet](../runtime/jetting.md). But one can imagine more ambitious use-cases like running complete Next.js or Rust apps on the Urbit ship. ## WebAssembly -WebAssembly is a small, hardware-independent assembly language for a stack-based virtual machine, primarily intended to be deployed on the web for client- and server-side applications that may be written in one of many programming languages other than Javascript. WASM is supported out-of-the-box in all mainstream browsers, and it uses Web APIs wherever possible, but WASM may be executed in other runtimes. +WebAssembly is a small, hardware-independent assembly language for a stack-based virtual machine, primarily intended to be deployed on the web for client- and server-side applications that may be written in one of many programming languages other than Javascript. Wasm is supported out-of-the-box in all mainstream browsers, and it uses Web APIs wherever possible, but Wasm may be executed in other runtimes. -Compiled WASM code (a `.wasm` file) is structured as a module, which consists of import and export declarations, function definitions, global variable and memory declarations, etc. A WASM module describes the starting state of a WASM virtual machine, whose state is modified by calling its functions, writing directly to the memory of the module, or what have you. +Compiled Wasm code (a `.wasm` file) is structured as a module, which consists of import and export declarations, function definitions, global variable and memory declarations, etc. A Wasm module describes the starting state of a Wasm virtual machine, whose state is modified by calling its functions, writing directly to the memory of the module, or what have you. -As a low-level language, WASM's functions only return 32/64 bit integers and floating-point numbers. Higher-level information like structs and function signatures are stripped away during compliation and must be restored via "host language bindings", which reimplement the source code functions as wrappers around calls to the WASM VM. These may be generated automatically by the WASM compiler in addition to the `.wasm` module, usually in Javascript if the code is targeting a browser. +As a low-level language, Wasm's functions only return 32/64 bit integers and floating-point numbers. Higher-level information like structs and function signatures are stripped away during compliation and must be restored via "host language bindings", which reimplement the source code functions as wrappers around calls to the Wasm VM. These may be generated automatically by the Wasm compiler in addition to the `.wasm` module, usually in Javascript if the code is targeting a browser. For example, the following Rust code... @@ -63,7 +63,7 @@ In our case, we'll have to write our own bindings manually in Hoon. We'll cover ## Lia -The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWasm solves this by executing compiled WASM in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages WASM's handful of nondeterministic edge-cases such that the same inputs to a WASM function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute WASM code at near-native speeds. +The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWasm solves this by executing compiled Wasm in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages Wasm's handful of nondeterministic edge-cases such that the same inputs to a Wasm function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute Wasm code at near-native speeds. * Determinism solved by Lia * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) @@ -77,13 +77,13 @@ The main theoretical blocker to executing non-Hoon code on Urbit was that doing UrWasm is structured as several nested cores, with each core in this list being in the [subject](../../hoon/why-hoon.md#subject-oriented-programming) of the core below. ``` -/sur/wasm/wasm/hoon :: WASM types -/sur/wasm/engine/hoon :: WASM interpreter types +/sur/wasm/wasm/hoon :: Wasm types +/sur/wasm/engine/hoon :: Wasm interpreter types /sur/wasm/lia/hoon :: Lia types -/lib/wasm/parser/hoon :: WASM parser -/lib/wasm/validator/hoon :: WASM validator -/lib/wasm/runner/op-def/hoon :: WASM operator definitions -/lib/wasm/runner/engine/hoon :: WASM interpreter +/lib/wasm/parser/hoon :: Wasm parser +/lib/wasm/validator/hoon :: Wasm validator +/lib/wasm/runner/op-def/hoon :: Wasm operator definitions +/lib/wasm/runner/engine/hoon :: Wasm interpreter /lib/wasm/lia/hoon :: Lia interpreter ``` From e0c768c150509302bfa9cd8859665c1eb850964c Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 11 Aug 2025 15:32:51 +0100 Subject: [PATCH 13/57] Start Wasm data types --- .../wasm-walkthrough/reference/README.md | 17 +- .../wasm-walkthrough/reference/data-types.md | 1161 ++++++++++++++++- 2 files changed, 1159 insertions(+), 19 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm-walkthrough/reference/README.md index 8187c7d6..25da38d7 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/README.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/README.md @@ -1,9 +1,8 @@ # UrWasm Reference -foobar - -Urwasm is structured as a series of nested cores: +UrWasm is structured as a series of nested cores: +``` /sur/wasm/wasm/hoon :: Wasm types definition /sur/wasm/engine/hoon :: Wasm interpreter types /sur/wasm/lia/hoon :: Lia [Language for Invocation of (web)Assembly] types @@ -12,14 +11,6 @@ Urwasm is structured as a series of nested cores: /lib/wasm/runner/op-def/hoon :: Wasm operator definitions /lib/wasm/runner/engine/hoon :: Wasm interpreter /lib/wasm/lia/hoon :: Lia interpreter +``` -All cores except for the topmost, defined in /lib/wasm/lia/hoon are additionally wrapped in one-armed cores to manage the namespace: - -/sur/wasm/wasm/hoon -> wasm-sur -/sur/wasm/engine/hoon -> engine-sur -/sur/wasm/lia/hoon -> lia-sur -/lib/wasm/parser/hoon -> parser -/lib/wasm/validator/hoon -> validator -/lib/wasm/runner/op-def/hoon -> op-def -/lib/wasm/runner/engine/hoon -> engine - +This reference section documents the UrWasm project's data types and library functionality. diff --git a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md index 069eee74..df6cbb2a 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md @@ -1,18 +1,1167 @@ # UrWasm Data Types -nested core structure +UrWasm's data types are defined in three nested `/sur` files in `%base`; innermost to outermost: +``` /sur/wasm/wasm/hoon :: Wasm types definition /sur/wasm/engine/hoon :: Wasm interpreter types /sur/wasm/lia/hoon :: Lia [Language for Invocation of (web)Assembly] types +``` -foobar +## Wasm types -## /sur/wasm/wasm/hoon -Wasm types definition +UrWasm's inner core, `+wasm-sur`, contains the foundational Wasm types. + +The first part implements the Structure chapter of the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/index.html). The second part implements Wasm's binary-format opcodes. + +### `$octs` (pair @ud @) + +```hoon ++$ octs (pair @ud @) +``` + +Pair of byte-length and octet stream data. + +### `+wasm-sur` + +Wrapper arm around the Wasm types. This just makes the types addressable by limb resolution paths like `num-type:wasm-sur`. + +### `$num-type` + +```hoon ++$ num-type ?(%i32 %i64 %f32 %f64) +``` + +Type annotation for the four types of number Wasm calls can return: +- 32-bit integers (`@F`). +- 64-bit integers (`@G`). +- 32-bit floating point numbers (`@rs`). +- 64-bit floating point numbers (`@rd`). + +### `$vec-type` + +```hoon ++$ vec-type %v128 +``` + +Type annotation for a 128-bit vector (`@H`). + +### `$ref-type` + +```hoon ++$ ref-type ?(%extn %func) :: externref and funcref +``` + +Type annotation for ??? + +### `$valtype` + +```hoon ++$ valtype + $~ %i32 + $? num-type + vec-type + ref-type + == +``` + +Type annotation for ??? + +### `$coin-wasm` + +```hoon ++$ coin-wasm + $~ [%i32 *@F] + $% [%i32 @F] + [%i64 @G] + [%f32 @rs] + [%f64 @rd] + [vec-type @H] + $: %ref :: function reference, null or not + $% [%func (unit @)] :: local + $: %extn :: external + %- unit + $: [mod=cord name=cord] + type=func-type + == == == == + :: + == +``` + +Type-annotated Wasm value. + +### `$limits` + +```hoon ++$ limits + $% [%flor p=@] :: min only + [%ceil p=@ q=@] :: min and max + == +``` + +??? + +### `$memarg` + +```hoon ++$ memarg + $+ memarg + [align=@ offset=@] +``` + +??? + +### `$block-type` + +```hoon ++$ block-type $@(@ func-type) :: typeidx in type section or func-type +``` + +??? + +### `$func-type` + +```hoon ++$ func-type + $: params=(list valtype) + results=(list valtype) + == +``` + +??? + +### `$lane-type` + +```hoon ++$ lane-type ?(%i8 %i16 num-type) +``` + +??? + +### `$instruction` + +```hoon ++$ instruction + $%([%vec instr-vec] instr-short instr-num instr-dbug) +``` + +??? + +### `$instr-dbug` + +```hoon ++$ instr-dbug + $% + [%dbug %print-tee term] + == +``` + +??? + +### `$instr-num` + +```hoon ++$ instr-num ?(instr-num-zero instr-num-one instr-num-two) +``` + +??? + +### `$instr-num-zero` + +```hoon ++$ instr-num-zero + $% + [%const p=$<(?(%v128 %ref) coin-wasm)] + == +``` + +??? + +### `$instr-num-one` + +```hoon ++$ instr-num-one + $% + [%eqz type=?(%i32 %i64)] + [%clz type=?(%i32 %i64)] + [%ctz type=?(%i32 %i64)] + [%popcnt type=?(%i8 %i32 %i64)] + [%abs type=lane-type] + [%neg type=lane-type] + [%ceil type=?(%f32 %f64)] + [%floor type=?(%f32 %f64)] + :: + $: %trunc + type=num-type + source-type=(unit ?(%f32 %f64)) + mode=(unit ?(%s %u)) + sat=? + == + :: + [%nearest type=?(%f32 %f64)] + [%sqrt type=?(%f32 %f64)] + [%wrap ~] + :: + $: %extend + type=?(%i32 %i64) + source-type=?(%i32 %i64) + source-size=?(%8 %16 %32) + mode=?(%s %u) + == + :: + [%convert type=?(%f32 %f64) source-type=?(%i32 %i64) mode=?(%s %u)] + [%demote ~] + [%promote ~] + [%reinterpret type=num-type source-type=num-type] + == +``` + +??? + +### `$instr-num-two` + +```hoon ++$ instr-num-two + $% + [%eq type=lane-type] + [%ne type=lane-type] + [%lt type=lane-type mode=(unit ?(%s %u))] + [%gt type=lane-type mode=(unit ?(%s %u))] + [%le type=lane-type mode=(unit ?(%s %u))] + [%ge type=lane-type mode=(unit ?(%s %u))] + [%add type=lane-type] + [%sub type=lane-type] + [%mul type=lane-type] + [%div type=lane-type mode=(unit ?(%s %u))] + [%rem type=?(%i32 %i64) mode=?(%s %u)] + [%and type=?(%i32 %i64)] + [%or type=?(%i32 %i64)] + [%xor type=?(%i32 %i64)] + [%shl type=?(%i8 %i16 %i32 %i64)] + [%shr type=?(%i8 %i16 %i32 %i64) mode=?(%s %u)] + [%rotl type=?(%i32 %i64)] + [%rotr type=?(%i32 %i64)] + [%min type=?(%f32 %f64)] + [%max type=?(%f32 %f64)] + [%copysign type=?(%f32 %f64)] + == +``` + +??? + +### `$instr-short` + +```hoon ++$ instr-short + $% + :: Control instructions + :: + [%unreachable ~] + [%nop ~] + [%block type=block-type body=expression] + [%loop type=block-type body=expression] + $: %if + type=block-type + branch-true=expression + branch-false=expression + == + :: + [%br label=@] + [%br-if label=@] + [%br-table label-vec=(list @) label-default=@] + [%return ~] + [%call func-id=@] + [%call-indirect type-id=@ table-id=@] + :: Reference instructions + :: + [%ref-null t=ref-type] + [%ref-is-null ~] + [%ref-func func-id=@] + :: Parametric instructions + :: + [%drop ~] + [%select (unit (list valtype))] + :: Variable instructions + :: + [%local-get index=@] + [%local-set index=@] + [%local-tee index=@] + [%global-get index=@] + [%global-set index=@] + :: Table instructions + :: + [%table-get tab-id=@] + [%table-set tab-id=@] + [%table-init elem-id=@ tab-id=@] + [%elem-drop elem-id=@] + [%table-copy tab-id-x=@ tab-id-y=@] + [%table-grow tab-id=@] + [%table-size tab-id=@] + [%table-fill tab-id=@] + :: Memory instructions + :: + $: %load + type=num-type + m=memarg + n=(unit ?(%8 %16 %32)) + mode=(unit ?(%s %u)) + == + :: + $: %store + type=num-type + m=memarg + n=(unit ?(%8 %16 %32)) + == + :: + [%memory-size mem-id=%0] + [%memory-grow mem-id=%0] + [%memory-init x=@ mem-id=%0] + [%data-drop x=@] + [%memory-copy mem-1=%0 mem-2=%0] + [%memory-fill mem-id=%0] + == :: $instr-short +``` + +??? + +### `$instr-vec` + +```hoon ++$ instr-vec + $% + :: Load + :: + $: %load + m=memarg + $= kind %- unit + $: p=?(%8 %16 %32 %64) + q=?(%splat %zero [%extend ?(%s %u)]) + == == + :: + [%load-lane m=memarg p=?(%8 %16 %32 %64) l=@] + :: Store + :: + [%store m=memarg] + [%store-lane m=memarg p=?(%8 %16 %32 %64) l=@] + :: Misc + [%const p=$>(%v128 coin-wasm)] + [%shuffle lane-ids=(list @)] + [%extract p=lane-type l=@ mode=?(%s %u)] + [%replace p=lane-type l=@] + :: Plain + :: + [%swizzle ~] + [%splat p=lane-type] + [%eq p=lane-type] + [%ne p=lane-type] + [%lt p=lane-type mode=?(%u %s)] + [%gt p=lane-type mode=?(%u %s)] + [%le p=lane-type mode=?(%u %s)] + [%ge p=lane-type mode=?(%u %s)] + [%not ~] + [%and ~] + [%andnot ~] + [%or ~] + [%xor ~] + [%bitselect ~] + [%any-true ~] + [%abs p=lane-type] + [%neg p=lane-type] + [%popcnt ~] + [%all-true p=?(%i8 %i16 %i32 %i64)] + [%bitmask p=?(%i8 %i16 %i32 %i64)] + [%narrow p=?(%i8 %i16) mode=?(%u %s)] + [%shl p=?(%i8 %i16 %i32 %i64)] + [%shr p=?(%i8 %i16 %i32 %i64) mode=?(%u %s)] + [%add p=lane-type sat=(unit ?(%u %s))] + [%sub p=lane-type sat=(unit ?(%u %s))] + [%min p=lane-type mode=?(%u %s)] + [%max p=lane-type mode=?(%u %s)] + [%avgr p=?(%i8 %i16) mode=%u] + [%extadd p=?(%i16 %i32) mode=?(%u %s)] + [%q15mul-r-sat ~] + [%extend p=?(%i16 %i32 %i64) mode=?(%u %s) half=?(%high %low)] + [%mul p=lane-type] + [%extmul p=?(%i16 %i32 %i64) mode=?(%u %s) half=?(%high %low)] + [%dot ~] + [%ceil p=?(%f32 %f64)] + [%floor p=?(%f32 %f64)] + [%trunc p=?(%i32 %f32 %f64) from=?(%f32 %f64) mode=?(%u %s)] + [%nearest p=?(%f32 %f64)] + [%sqrt p=?(%f32 %f64)] + [%div p=?(%f32 %f64)] + [%pmin p=?(%f32 %f64)] + [%pmax p=?(%f32 %f64)] + [%convert p=?(%f32 %f64) mode=?(%u %s)] + [%demote ~] + [%promote ~] + == :: $instr-vec +``` + +??? + +### `$expression` + +```hoon ++$ expression (list instruction) +``` + +List of `$instruction`s. + +### `$const-instr` + +```hoon ++$ const-instr + $~ [%const %i32 `@`0] + $? [%vec $>(%const instr-vec)] + $>(?(%const %global-get %ref-null %ref-func) instruction) + == +``` + +??? + +### `$module` + +```hoon ++$ module + $: + =type-section + =import-section + =function-section + =table-section + =memory-section + =global-section + =export-section + =start-section + =elem-section + =datacnt-section + =code-section + =data-section + == +``` + +A Wasm module, represented in a format closer to its binary representation (i.e. separate code and function sections) to simplify parsing. + +### `$type-section` + +```hoon ++$ type-section + $+ type-section + (list func-type) +``` + +??? + +### `$import-section` + +```hoon ++$ import-section + $+ import-section + (list import) +``` + +??? + +### `$import` + +```hoon +``` + +??? + +### `$function-section` + +```hoon ++$ function-section + $+ function-section + (list type-id=@) +``` + +??? + +### `$table-section` + +```hoon ++$ table-section (list table) +``` + +??? + +### `$table` + +```hoon ++$ table (pair ref-type limits) +``` + +??? + +### `$memory-section` + +```hoon ++$ memory-section (list limits) +``` + +??? + +### `$global-section` + +```hoon ++$ global-section (list global) +``` + +??? + +### `$global` + +```hoon ++$ global + $: v=valtype + m=?(%con %var) + i=const-instr + == +``` + + :: valtype, mutability and init value. + :: We use a single constant instruction as opposed to a + :: (list instruction) since there is no global value type + :: that would take multiple constant values + +### `$export-section` + +```hoon ++$ export-section + $+ export-section + (list export) +``` + +??? + +### `$export` + +```hoon ++$ export [name=cord =export-desc] +``` + +??? + +### `$export-desc` + +```hoon ++$ export-desc + $% [%func i=@] + [%tabl i=@] + [%memo i=@] + [%glob i=@] + == +``` + +??? + +### `$start-section` + +```hoon ++$ start-section (unit @) +``` + +??? + +### `$elem-section` + +```hoon ++$ elem-section (list elem) +``` + +??? + +### `$elem` + +```hoon ++$ elem + $~ [*ref-type ~ %pass ~] + $: t=ref-type + i=(list $>(?(%ref-func %ref-null) instruction)) + $= m + $% [%pass ~] + [%decl ~] + [%acti tab=@ off=const-instr] + == == +``` + +??? + +### `$code-section` + +```hoon ++$ code-section + $+ code-section + (list code) +``` + +??? + +### `$code` + +```hoon ++$ code + $: locals=(list valtype) + =expression + == +``` + +??? + +### `$data-section` + +```hoon ++$ data-section (list data) +``` + +??? + +### `$data` + +```hoon ++$ data + $% + [%acti off=const-instr b=octs] + [%pass b=octs] + == +``` + +??? + +### `+datacnt-section` + +```hoon +++ datacnt-section (unit @) +``` + +??? + +### `$opcode` + +```hoon ++$ opcode $? bin-opcodes-zero-args + bin-opcodes-one-arg + bin-opcodes-two-args + bin-opcodes-blocks + pseudo-opcode + == +``` + +??? + +### `$bin-opcodes-zero-args` + +```hoon ++$ bin-opcodes-zero-args + $? +:: trap nop return drop select wrap demote promote + %0x0 %0x1 %0xf %0x1a %0x1b %0xa7 %0xb6 %0xbb +:: + eqz-opcodes eq-opcodes ne-opcodes lt-opcodes gt-opcodes le-opcodes + ge-opcodes clz-opcodes ctz-opcodes popcnt-opcodes add-opcodes + sub-opcodes mul-opcodes div-opcodes rem-opcodes and-opcodes or-opcodes + xor-opcodes shl-opcodes shr-opcodes rotl-opcodes rotr-opcodes + abs-opcodes neg-opcodes ceil-opcodes floor-opcodes trunc-opcodes + nearest-opcodes sqrt-opcodes min-opcodes max-opcodes copysign-opcodes + extend-opcodes convert-opcodes reinterpret-opcodes + == +``` + +WebAssembly opcodes. Most of these are defined in the types below, with some exceptions defined here: +- `%0x0`: ??? error? +- `%0x01`: `nop`, no-op, do nothing. +- `%0x0f`: `return` the result of a function, with two wrinkles: + - If there's nothing in the stack to return, this returns nothing. + - If there are more values on the stack than allowed by the function's return type, the first $$n$$ values are returned (where $$n$$ is the number of values allowed) and the rest are discarded. +- `%0x1a`: `drop` a value from the stack. +- `%0x1b`: Like a ternary operator, `select` one of the first two operands based on whether the third is `0` or not. +- `%0xa7`: Convert an `i64` to an `i32` if possible. (If not, the operation "`wrap`s" and returns a different number entirely.) +- `%0xb6`: Convert an `f64` to `f32`. +- `%0xbb`: Convert an `f32` to `f64`. + +### `$pseudo-opcode` + +```hoon ++$ pseudo-opcode ?(%0x5 %0xb) :: else, end +``` + +??? + +### `$bin-opcodes-one-arg` + +```hoon ++$ bin-opcodes-one-arg + $? +:: br br_if call local.get local.set local.tee global.get global.set + %0xc %0xd %0x10 %0x20 %0x21 %0x22 %0x23 %0x24 +:: + const-opcodes + %0x3f :: memory.size + %0x40 :: memory.grow + == +``` + +??? + +### `$bin-opcodes-two-args` + +```hoon ++$ bin-opcodes-two-args + $? + %0xe :: br_table + %0x11 :: call_indirect + load-opcodes + store-opcodes + == +``` + +??? + +### `$bin-opcodes-blocks` + +```hoon ++$ bin-opcodes-blocks + $? + %0x2 :: block + %0x3 :: loop + %0x4 :: if + == +``` + +??? + +### `$const-opcodes` + +```hoon ++$ const-opcodes + $? + %0x41 :: i32 + %0x42 :: i64 + %0x43 :: f32 + %0x44 :: f64 + == +``` + +??? + +### `$load-opcodes` + +```hoon ++$ load-opcodes + $? + %0x28 :: i32 + %0x29 :: i64 + %0x2a :: f32 + %0x2b :: f64 + %0x2c :: i32 8 s + %0x2d :: i32 8 u + %0x2e :: i32 16 s + %0x2f :: i32 16 u + %0x30 :: i64 8 s + %0x31 :: i64 8 u + %0x32 :: i64 16 s + %0x33 :: i64 16 u + %0x34 :: i64 32 s + %0x35 :: i64 32 u + == +``` + +??? + +### `$store-opcodes` + +```hoon ++$ store-opcodes + $? + %0x36 :: i32 + %0x37 :: i64 + %0x38 :: f32 + %0x39 :: f64 + %0x3a :: i32 8 + %0x3b :: i32 16 + %0x3c :: i64 8 + %0x3d :: i64 16 + %0x3e :: i64 32 + == +``` + +??? + +### `$eqz-opcodes` + +```hoon ++$ eqz-opcodes ?(%0x45 %0x50) :: i32, i64 +``` + +??? + +### `$eq-opcodes` + +```hoon ++$ eq-opcodes ?(%0x46 %0x51 %0x5b %0x61) :: i32, i64, f32, f64 +``` + +??? + +### `$ne-opcodes` + +```hoon ++$ ne-opcodes ?(%0x47 %0x52 %0x5c %0x62) :: i32, i64, f32, f64 +``` + +??? + +### `$lt-opcodes` + +```hoon ++$ lt-opcodes + $? + %0x48 :: i32 s + %0x49 :: i32 u + %0x53 :: i64 s + %0x54 :: i64 u + %0x5d :: f32 + %0x63 :: f64 + == +``` + +??? + +### `$gt-opcodes` + +```hoon ++$ gt-opcodes + $? + %0x4a :: i32 s + %0x4b :: i32 u + %0x55 :: i64 s + %0x56 :: i64 u + %0x5e :: f32 + %0x64 :: f64 + == +``` + +??? + +### `$le-opcodes` + +```hoon ++$ le-opcodes + $? + %0x4c :: i32 s + %0x4d :: i32 u + %0x57 :: i64 s + %0x58 :: i64 u + %0x5f :: f32 + %0x65 :: f64 + == +``` + +??? + +### `$ge-opcodes` + +```hoon ++$ ge-opcodes + $? + %0x4e :: i32 s + %0x4f :: i32 u + %0x59 :: i64 s + %0x5a :: i64 u + %0x60 :: f32 + %0x66 :: f64 + == +``` + +??? + +### `$clz-opcodes` + +```hoon ++$ clz-opcodes ?(%0x67 %0x79) :: i32, i64 +``` + +??? + +### `$ctz-opcodes` + +```hoon ++$ ctz-opcodes ?(%0x68 %0x7a) :: i32, i64 +``` + +??? + +### `$popcnt-opcodes` + +```hoon ++$ popcnt-opcodes ?(%0x69 %0x7b) :: i32, i64 +``` + +??? + +### `$add-opcodes` + +```hoon ++$ add-opcodes ?(%0x6a %0x7c %0x92 %0xa0) :: i32, i64, f32, f64 +``` + +??? + +### `$sub-opcodes` + +```hoon ++$ sub-opcodes ?(%0x6b %0x7d %0x93 %0xa1) :: i32, i64, f32, f64 +``` + +??? + +### `$mul-opcodes` + +```hoon ++$ mul-opcodes ?(%0x6c %0x7e %0x94 %0xa2) :: i32, i64, f32, f64 +``` + +??? + +### `$div-opcodes` + +```hoon ++$ div-opcodes + $? + %0x6d :: i32 s + %0x6e :: i32 u + %0x7f :: i64 s + %0x80 :: i64 u + %0x95 :: f32 + %0xa3 :: f64 + == +``` + +??? + +### `$rem-opcodes` + +```hoon ++$ rem-opcodes + $? + %0x6f :: i32 s + %0x70 :: i32 u + %0x81 :: i64 s + %0x82 :: i64 u + == +``` + +??? + +### `$and-opcodes` + +```hoon ++$ and-opcodes ?(%0x71 %0x83) :: i32, i64 +``` + +??? + +### `$or-opcodes` + +```hoon ++$ or-opcodes ?(%0x72 %0x84) :: i32, i64 +``` + +??? + +### `$xor-opcodes` + +```hoon ++$ xor-opcodes ?(%0x73 %0x85) :: i32, i64 +``` + +??? + +### `$shl-opcodes` + +```hoon ++$ shl-opcodes ?(%0x74 %0x86) :: i32, i64 +``` + +??? + +### `$shr-opcodes` + +```hoon ++$ shr-opcodes + $? + %0x75 :: i32 s + %0x76 :: i32 u + %0x87 :: i64 s + %0x88 :: i64 u + == +``` + +??? + +### `$rotl-opcodes` + +```hoon ++$ rotl-opcodes ?(%0x77 %0x89) :: i32, i64 +``` + +??? + +### `$rotr-opcodes` + +```hoon ++$ rotr-opcodes ?(%0x78 %0x8a) :: i32, i64 +``` + +??? + +### `$abs-opcodes` + +```hoon ++$ abs-opcodes ?(%0x8b %0x99) :: f32, f64 +``` + +??? + +### `$neg-opcodes` + +```hoon ++$ neg-opcodes ?(%0x8c %0x9a) :: f32, f64 +``` + +??? + +### `$ceil-opcodes` + +```hoon ++$ ceil-opcodes ?(%0x8d %0x9b) :: f32, f64 +``` + +??? + +### `$floor-opcodes` + +```hoon ++$ floor-opcodes ?(%0x8e %0x9c) :: f32, f64 +``` + +??? + +### `$trunc-opcodes` + +```hoon ++$ trunc-opcodes + $? + %0x8f :: f32 + %0x9d :: f64 + %0xa8 :: f32 -> i32 s + %0xa9 :: f32 -> i32 u + %0xaa :: f64 -> i32 s + %0xab :: f64 -> i32 u + %0xae :: f32 -> i64 s + %0xaf :: f32 -> i64 u + %0xb0 :: f64 -> i64 s + %0xb1 :: f64 -> i64 u + == +``` + +??? + +### `$nearest-opcodes` + +```hoon ++$ nearest-opcodes ?(%0x90 %0x9e) :: f32, f64 +``` + +??? + +### `$sqrt-opcodes` + +```hoon ++$ sqrt-opcodes ?(%0x91 %0x9f) :: f32, f64 +``` + +??? + +### `$min-opcodes` + +```hoon ++$ min-opcodes ?(%0x96 %0xa4) :: f32, f64 +``` + +??? + +### `$max-opcodes` + +```hoon ++$ max-opcodes ?(%0x97 %0xa5) :: f32, f64 +``` + +??? + +### `$copysign-opcodes` + +```hoon ++$ copysign-opcodes ?(%0x98 %0xa6) :: f32, f64 +``` + +??? + +### `$extend-opcodes` + +```hoon ++$ extend-opcodes + $? + %0xac :: i32 -> i64 s + %0xad :: i32 -> i64 u + %0xc0 :: i8 -> i32 s + %0xc1 :: i16 -> i32 s + %0xc2 :: i8 -> i64 s + %0xc3 :: i16 -> i64 s + %0xc4 :: i32 -> i64 s ?? same as 0xac??? (yes) + == +``` + +??? + +### `$convert-opcodes` + +```hoon ++$ convert-opcodes + $? + %0xb2 :: i32 s -> f32 + %0xb3 :: i32 u -> f32 + %0xb4 :: i64 s -> f32 + %0xb5 :: i64 u -> f32 + %0xb7 :: i32 s -> f64 + %0xb8 :: i32 u -> f64 + %0xb9 :: i64 s -> f64 + %0xba :: i64 u -> f64 + == +``` + +??? + +### `$reinterpret-opcodes` + +```hoon ++$ reinterpret-opcodes + $? + %0xbc :: f32 -> i32 + %0xbd :: f64 -> i64 + %0xbe :: i32 -> f32 + %0xbf :: i64 -> f64 + == +``` + +??? + +## Wasm interpreter types -## /sur/wasm/engine/hoon Wasm interpreter types -## /sur/wasm/lia/hoon +## Lia types Lia [Language for Invocation of (web)Assembly] types + From 607175aea7f81f153e861bd3e985719e2200c843 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 11 Aug 2025 15:34:38 +0100 Subject: [PATCH 14/57] Add atoms --- .../build-on-urbit/wasm-walkthrough/reference/data-types.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md index df6cbb2a..9617ccff 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/data-types.md @@ -677,9 +677,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc - If there are more values on the stack than allowed by the function's return type, the first $$n$$ values are returned (where $$n$$ is the number of values allowed) and the rest are discarded. - `%0x1a`: `drop` a value from the stack. - `%0x1b`: Like a ternary operator, `select` one of the first two operands based on whether the third is `0` or not. -- `%0xa7`: Convert an `i64` to an `i32` if possible. (If not, the operation "`wrap`s" and returns a different number entirely.) -- `%0xb6`: Convert an `f64` to `f32`. -- `%0xbb`: Convert an `f32` to `f64`. +- `%0xa7`: Convert an `i64` / `@G` to an `i32` / `@F` if possible. (If not, the operation "`wrap`s" and returns a different number entirely.) +- `%0xb6`: Convert an `f64` / `@rd` to `f32` / `@rs`. +- `%0xbb`: Convert an `f32` / `@rs` to `f64` / `@rd`. ### `$pseudo-opcode` From 9a6cd8c4bf13f9ed6ec1a76d6520541cee123212 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 11 Aug 2025 15:38:42 +0100 Subject: [PATCH 15/57] Break up Wasm reference section --- .../wasm-walkthrough/reference/README.md | 16 ++++++++++++++-- .../reference/lia-data-types.md | 1 + .../{data-types.md => wasm-data-types.md} | 18 +----------------- .../reference/wasm-interpreter-data-types.md | 1 + 4 files changed, 17 insertions(+), 19 deletions(-) create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md rename content/build-on-urbit/wasm-walkthrough/reference/{data-types.md => wasm-data-types.md} (97%) create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm-walkthrough/reference/README.md index 25da38d7..c623181a 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/README.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/README.md @@ -1,6 +1,6 @@ # UrWasm Reference -UrWasm is structured as a series of nested cores: +The UrWasm project is structured as a series of nested cores, innermost to outermost: ``` /sur/wasm/wasm/hoon :: Wasm types definition @@ -13,4 +13,16 @@ UrWasm is structured as a series of nested cores: /lib/wasm/lia/hoon :: Lia interpreter ``` -This reference section documents the UrWasm project's data types and library functionality. +This reference section documents UrWasm's data types and library functionality. + +## Data types +- Wasm data types +- Wasm interpreter data types +- Lia data types + +## Libraries +- Wasm parser +- Wasm validator +- Wasm operator +- Wasm interpreter +- Lia interpreter diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md new file mode 100644 index 00000000..abb85df9 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md @@ -0,0 +1 @@ +# Lia Data Types diff --git a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md similarity index 97% rename from content/build-on-urbit/wasm-walkthrough/reference/data-types.md rename to content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 9617ccff..64852671 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -1,14 +1,5 @@ -# UrWasm Data Types +# Wasm Data Types -UrWasm's data types are defined in three nested `/sur` files in `%base`; innermost to outermost: - -``` -/sur/wasm/wasm/hoon :: Wasm types definition -/sur/wasm/engine/hoon :: Wasm interpreter types -/sur/wasm/lia/hoon :: Lia [Language for Invocation of (web)Assembly] types -``` - -## Wasm types UrWasm's inner core, `+wasm-sur`, contains the foundational Wasm types. @@ -1158,10 +1149,3 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -## Wasm interpreter types - -Wasm interpreter types - -## Lia types -Lia [Language for Invocation of (web)Assembly] types - diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md new file mode 100644 index 00000000..7215f7f8 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md @@ -0,0 +1 @@ +# Wasm Interpeter Data Types From 470b27599da7bb7144695b3e786d2f6541cc3ec7 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 11 Aug 2025 15:39:53 +0100 Subject: [PATCH 16/57] Add /sur links to Wasm reference --- content/build-on-urbit/wasm-walkthrough/reference/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm-walkthrough/reference/README.md index c623181a..28ef154f 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/README.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/README.md @@ -16,9 +16,9 @@ The UrWasm project is structured as a series of nested cores, innermost to outer This reference section documents UrWasm's data types and library functionality. ## Data types -- Wasm data types -- Wasm interpreter data types -- Lia data types +- [Wasm data types](./wasm-data-types.md) +- [Wasm interpreter data types](./wasm-interpreter-data-types.md) +- [Lia data types](./lia-data-types.md) ## Libraries - Wasm parser From f05e2f502130fbe6d7c763e5adf9b835466ee0df Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Tue, 12 Aug 2025 10:44:12 +0100 Subject: [PATCH 17/57] Amend /sur/wasm --- .../wasm-walkthrough/reference/wasm-data-types.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 64852671..6b2dd7b5 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -3,7 +3,9 @@ UrWasm's inner core, `+wasm-sur`, contains the foundational Wasm types. -The first part implements the Structure chapter of the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/index.html). The second part implements Wasm's binary-format opcodes. +The first part implements the [Structure chapter](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/index.html) of the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/index.html). + +The second part implements Wasm's binary-format opcodes. ### `$octs` (pair @ud @) From ca2036b72f6f01f8ce7b3a02d78576b29216b9e0 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Tue, 12 Aug 2025 14:46:49 +0100 Subject: [PATCH 18/57] Moar draft Wasm data types --- .../reference/wasm-data-types.md | 269 ++++++++++-------- 1 file changed, 151 insertions(+), 118 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 6b2dd7b5..f6d0fc46 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -15,11 +15,11 @@ The second part implements Wasm's binary-format opcodes. Pair of byte-length and octet stream data. -### `+wasm-sur` +### `+wasm-sur` {#wasm-sur} Wrapper arm around the Wasm types. This just makes the types addressable by limb resolution paths like `num-type:wasm-sur`. -### `$num-type` +### `$num-type` {#num-type} ```hoon +$ num-type ?(%i32 %i64 %f32 %f64) @@ -31,23 +31,23 @@ Type annotation for the four types of number Wasm calls can return: - 32-bit floating point numbers (`@rs`). - 64-bit floating point numbers (`@rd`). -### `$vec-type` +### `$vec-type` {#vec-type} ```hoon +$ vec-type %v128 ``` -Type annotation for a 128-bit vector (`@H`). +Type annotation for a 128-bit (`@H`) register. -### `$ref-type` +### `$ref-type` {#ref-type} ```hoon +$ ref-type ?(%extn %func) :: externref and funcref ``` -Type annotation for ??? +Type annotation for references in the Wasm state, be those functions or data. -### `$valtype` +### `$valtype` {#valtype} ```hoon +$ valtype @@ -58,9 +58,9 @@ Type annotation for ??? == ``` -Type annotation for ??? +Type annotation for all the types that Wasm can accept: numbers, vectors, and references. -### `$coin-wasm` +### `$coin-wasm` {#coin-wasm} ```hoon +$ coin-wasm @@ -81,9 +81,11 @@ Type annotation for ??? == ``` -Type-annotated Wasm value. +Type-annotated Wasm value. A `$coin-wasm` is UrWasm's version of Wasm's [result types](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/types.html#result-types), which look something like Hoon's [`$coin`](https://docs.urbit.org/hoon/stdlib/3g#coin) nouns. -### `$limits` +These are the [`$valtype`](#valtype) type annotation terms with extra specification for atom size and object references. + +### `$limits` {#limits} ```hoon +$ limits @@ -92,9 +94,9 @@ Type-annotated Wasm value. == ``` -??? +Limits the range of available storage for [`$memarg`](#memarg)s and [`$table`](#table)s. -### `$memarg` +### `$memarg` {#memarg} ```hoon +$ memarg @@ -102,9 +104,9 @@ Type-annotated Wasm value. [align=@ offset=@] ``` -??? +Defines the minimum and maximum size of a memory instance. The `.align` and `.offset` values represent units of Wasm's page size, which is 128 bits (so, a `@H`). -### `$block-type` +### `$block-type` {#block-type} ```hoon +$ block-type $@(@ func-type) :: typeidx in type section or func-type @@ -112,7 +114,7 @@ Type-annotated Wasm value. ??? -### `$func-type` +### `$func-type` {#func-type} ```hoon +$ func-type @@ -121,17 +123,17 @@ Type-annotated Wasm value. == ``` -??? +Function signature. -### `$lane-type` +### `$lane-type` {#lane-type} ```hoon +$ lane-type ?(%i8 %i16 num-type) ``` -??? +Type annotation for lanes (memory elements) in a 128-bit (`@H`) register. Includes the usual [`$num-type`s](#num-type) and additional `%i8` and `%i16` types for smaller lanes. -### `$instruction` +### `$instruction` {#instruction} ```hoon +$ instruction @@ -140,7 +142,7 @@ Type-annotated Wasm value. ??? -### `$instr-dbug` +### `$instr-dbug` {#instr-dbug} ```hoon +$ instr-dbug @@ -151,7 +153,7 @@ Type-annotated Wasm value. ??? -### `$instr-num` +### `$instr-num` {#instr-num} ```hoon +$ instr-num ?(instr-num-zero instr-num-one instr-num-two) @@ -159,7 +161,7 @@ Type-annotated Wasm value. ??? -### `$instr-num-zero` +### `$instr-num-zero` {#instr-num-zero} ```hoon +$ instr-num-zero @@ -168,9 +170,9 @@ Type-annotated Wasm value. == ``` -??? +Any [`$coin-wasm`](#coin-wasm) that represents a constant value. -### `$instr-num-one` +### `$instr-num-one` {#instr-num-one} ```hoon +$ instr-num-one @@ -211,7 +213,7 @@ Type-annotated Wasm value. ??? -### `$instr-num-two` +### `$instr-num-two` {#instr-num-two} ```hoon +$ instr-num-two @@ -242,7 +244,7 @@ Type-annotated Wasm value. ??? -### `$instr-short` +### `$instr-short` {#instr-short} ```hoon +$ instr-short @@ -317,7 +319,7 @@ Type-annotated Wasm value. ??? -### `$instr-vec` +### `$instr-vec` {#instr-vec} ```hoon +$ instr-vec @@ -393,15 +395,15 @@ Type-annotated Wasm value. ??? -### `$expression` +### `$expression` {#expression} ```hoon +$ expression (list instruction) ``` -List of `$instruction`s. +An ordered sequence of [`$instruction`](#instruction)s. -### `$const-instr` +### `$const-instr` {#const-instr} ```hoon +$ const-instr @@ -411,9 +413,9 @@ List of `$instruction`s. == ``` -??? +Constant instruction. ??? -### `$module` +### `$module` {#module} ```hoon +$ module @@ -433,9 +435,9 @@ List of `$instruction`s. == ``` -A Wasm module, represented in a format closer to its binary representation (i.e. separate code and function sections) to simplify parsing. +A Wasm module, represented in a format closer to its binary representation to simplify parsing. -### `$type-section` +### `$type-section` {#type-section} ```hoon +$ type-section @@ -443,9 +445,9 @@ A Wasm module, represented in a format closer to its binary representation (i.e. (list func-type) ``` -??? +List of function signatures in the module. -### `$import-section` +### `$import-section` {#import-section} ```hoon +$ import-section @@ -453,16 +455,29 @@ A Wasm module, represented in a format closer to its binary representation (i.e. (list import) ``` -??? +List of [`$import`s](#import) this module requires from other modules. -### `$import` +### `$import` {#import} ```hoon ++$ import + $: mod=cord + name=cord + $= desc + $% + [%func type-id=@] + [%tabl t=table] + [%memo l=limits] + [%glob v=valtype m=?(%con %var)] :: constant or variable + == == ``` -??? +Import from another Wasm module, including: +- `.mod`: Module name. +- `.name`: Name for the entity in the module we'd like to import. +- `.desc`: Importable definitions within the module, including functions, tables, global variables, etc. -### `$function-section` +### `$function-section` {#function-section} ```hoon +$ function-section @@ -470,41 +485,41 @@ A Wasm module, represented in a format closer to its binary representation (i.e. (list type-id=@) ``` -??? +List of functions in this module, referenced by index. -### `$table-section` +### `$table-section` {#table-section} ```hoon +$ table-section (list table) ``` -??? +List of [`$table`s](#table) in the module. -### `$table` +### `$table` {#table} ```hoon +$ table (pair ref-type limits) ``` -??? +Wasm table, referenced by its [`$ref-type`](#ref-type) and describing the [`$limits`](#limits) of its size. -### `$memory-section` +### `$memory-section` {#memory-section} ```hoon +$ memory-section (list limits) ``` -??? +List of the module's memory arrays, defined by the [`$limits`](#limits) of their size. -### `$global-section` +### `$global-section` {#global-section} ```hoon +$ global-section (list global) ``` -??? +List of the module's [`$global`](#global) variables. -### `$global` +### `$global` {#global} ```hoon +$ global @@ -514,12 +529,12 @@ A Wasm module, represented in a format closer to its binary representation (i.e. == ``` - :: valtype, mutability and init value. - :: We use a single constant instruction as opposed to a - :: (list instruction) since there is no global value type - :: that would take multiple constant values +Global variable, including: +- `.val`: [`$valtype`](#valtype), type of the variable's value. +- `.m`: Constant or variable. +- `.i`: Initial value. (Note that this is a constant instruction and not a `(list instruction)` as Wasm has no global value type that would take multiple constant values.) -### `$export-section` +### `$export-section` {#export-section} ```hoon +$ export-section @@ -527,17 +542,19 @@ A Wasm module, represented in a format closer to its binary representation (i.e. (list export) ``` -??? +List of [`$export`s](#export) in the module. -### `$export` +### `$export` {#export} ```hoon +$ export [name=cord =export-desc] ``` -??? +Element to be exportable for use in other modules: +- `.name`: Name of the export. +- `.export-desk`: [`$export-desc`](#export-desc), type-annotated value of the export. -### `$export-desc` +### `$export-desc` {#export-desc} ```hoon +$ export-desc @@ -548,25 +565,31 @@ A Wasm module, represented in a format closer to its binary representation (i.e. == ``` -??? +Type-annotated value of an export addressed by its index: +- `%func`: Function. +- `%tabl`: Table. +- `%memo`: Memory. +- `%glob`: Global variable. + +In practice these indexes will always be 32-bit integers (`@F`s). -### `$start-section` +### `$start-section` {#start-section} ```hoon +$ start-section (unit @) ``` -??? +The initialization (or "start") function for the module, if one exists. -### `$elem-section` +### `$elem-section` {#elem-section} ```hoon +$ elem-section (list elem) ``` -??? +List of [`$elem`s](#elem). -### `$elem` +### `$elem` {#elem} ```hoon +$ elem @@ -580,9 +603,17 @@ A Wasm module, represented in a format closer to its binary representation (i.e. == == ``` -??? +Wasm element segment: +- `.t`: Reference type. (Currently Wasm only supports function references (`%func` [`$ref-type`s](#ref-type)).) +- `.i`: Sequence of [`$instruction`s](#instruction) to produce function references. +- `.m`: Element segment mode: + - `%pass`: Passive, elements copied manually via table initialization. + - `%decl`: Declarative, declares references which aren't copied to tables. + - `%acti`: Active, automatically copies element data to the table `.tab` at offset `.off` when the module is instantiated. -### `$code-section` +Element segments store static data with which to populate [`$table`s](#table) when the module is initialized. + +### `$code-section` {#code-section} ```hoon +$ code-section @@ -592,7 +623,7 @@ A Wasm module, represented in a format closer to its binary representation (i.e. ??? -### `$code` +### `$code` {#code} ```hoon +$ code @@ -603,15 +634,15 @@ A Wasm module, represented in a format closer to its binary representation (i.e. ??? -### `$data-section` +### `$data-section` {#data-section} ```hoon +$ data-section (list data) ``` -??? +List of the module's [`$data`](#data) segments. -### `$data` +### `$data` {#data} ```hoon +$ data @@ -621,9 +652,11 @@ A Wasm module, represented in a format closer to its binary representation (i.e. == ``` -??? +Data segment for initializing the module's state. +- `%acti`: Active segments automatically copy `$octs` `.b` to the module's memory at offset `.off` during instantiation. +- `%pass`: Passive segments are copied manually when instructed. -### `+datacnt-section` +### `+datacnt-section` {#datacnt-section} ```hoon ++ datacnt-section (unit @) @@ -631,7 +664,7 @@ A Wasm module, represented in a format closer to its binary representation (i.e. ??? -### `$opcode` +### `$opcode` {#opcode} ```hoon +$ opcode $? bin-opcodes-zero-args @@ -644,7 +677,7 @@ A Wasm module, represented in a format closer to its binary representation (i.e. ??? -### `$bin-opcodes-zero-args` +### `$bin-opcodes-zero-args` {#bin-opcodes-zero-args} ```hoon +$ bin-opcodes-zero-args @@ -674,7 +707,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc - `%0xb6`: Convert an `f64` / `@rd` to `f32` / `@rs`. - `%0xbb`: Convert an `f32` / `@rs` to `f64` / `@rd`. -### `$pseudo-opcode` +### `$pseudo-opcode` {#pseudo-opcode} ```hoon +$ pseudo-opcode ?(%0x5 %0xb) :: else, end @@ -682,7 +715,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$bin-opcodes-one-arg` +### `$bin-opcodes-one-arg` {#bin-opcodes-one-arg} ```hoon +$ bin-opcodes-one-arg @@ -698,7 +731,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$bin-opcodes-two-args` +### `$bin-opcodes-two-args` {#bin-opcodes-two-args} ```hoon +$ bin-opcodes-two-args @@ -712,7 +745,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$bin-opcodes-blocks` +### `$bin-opcodes-blocks` {#bin-opcodes-blocks} ```hoon +$ bin-opcodes-blocks @@ -725,7 +758,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$const-opcodes` +### `$const-opcodes` {#const-opcodes} ```hoon +$ const-opcodes @@ -739,7 +772,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$load-opcodes` +### `$load-opcodes` {#load-opcodes} ```hoon +$ load-opcodes @@ -763,7 +796,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$store-opcodes` +### `$store-opcodes` {#store-opcodes} ```hoon +$ store-opcodes @@ -782,7 +815,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$eqz-opcodes` +### `$eqz-opcodes` {#eqz-opcodes} ```hoon +$ eqz-opcodes ?(%0x45 %0x50) :: i32, i64 @@ -790,7 +823,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$eq-opcodes` +### `$eq-opcodes` {#eq-opcodes} ```hoon +$ eq-opcodes ?(%0x46 %0x51 %0x5b %0x61) :: i32, i64, f32, f64 @@ -798,7 +831,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$ne-opcodes` +### `$ne-opcodes` {#ne-opcodes} ```hoon +$ ne-opcodes ?(%0x47 %0x52 %0x5c %0x62) :: i32, i64, f32, f64 @@ -806,7 +839,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$lt-opcodes` +### `$lt-opcodes` {#lt-opcodes} ```hoon +$ lt-opcodes @@ -822,7 +855,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$gt-opcodes` +### `$gt-opcodes` {#gt-opcodes} ```hoon +$ gt-opcodes @@ -838,7 +871,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$le-opcodes` +### `$le-opcodes` {#le-opcodes} ```hoon +$ le-opcodes @@ -854,7 +887,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$ge-opcodes` +### `$ge-opcodes` {#ge-opcodes} ```hoon +$ ge-opcodes @@ -870,7 +903,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$clz-opcodes` +### `$clz-opcodes` {#clz-opcodes} ```hoon +$ clz-opcodes ?(%0x67 %0x79) :: i32, i64 @@ -878,7 +911,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$ctz-opcodes` +### `$ctz-opcodes` {#ctz-opcodes} ```hoon +$ ctz-opcodes ?(%0x68 %0x7a) :: i32, i64 @@ -886,7 +919,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$popcnt-opcodes` +### `$popcnt-opcodes` {#popcnt-opcodes} ```hoon +$ popcnt-opcodes ?(%0x69 %0x7b) :: i32, i64 @@ -894,7 +927,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$add-opcodes` +### `$add-opcodes` {#add-opcodes} ```hoon +$ add-opcodes ?(%0x6a %0x7c %0x92 %0xa0) :: i32, i64, f32, f64 @@ -902,7 +935,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$sub-opcodes` +### `$sub-opcodes` {#sub-opcodes} ```hoon +$ sub-opcodes ?(%0x6b %0x7d %0x93 %0xa1) :: i32, i64, f32, f64 @@ -910,7 +943,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$mul-opcodes` +### `$mul-opcodes` {#mul-opcodes} ```hoon +$ mul-opcodes ?(%0x6c %0x7e %0x94 %0xa2) :: i32, i64, f32, f64 @@ -918,7 +951,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$div-opcodes` +### `$div-opcodes` {#div-opcodes} ```hoon +$ div-opcodes @@ -934,7 +967,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$rem-opcodes` +### `$rem-opcodes` {#rem-opcodes} ```hoon +$ rem-opcodes @@ -948,7 +981,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$and-opcodes` +### `$and-opcodes` {#and-opcodes} ```hoon +$ and-opcodes ?(%0x71 %0x83) :: i32, i64 @@ -956,7 +989,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$or-opcodes` +### `$or-opcodes` {#or-opcodes} ```hoon +$ or-opcodes ?(%0x72 %0x84) :: i32, i64 @@ -964,7 +997,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$xor-opcodes` +### `$xor-opcodes` {#xor-opcodes} ```hoon +$ xor-opcodes ?(%0x73 %0x85) :: i32, i64 @@ -972,7 +1005,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$shl-opcodes` +### `$shl-opcodes` {#shl-opcodes} ```hoon +$ shl-opcodes ?(%0x74 %0x86) :: i32, i64 @@ -980,7 +1013,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$shr-opcodes` +### `$shr-opcodes` {#shr-opcodes} ```hoon +$ shr-opcodes @@ -994,7 +1027,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$rotl-opcodes` +### `$rotl-opcodes` {#rotl-opcodes} ```hoon +$ rotl-opcodes ?(%0x77 %0x89) :: i32, i64 @@ -1002,7 +1035,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$rotr-opcodes` +### `$rotr-opcodes` {#rotr-opcodes} ```hoon +$ rotr-opcodes ?(%0x78 %0x8a) :: i32, i64 @@ -1010,7 +1043,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$abs-opcodes` +### `$abs-opcodes` {#abs-opcodes} ```hoon +$ abs-opcodes ?(%0x8b %0x99) :: f32, f64 @@ -1018,7 +1051,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$neg-opcodes` +### `$neg-opcodes` {#neg-opcodes} ```hoon +$ neg-opcodes ?(%0x8c %0x9a) :: f32, f64 @@ -1026,7 +1059,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$ceil-opcodes` +### `$ceil-opcodes` {#ceil-opcodes} ```hoon +$ ceil-opcodes ?(%0x8d %0x9b) :: f32, f64 @@ -1034,7 +1067,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$floor-opcodes` +### `$floor-opcodes` {#floor-opcodes} ```hoon +$ floor-opcodes ?(%0x8e %0x9c) :: f32, f64 @@ -1042,7 +1075,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$trunc-opcodes` +### `$trunc-opcodes` {#trunc-opcodes} ```hoon +$ trunc-opcodes @@ -1062,7 +1095,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$nearest-opcodes` +### `$nearest-opcodes` {#nearest-opcodes} ```hoon +$ nearest-opcodes ?(%0x90 %0x9e) :: f32, f64 @@ -1070,7 +1103,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$sqrt-opcodes` +### `$sqrt-opcodes` {#sqrt-opcodes} ```hoon +$ sqrt-opcodes ?(%0x91 %0x9f) :: f32, f64 @@ -1078,7 +1111,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$min-opcodes` +### `$min-opcodes` {#min-opcodes} ```hoon +$ min-opcodes ?(%0x96 %0xa4) :: f32, f64 @@ -1086,7 +1119,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$max-opcodes` +### `$max-opcodes` {#max-opcodes} ```hoon +$ max-opcodes ?(%0x97 %0xa5) :: f32, f64 @@ -1094,7 +1127,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$copysign-opcodes` +### `$copysign-opcodes` {#copysign-opcodes} ```hoon +$ copysign-opcodes ?(%0x98 %0xa6) :: f32, f64 @@ -1102,7 +1135,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$extend-opcodes` +### `$extend-opcodes` {#extend-opcodes} ```hoon +$ extend-opcodes @@ -1119,7 +1152,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$convert-opcodes` +### `$convert-opcodes` {#convert-opcodes} ```hoon +$ convert-opcodes @@ -1137,7 +1170,7 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc ??? -### `$reinterpret-opcodes` +### `$reinterpret-opcodes` {#reinterpret-opcodes} ```hoon +$ reinterpret-opcodes From 5c87a41e11a0f5c6afda725e036b92db3df6a28f Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Tue, 12 Aug 2025 15:02:51 +0100 Subject: [PATCH 19/57] Code wasm docs --- .../wasm-walkthrough/reference/wasm-data-types.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index f6d0fc46..cead409a 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -621,7 +621,7 @@ Element segments store static data with which to populate [`$table`s](#table) wh (list code) ``` -??? +List of [`$code`](#code) entries. ### `$code` {#code} @@ -632,7 +632,9 @@ Element segments store static data with which to populate [`$table`s](#table) wh == ``` -??? +Function implementation stored in binary format: +- `.locals`: List of local variables in this function. +- `.expression`: The function body as a sequence of instructions. (See [`$expression`](#expression).) ### `$data-section` {#data-section} From 0bc20c7eb39ccf8a6ab154135f06988bcd807d94 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Tue, 12 Aug 2025 15:06:39 +0100 Subject: [PATCH 20/57] Note on separate sections --- .../wasm-walkthrough/reference/wasm-data-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index cead409a..404a6a89 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -435,7 +435,7 @@ Constant instruction. ??? == ``` -A Wasm module, represented in a format closer to its binary representation to simplify parsing. +A Wasm module. Note code and function sections have been separated here to simplify parsing. ### `$type-section` {#type-section} From b60ee4fa94cf8357ff4a85c3989bc9ad3542b443 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Tue, 12 Aug 2025 16:28:50 +0100 Subject: [PATCH 21/57] Draft instruction docs --- .../reference/wasm-data-types.md | 158 +++++++++++++++++- 1 file changed, 150 insertions(+), 8 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 404a6a89..47a8585f 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -140,7 +140,13 @@ Type annotation for lanes (memory elements) in a 128-bit (`@H`) register. Includ $%([%vec instr-vec] instr-short instr-num instr-dbug) ``` -??? +Type union of all Wasm instructions. + +Instructions are categorized here by their operand patterns: +- `%vec`: Vector instructions. (See [`$instr-vec`]($instr-vec).) +- [`$instr-short`](#instr-short): ??? +- [`$instr-num`](#instr-num): Standard Wasm instructions categorized by arity. +- [`$instr-dbug`](#instr-dbug): Debugging. ### `$instr-dbug` {#instr-dbug} @@ -151,7 +157,7 @@ Type annotation for lanes (memory elements) in a 128-bit (`@H`) register. Includ == ``` -??? +Debugging instructions. The only one supported here is `%print-tee`, which prints a value {TODO ???} with the given `$term` as a label. ### `$instr-num` {#instr-num} @@ -159,7 +165,7 @@ Type annotation for lanes (memory elements) in a 128-bit (`@H`) register. Includ +$ instr-num ?(instr-num-zero instr-num-one instr-num-two) ``` -??? +Type union of all standard Wasm instructions, categorized here by arity. ### `$instr-num-zero` {#instr-num-zero} @@ -170,7 +176,15 @@ Type annotation for lanes (memory elements) in a 128-bit (`@H`) register. Includ == ``` -Any [`$coin-wasm`](#coin-wasm) that represents a constant value. +Wasm `const` instruction, whose value is any [`$coin-wasm`](#coin-wasm) that may represent a constant value. So... + +```hoon +$? [%i32 @F] + [%i64 @G] + [%f32 @rs] + [%f64 @rd] +== +``` ### `$instr-num-one` {#instr-num-one} @@ -211,7 +225,24 @@ Any [`$coin-wasm`](#coin-wasm) that represents a constant value. == ``` -??? +Standard Wasm instructions with one parameter each: +- `eqz`: Check if equals zero. +- `clz`: Count leading zeroes. +- `ctz`: Count trailing zeroes. +- `popcnt`: Population count (number of set bits). +- `abs`: Absolute value. +- `neg`: Negate. +- `ceil`: Round a float up to nearest integer. +- `floor`: Round a float down to nearest integer. +- `nearest`: Round a float to nearest integer. +- `sqrt`: Square root. +- `trunc`: Truncate float to integer (with optional saturation). +- `wrap`: Wrap larger integer to smaller type. +- `extend`: Extend smaller integer to larger type. +- `convert`: Convert between integer and float. +- `demote`: Convert `f64` (`@rd`) to `f32` `(@rs`). +- `promote`: Convert `f32` (`@rs`) to `f64` (`@rd`). +- `reinterpret`: Reinterpret bit pattern as different type. ### `$instr-num-two` {#instr-num-two} @@ -242,7 +273,28 @@ Any [`$coin-wasm`](#coin-wasm) that represents a constant value. == ``` -??? +Wasm's binary numeric instructions: +- `eq`: Test equality. +- `ne`: Test inequality. +- `lt`: Less than. +- `gt`: Greater than. +- `le`: Less than or equal. +- `ge`: Greater than or equal. +- `add`: Addition. +- `sub`: Subtraction. +- `mul`: Multiplication. +- `div`: Division. +- `rem`: Remainder. +- `and`: Bitwise AND. +- `or`: Bitwise OR. +- `xor`: Bitwise XOR. +- `shl`: Shift left. +- `shr`: Shift right (logical or arithmetic). +- `rotl`: Rotate left. +- `rotr`: Rotate right. +- `min`: Minimum value. +- `max`: Maximum value. +- `copysign`: Copy sign bit from second operand to first. ### `$instr-short` {#instr-short} @@ -317,7 +369,44 @@ Any [`$coin-wasm`](#coin-wasm) that represents a constant value. == :: $instr-short ``` -??? +Non-numeric Wasm instructions: +- `unreachable`: Trap execution unconditionally. +- `nop`: No operation. +- `block`: Start a block with optional result type. +- `loop`: Start a loop with optional result type. +- `if`: Conditional execution with true/false branches. +- `br`: Unconditional branch to label. +- `br-if`: Conditional branch to label. +- `br-table`: Multi-way branch (switch statement). +- `return`: Return from current function. +- `call`: Call function by index. +- `call-indirect`: Call function indirectly through table. +- `ref-null`: Create null reference. +- `ref-is-null`: Test if reference is null. +- `ref-func`: Get function reference. +- `drop`: Remove top stack value. +- `select`: Choose between two values based on condition. +- `local-get`: Get local variable value. +- `local-set`: Set local variable value. +- `local-tee`: Set local variable and return the value. +- `global-get`: Get global variable value. +- `global-set`: Set global variable value. +- `table-get`: Get element from table. +- `table-set`: Set element in table. +- `table-init`: Initialize table from element segment. +- `table-copy`: Copy elements between tables. +- `table-grow`: Grow table size. +- `table-size`: Get table size. +- `table-fill`: Fill table range with value. +- `elem-drop`: Drop element segment. +- `load`: Load value from memory. +- `store`: Store value to memory. +- `memory-size`: Get memory size in pages. +- `memory-grow`: Grow memory size. +- `memory-init`: Initialize memory from data segment. +- `data-drop`: Drop data segment. +- `memory-copy`: Copy memory regions. +- `memory-fill`: Fill memory range with byte value. ### `$instr-vec` {#instr-vec} @@ -393,7 +482,60 @@ Any [`$coin-wasm`](#coin-wasm) that represents a constant value. == :: $instr-vec ``` -??? +Wasm SIMD vector instructions for 128-bit vectors: +- `load`: Load vector from memory (with optional splat/zero-extend/sign-extend). +- `load-lane`: Load single value into specific lane. +- `store`: Store vector to memory. +- `store-lane`: Store single lane to memory. +- `const`: Vector constant. +- `shuffle`: Rearrange lanes by index list. +- `extract`: Get value from specific lane. +- `replace`: Set value in specific lane. +- `swizzle`: Rearrange lanes using second vector as indices. +- `splat`: Broadcast scalar to all lanes. +- `eq`: Lane-wise equality comparison. +- `ne`: Lane-wise inequality comparison. +- `lt`: Lane-wise less than comparison. +- `gt`: Lane-wise greater than comparison. +- `le`: Lane-wise less than or equal comparison. +- `ge`: Lane-wise greater than or equal comparison. +- `not`: Bitwise NOT on entire vector. +- `and`: Bitwise AND on entire vector. +- `andnot`: Bitwise AND-NOT on entire vector. +- `or`: Bitwise OR on entire vector. +- `xor`: Bitwise XOR on entire vector. +- `bitselect`: Select bits based on mask. +- `any-true`: Test if any lanes are true. +- `all-true`: Test if all lanes are true. +- `bitmask`: Extract high bit from each lane. +- `abs`: Lane-wise absolute value. +- `neg`: Lane-wise negation. +- `popcnt`: Population count on each lane. +- `narrow`: Pack two vectors into one with narrower lanes. +- `shl`: Lane-wise left bit shift. +- `shr`: Lane-wise right bit shift. +- `add`: Lane-wise addition (with optional saturation). +- `sub`: Lane-wise subtraction (with optional saturation). +- `min`: Lane-wise minimum. +- `max`: Lane-wise maximum. +- `avgr`: Averaging with rounding. +- `mul`: Lane-wise multiplication. +- `extend`: Extend lane width. +- `extmul`: Extended multiplication. +- `extadd`: Extended addition. +- `q15mul-r-sat`: Q15 fixed-point multiplication. +- `dot`: Dot product. +- `ceil`: Lane-wise ceiling (round up). +- `floor`: Lane-wise floor (round down). +- `nearest`: Lane-wise round to nearest. +- `sqrt`: Lane-wise square root. +- `div`: Lane-wise division. +- `trunc`: Lane-wise truncate to integer. +- `convert`: Lane-wise type conversion. +- `demote`: Lane-wise f64 to f32 conversion. +- `promote`: Lane-wise f32 to f64 conversion. +- `pmin`: Propagating minimum (NaN handling). +- `pmax`: Propagating maximum (NaN handling). ### `$expression` {#expression} From 15db8bdfbd6b010cac578a731bb3b63499c71d1f Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Wed, 13 Aug 2025 14:12:35 +0100 Subject: [PATCH 22/57] Draft binary opcodes docs --- .claude/settings.local.json | 11 + .../reference/wasm-data-types.md | 294 ++++++++++++++---- 2 files changed, 246 insertions(+), 59 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..009b64a9 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "WebSearch", + "WebFetch(domain:webassembly.github.io)", + "WebFetch(domain:pengowray.github.io)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 47a8585f..982a67c6 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -112,7 +112,7 @@ Defines the minimum and maximum size of a memory instance. The `.align` and `.of +$ block-type $@(@ func-type) :: typeidx in type section or func-type ``` -??? +Block type for {structured control instructions ???}. Can be a type index in the [`$type-section`](#type-section) or a [`$func-type`](#func-type) function signature. ### `$func-type` {#func-type} @@ -369,7 +369,7 @@ Wasm's binary numeric instructions: == :: $instr-short ``` -Non-numeric Wasm instructions: +???: - `unreachable`: Trap execution unconditionally. - `nop`: No operation. - `block`: Start a block with optional result type. @@ -532,8 +532,8 @@ Wasm SIMD vector instructions for 128-bit vectors: - `div`: Lane-wise division. - `trunc`: Lane-wise truncate to integer. - `convert`: Lane-wise type conversion. -- `demote`: Lane-wise f64 to f32 conversion. -- `promote`: Lane-wise f32 to f64 conversion. +- `demote`: Lane-wise `f64` to `f32` conversion. +- `promote`: Lane-wise `f32` to `f64` conversion. - `pmin`: Propagating minimum (NaN handling). - `pmax`: Propagating maximum (NaN handling). @@ -555,7 +555,7 @@ An ordered sequence of [`$instruction`](#instruction)s. == ``` -Constant instruction. ??? +{??? - some kind of const but not sure how relates to `$instr-num-zero`} ### `$module` {#module} @@ -577,7 +577,7 @@ Constant instruction. ??? == ``` -A Wasm module. Note code and function sections have been separated here to simplify parsing. +A Wasm module. Note code and function sections are separated here to simplify parsing. ### `$type-section` {#type-section} @@ -806,7 +806,9 @@ Data segment for initializing the module's state. ++ datacnt-section (unit @) ``` -??? +{TODO check the below} + +Data count section of the Wasm module, which may optionally contain the number of data segments ([`$data`](#data)) in the module. This allows validators to check the index validity of the data section before trying to access it. ### `$opcode` {#opcode} @@ -819,7 +821,7 @@ Data segment for initializing the module's state. == ``` -??? +Type union of all Wasm's binary instruction opcodes. ### `$bin-opcodes-zero-args` {#bin-opcodes-zero-args} @@ -839,17 +841,19 @@ Data segment for initializing the module's state. == ``` -WebAssembly opcodes. Most of these are defined in the types below, with some exceptions defined here: -- `%0x0`: ??? error? -- `%0x01`: `nop`, no-op, do nothing. -- `%0x0f`: `return` the result of a function, with two wrinkles: +Wasm binary instruction opcodes that take no immediate arguments. + +A few simple opcodes are defined here: +- `%0x0`: `unreachable` - causes an unconditional trap when executed. +- `%0x1`: `nop` - no-op, do nothing. +- `%0xf`: `return` - return from current function with values from stack. - If there's nothing in the stack to return, this returns nothing. - If there are more values on the stack than allowed by the function's return type, the first $$n$$ values are returned (where $$n$$ is the number of values allowed) and the rest are discarded. -- `%0x1a`: `drop` a value from the stack. -- `%0x1b`: Like a ternary operator, `select` one of the first two operands based on whether the third is `0` or not. -- `%0xa7`: Convert an `i64` / `@G` to an `i32` / `@F` if possible. (If not, the operation "`wrap`s" and returns a different number entirely.) -- `%0xb6`: Convert an `f64` / `@rd` to `f32` / `@rs`. -- `%0xbb`: Convert an `f32` / `@rs` to `f64` / `@rd`. +- `%0x1a`: `drop` - remove top value from stack. +- `%0x1b`: `select` - choose between two values based on condition. +- `%0xa7`: `i64.wrap_i32` - convert `i64` to `i32` by wrapping (truncating high bits). +- `%0xb6`: `f32.demote_f64` - convert `f64` to `f32`. +- `%0xbb`: `f64.promote_f32` - convert `f32` to `f64`. ### `$pseudo-opcode` {#pseudo-opcode} @@ -857,7 +861,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ pseudo-opcode ?(%0x5 %0xb) :: else, end ``` -??? +Pseudo-opcodes for control flow constructs: +- `%0x5`: `else` - marks the else branch of an if block. +- `%0xb`: `end` - terminates blocks, loops, if-statements, and functions. ### `$bin-opcodes-one-arg` {#bin-opcodes-one-arg} @@ -873,7 +879,18 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Instructions taking one immediate argument: +- `%0xc`: `br` - unconditional branch to label. +- `%0xd`: `br_if` - conditional branch to label. +- `%0x10`: `call` - invoke function by index. +- `%0x20`: `local.get` - read local variable. +- `%0x21`: `local.set` - write local variable. +- `%0x22`: `local.tee` - write local variable and return value. +- `%0x23`: `global.get` - read global variable. +- `%0x24`: `global.set` - write global variable. +- `%0x3f`: `memory.size` - query memory size. +- `%0x40`: `memory.grow` - grow memory by given delta. +- [`$const-opcodes`](#const-opcodes): constants for `i32`, `i64`, `f32`, `f64`. ### `$bin-opcodes-two-args` {#bin-opcodes-two-args} @@ -887,7 +904,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Instructions taking two immediate arguments: +- `%0xe`: `br_table` - branch table for switch-like control flow. +- `%0x11`: `call_indirect` - invoke function indirectly through table. +- [`$load-opcodes`](#load-opcodes): memory load operations with alignment and offset. +- [`$store-opcodes`](#store-opcodes): memory store operations with alignment and offset. ### `$bin-opcodes-blocks` {#bin-opcodes-blocks} @@ -900,7 +921,10 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Structured control flow instructions that create blocks with labels: +- `%0x2`: `block` - creates a block construct that can be targeted by branch instructions. +- `%0x3`: `loop` - creates a loop construct where branches target the beginning of the block. +- `%0x4`: `if` - creates a conditional block that executes based on a condition value. ### `$const-opcodes` {#const-opcodes} @@ -914,7 +938,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Constant value instructions that push literal values onto the stack: +- `%0x41`: `i32.const` - push 32-bit integer constant. +- `%0x42`: `i64.const` - push 64-bit integer constant. +- `%0x43`: `f32.const` - push 32-bit float constant. +- `%0x44`: `f64.const` - push 64-bit float constant. ### `$load-opcodes` {#load-opcodes} @@ -938,7 +966,21 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Memory load instructions that read values from linear memory: +- `%0x28`: `i32.load` - load 32-bit integer. +- `%0x29`: `i64.load` - load 64-bit integer. +- `%0x2a`: `f32.load` - load 32-bit float. +- `%0x2b`: `f64.load` - load 64-bit float. +- `%0x2c`: `i32.load8_s` - load 8-bit signed, extend to `i32`. +- `%0x2d`: `i32.load8_u` - load 8-bit unsigned, extend to `i32`. +- `%0x2e`: `i32.load16_s` - load 16-bit signed, extend to `i32`. +- `%0x2f`: `i32.load16_u` - load 16-bit unsigned, extend to `i32`. +- `%0x30`: `i64.load8_s` - load 8-bit signed, extend to `i64`. +- `%0x31`: `i64.load8_u` - load 8-bit unsigned, extend to `i64`. +- `%0x32`: `i64.load16_s` - load 16-bit signed, extend to `i64`. +- `%0x33`: `i64.load16_u` - load 16-bit unsigned, extend to `i64`. +- `%0x34`: `i64.load32_s` - load 32-bit signed, extend to `i64`. +- `%0x35`: `i64.load32_u` - load 32-bit unsigned, extend to `i64`. ### `$store-opcodes` {#store-opcodes} @@ -957,7 +999,16 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Memory store instructions that write values to linear memory: +- `%0x36`: `i32.store` - store 32-bit integer. +- `%0x37`: `i64.store` - store 64-bit integer. +- `%0x38`: `f32.store` - store 32-bit float. +- `%0x39`: `f64.store` - store 64-bit float. +- `%0x3a`: `i32.store8` - store lower 8 bits of `i32`. +- `%0x3b`: `i32.store16` - store lower 16 bits of `i32`. +- `%0x3c`: `i64.store8` - store lower 8 bits of `i64`. +- `%0x3d`: `i64.store16` - store lower 16 bits of `i64`. +- `%0x3e`: `i64.store32` - store lower 32 bits of `i64`. ### `$eqz-opcodes` {#eqz-opcodes} @@ -965,7 +1016,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ eqz-opcodes ?(%0x45 %0x50) :: i32, i64 ``` -??? +Test if value equals zero: +- `%0x45`: `i32.eqz` - test if `i32` equals zero. +- `%0x50`: `i64.eqz` - test if `i64` equals zero. ### `$eq-opcodes` {#eq-opcodes} @@ -973,7 +1026,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ eq-opcodes ?(%0x46 %0x51 %0x5b %0x61) :: i32, i64, f32, f64 ``` -??? +Test if two values are equal: +- `%0x46`: `i32.eq` - `i32` equality comparison. +- `%0x51`: `i64.eq` - `i64` equality comparison. +- `%0x5b`: `f32.eq` - `f32` equality comparison. +- `%0x61`: `f64.eq` - `f64` equality comparison. ### `$ne-opcodes` {#ne-opcodes} @@ -981,7 +1038,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ ne-opcodes ?(%0x47 %0x52 %0x5c %0x62) :: i32, i64, f32, f64 ``` -??? +Test if two values are not equal: +- `%0x47`: `i32.ne` - `i32` inequality comparison. +- `%0x52`: `i64.ne` - `i64` inequality comparison. +- `%0x5c`: `f32.ne` - `f32` inequality comparison. +- `%0x62`: `f64.ne` - `f64` inequality comparison. ### `$lt-opcodes` {#lt-opcodes} @@ -997,7 +1058,13 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Test if first value is less than second: +- `%0x48`: `i32.lt_s` - `i32` signed less-than. +- `%0x49`: `i32.lt_u` - `i32` unsigned less-than. +- `%0x53`: `i64.lt_s` - `i64` signed less-than. +- `%0x54`: `i64.lt_u` - `i64` unsigned less-than. +- `%0x5d`: `f32.lt` - `f32` less-than. +- `%0x63`: `f64.lt` - `f64` less-than. ### `$gt-opcodes` {#gt-opcodes} @@ -1013,7 +1080,13 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Test if first value is greater than second: +- `%0x4a`: `i32.gt_s` - `i32` signed greater-than. +- `%0x4b`: `i32.gt_u` - `i32` unsigned greater-than. +- `%0x55`: `i64.gt_s` - `i64` signed greater-than. +- `%0x56`: `i64.gt_u` - `i64` unsigned greater-than. +- `%0x5e`: `f32.gt` - `f32` greater-than. +- `%0x64`: `f64.gt` - `f64` greater-than. ### `$le-opcodes` {#le-opcodes} @@ -1029,7 +1102,13 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Test if first value is less than or equal to second: +- `%0x4c`: `i32.le_s` - `i32` signed less-than-or-equal. +- `%0x4d`: `i32.le_u` - `i32` unsigned less-than-or-equal. +- `%0x57`: `i64.le_s` - `i64` signed less-than-or-equal. +- `%0x58`: `i64.le_u` - `i64` unsigned less-than-or-equal. +- `%0x5f`: `f32.le` - `f32` less-than-or-equal. +- `%0x65`: `f64.le` - `f64` less-than-or-equal. ### `$ge-opcodes` {#ge-opcodes} @@ -1045,7 +1124,13 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Test if first value is greater than or equal to second: +- `%0x4e`: `i32.ge_s` - `i32` signed greater-than-or-equal. +- `%0x4f`: `i32.ge_u` - `i32` unsigned greater-than-or-equal. +- `%0x59`: `i64.ge_s` - `i64` signed greater-than-or-equal. +- `%0x5a`: `i64.ge_u` - `i64` unsigned greater-than-or-equal. +- `%0x60`: `f32.ge` - `f32` greater-than-or-equal. +- `%0x66`: `f64.ge` - `f64` greater-than-or-equal. ### `$clz-opcodes` {#clz-opcodes} @@ -1053,7 +1138,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ clz-opcodes ?(%0x67 %0x79) :: i32, i64 ``` -??? +Count leading zeros: +- `%0x67`: `i32.clz` - count leading zeros in `i32`. +- `%0x79`: `i64.clz` - count leading zeros in `i64`. ### `$ctz-opcodes` {#ctz-opcodes} @@ -1061,7 +1148,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ ctz-opcodes ?(%0x68 %0x7a) :: i32, i64 ``` -??? +Count trailing zeros: +- `%0x68`: `i32.ctz` - count trailing zeros in `i32`. +- `%0x7a`: `i64.ctz` - count trailing zeros in `i64`. ### `$popcnt-opcodes` {#popcnt-opcodes} @@ -1069,7 +1158,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ popcnt-opcodes ?(%0x69 %0x7b) :: i32, i64 ``` -??? +Count number of set bits (population count): +- `%0x69`: `i32.popcnt` - count set bits in `i32`. +- `%0x7b`: `i64.popcnt` - count set bits in `i64`. ### `$add-opcodes` {#add-opcodes} @@ -1077,7 +1168,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ add-opcodes ?(%0x6a %0x7c %0x92 %0xa0) :: i32, i64, f32, f64 ``` -??? +Addition operations: +- `%0x6a`: `i32.add` - `i32` addition. +- `%0x7c`: `i64.add` - `i64` addition. +- `%0x92`: `f32.add` - `f32` addition. +- `%0xa0`: `f64.add` - `f64` addition. ### `$sub-opcodes` {#sub-opcodes} @@ -1085,7 +1180,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ sub-opcodes ?(%0x6b %0x7d %0x93 %0xa1) :: i32, i64, f32, f64 ``` -??? +Subtraction operations: +- `%0x6b`: `i32.sub` - `i32` subtraction. +- `%0x7d`: `i64.sub` - `i64` subtraction. +- `%0x93`: `f32.sub` - `f32` subtraction. +- `%0xa1`: `f64.sub` - `f64` subtraction. ### `$mul-opcodes` {#mul-opcodes} @@ -1093,7 +1192,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ mul-opcodes ?(%0x6c %0x7e %0x94 %0xa2) :: i32, i64, f32, f64 ``` -??? +Multiplication operations: +- `%0x6c`: `i32.mul` - `i32` multiplication. +- `%0x7e`: `i64.mul` - `i64` multiplication. +- `%0x94`: `f32.mul` - `f32` multiplication. +- `%0xa2`: `f64.mul` - `f64` multiplication. ### `$div-opcodes` {#div-opcodes} @@ -1109,7 +1212,13 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Division operations: +- `%0x6d`: `i32.div_s` - `i32` signed division. +- `%0x6e`: `i32.div_u` - `i32` unsigned division. +- `%0x7f`: `i64.div_s` - `i64` signed division. +- `%0x80`: `i64.div_u` - `i64` unsigned division. +- `%0x95`: `f32.div` - `f32` division. +- `%0xa3`: `f64.div` - `f64` division. ### `$rem-opcodes` {#rem-opcodes} @@ -1123,7 +1232,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Remainder operations: +- `%0x6f`: `i32.rem_s` - `i32` signed remainder. +- `%0x70`: `i32.rem_u` - `i32` unsigned remainder. +- `%0x81`: `i64.rem_s` - `i64` signed remainder. +- `%0x82`: `i64.rem_u` - `i64` unsigned remainder. ### `$and-opcodes` {#and-opcodes} @@ -1131,7 +1244,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ and-opcodes ?(%0x71 %0x83) :: i32, i64 ``` -??? +Bitwise AND operations: +- `%0x71`: `i32.and` - `i32` bitwise AND. +- `%0x83`: `i64.and` - `i64` bitwise AND. ### `$or-opcodes` {#or-opcodes} @@ -1139,7 +1254,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ or-opcodes ?(%0x72 %0x84) :: i32, i64 ``` -??? +Bitwise OR operations: +- `%0x72`: `i32.or` - `i32` bitwise OR. +- `%0x84`: `i64.or` - `i64` bitwise OR. ### `$xor-opcodes` {#xor-opcodes} @@ -1147,7 +1264,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ xor-opcodes ?(%0x73 %0x85) :: i32, i64 ``` -??? +Bitwise XOR operations: +- `%0x73`: `i32.xor` - `i32` bitwise exclusive OR. +- `%0x85`: `i64.xor` - `i64` bitwise exclusive OR. ### `$shl-opcodes` {#shl-opcodes} @@ -1155,7 +1274,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ shl-opcodes ?(%0x74 %0x86) :: i32, i64 ``` -??? +Bitwise left shift operations: +- `%0x74`: `i32.shl` - `i32` shift left. +- `%0x86`: `i64.shl` - `i64` shift left. ### `$shr-opcodes` {#shr-opcodes} @@ -1169,7 +1290,11 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Bitwise right shift operations: +- `%0x75`: `i32.shr_s` - `i32` arithmetic right shift (sign-extending). +- `%0x76`: `i32.shr_u` - `i32` logical right shift (zero-filling). +- `%0x87`: `i64.shr_s` - `i64` arithmetic right shift (sign-extending). +- `%0x88`: `i64.shr_u` - `i64` logical right shift (zero-filling). ### `$rotl-opcodes` {#rotl-opcodes} @@ -1177,7 +1302,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ rotl-opcodes ?(%0x77 %0x89) :: i32, i64 ``` -??? +Rotate left operations: +- `%0x77`: `i32.rotl` - `i32` rotate left. +- `%0x89`: `i64.rotl` - `i64` rotate left. ### `$rotr-opcodes` {#rotr-opcodes} @@ -1185,7 +1312,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ rotr-opcodes ?(%0x78 %0x8a) :: i32, i64 ``` -??? +Rotate right operations: +- `%0x78`: `i32.rotr` - `i32` rotate right. +- `%0x8a`: `i64.rotr` - `i64` rotate right. ### `$abs-opcodes` {#abs-opcodes} @@ -1193,7 +1322,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ abs-opcodes ?(%0x8b %0x99) :: f32, f64 ``` -??? +Floating-point absolute value operations: +- `%0x8b`: `f32.abs` - `f32` absolute value. +- `%0x99`: `f64.abs` - `f64` absolute value. ### `$neg-opcodes` {#neg-opcodes} @@ -1201,7 +1332,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ neg-opcodes ?(%0x8c %0x9a) :: f32, f64 ``` -??? +Floating-point negation operations: +- `%0x8c`: `f32.neg` - `f32` negation. +- `%0x9a`: `f64.neg` - `f64` negation. ### `$ceil-opcodes` {#ceil-opcodes} @@ -1209,7 +1342,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ ceil-opcodes ?(%0x8d %0x9b) :: f32, f64 ``` -??? +Floating-point ceiling operations (round up to nearest integer): +- `%0x8d`: `f32.ceil` - `f32` ceiling. +- `%0x9b`: `f64.ceil` - `f64` ceiling. ### `$floor-opcodes` {#floor-opcodes} @@ -1217,7 +1352,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ floor-opcodes ?(%0x8e %0x9c) :: f32, f64 ``` -??? +Floating-point floor operations (round down to nearest integer): +- `%0x8e`: `f32.floor` - `f32` floor. +- `%0x9c`: `f64.floor` - `f64` floor. ### `$trunc-opcodes` {#trunc-opcodes} @@ -1237,7 +1374,17 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Truncation operations (remove fractional part): +- `%0x8f`: `f32.trunc` - `f32` truncate toward zero. +- `%0x9d`: `f64.trunc` - `f64` truncate toward zero. +- `%0xa8`: `i32.trunc_f32_s` - convert `f32` to signed `i32` (truncate). +- `%0xa9`: `i32.trunc_f32_u` - convert `f32` to unsigned `i32` (truncate). +- `%0xaa`: `i32.trunc_f64_s` - convert `f64` to signed `i32` (truncate). +- `%0xab`: `i32.trunc_f64_u` - convert `f64` to unsigned `i32` (truncate). +- `%0xae`: `i64.trunc_f32_s` - convert `f32` to signed `i64` (truncate). +- `%0xaf`: `i64.trunc_f32_u` - convert `f32` to unsigned `i64` (truncate). +- `%0xb0`: `i64.trunc_f64_s` - convert `f64` to signed `i64` (truncate). +- `%0xb1`: `i64.trunc_f64_u` - convert `f64` to unsigned `i64` (truncate). ### `$nearest-opcodes` {#nearest-opcodes} @@ -1245,7 +1392,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ nearest-opcodes ?(%0x90 %0x9e) :: f32, f64 ``` -??? +Floating-point nearest integer operations (round to nearest, ties to even): +- `%0x90`: `f32.nearest` - `f32` round to nearest integer. +- `%0x9e`: `f64.nearest` - `f64` round to nearest integer. ### `$sqrt-opcodes` {#sqrt-opcodes} @@ -1253,7 +1402,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ sqrt-opcodes ?(%0x91 %0x9f) :: f32, f64 ``` -??? +Floating-point square root operations: +- `%0x91`: `f32.sqrt` - `f32` square root. +- `%0x9f`: `f64.sqrt` - `f64` square root. ### `$min-opcodes` {#min-opcodes} @@ -1261,7 +1412,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ min-opcodes ?(%0x96 %0xa4) :: f32, f64 ``` -??? +Floating-point minimum operations: +- `%0x96`: `f32.min` - `f32` minimum of two values. +- `%0xa4`: `f64.min` - `f64` minimum of two values. ### `$max-opcodes` {#max-opcodes} @@ -1269,7 +1422,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ max-opcodes ?(%0x97 %0xa5) :: f32, f64 ``` -??? +Floating-point maximum operations: +- `%0x97`: `f32.max` - `f32` maximum of two values. +- `%0xa5`: `f64.max` - `f64` maximum of two values. ### `$copysign-opcodes` {#copysign-opcodes} @@ -1277,7 +1432,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc +$ copysign-opcodes ?(%0x98 %0xa6) :: f32, f64 ``` -??? +Floating-point copy sign operations (combine magnitude of first value with sign of second): +- `%0x98`: `f32.copysign` - `f32` copy sign. +- `%0xa6`: `f64.copysign` - `f64` copy sign. ### `$extend-opcodes` {#extend-opcodes} @@ -1294,7 +1451,14 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Integer extension operations (widen integer types): +- `%0xac`: `i64.extend_i32_s` - extend signed `i32` to `i64`. +- `%0xad`: `i64.extend_i32_u` - extend unsigned `i32` to `i64`. +- `%0xc0`: `i32.extend8_s` - extend signed `i8` to `i32`. +- `%0xc1`: `i32.extend16_s` - extend signed `i16` to `i32`. +- `%0xc2`: `i64.extend8_s` - extend signed `i8` to `i64`. +- `%0xc3`: `i64.extend16_s` - extend signed `i16` to `i64`. +- `%0xc4`: `i64.extend32_s` - extend signed `i32` to `i64` (same as `%0xac`). ### `$convert-opcodes` {#convert-opcodes} @@ -1312,7 +1476,15 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Type conversion operations (integer to floating-point): +- `%0xb2`: `f32.convert_i32_s` - convert signed `i32` to `f32`. +- `%0xb3`: `f32.convert_i32_u` - convert unsigned `i32` to `f32`. +- `%0xb4`: `f32.convert_i64_s` - convert signed `i64` to `f32`. +- `%0xb5`: `f32.convert_i64_u` - convert unsigned `i64` to `f32`. +- `%0xb7`: `f64.convert_i32_s` - convert signed `i32` to `f64`. +- `%0xb8`: `f64.convert_i32_u` - convert unsigned `i32` to `f64`. +- `%0xb9`: `f64.convert_i64_s` - convert signed `i64` to `f64`. +- `%0xba`: `f64.convert_i64_u` - convert unsigned `i64` to `f64`. ### `$reinterpret-opcodes` {#reinterpret-opcodes} @@ -1326,5 +1498,9 @@ WebAssembly opcodes. Most of these are defined in the types below, with some exc == ``` -??? +Type reinterpretation operations (reinterpret bit pattern without conversion): +- `%0xbc`: `i32.reinterpret_f32` - reinterpret `f32` bits as `i32`. +- `%0xbd`: `i64.reinterpret_f64` - reinterpret `f64` bits as `i64`. +- `%0xbe`: `f32.reinterpret_i32` - reinterpret `i32` bits as `f32`. +- `%0xbf`: `f64.reinterpret_i64` - reinterpret `i64` bits as `f64`. From 3cdc641700795c63db085a6dc582816fd7ae6bff Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Wed, 13 Aug 2025 14:32:27 +0100 Subject: [PATCH 23/57] Finish draft wasm data types --- .../wasm-walkthrough/reference/wasm-data-types.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 982a67c6..96cec64d 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -112,7 +112,7 @@ Defines the minimum and maximum size of a memory instance. The `.align` and `.of +$ block-type $@(@ func-type) :: typeidx in type section or func-type ``` -Block type for {structured control instructions ???}. Can be a type index in the [`$type-section`](#type-section) or a [`$func-type`](#func-type) function signature. +Function signature for control flow blocks (`if`, `loop`, etc.). This may be defined inline ([`$func-type`](#func-type)) or referred to by its index in the [`$type-section`](#type-section). ### `$func-type` {#func-type} @@ -144,7 +144,7 @@ Type union of all Wasm instructions. Instructions are categorized here by their operand patterns: - `%vec`: Vector instructions. (See [`$instr-vec`]($instr-vec).) -- [`$instr-short`](#instr-short): ??? +- [`$instr-short`](#instr-short): Non-numeric Wasm instructions. - [`$instr-num`](#instr-num): Standard Wasm instructions categorized by arity. - [`$instr-dbug`](#instr-dbug): Debugging. @@ -157,7 +157,7 @@ Instructions are categorized here by their operand patterns: == ``` -Debugging instructions. The only one supported here is `%print-tee`, which prints a value {TODO ???} with the given `$term` as a label. +Debugging instructions. The only one supported here is `%print-tee`, which prints a value to output with the given `$term` as a label. ### `$instr-num` {#instr-num} @@ -369,7 +369,7 @@ Wasm's binary numeric instructions: == :: $instr-short ``` -???: +Non-numeric WebAssembly instructions organized by category: - `unreachable`: Trap execution unconditionally. - `nop`: No operation. - `block`: Start a block with optional result type. @@ -555,7 +555,7 @@ An ordered sequence of [`$instruction`](#instruction)s. == ``` -{??? - some kind of const but not sure how relates to `$instr-num-zero`} +Instructions that produce constant values e.g. global variables. Unlike [`$instr-num-zero`](#instr-num-zero) which only handles scalar numeric constants, this includes vector constants, global variable reads, and reference constants. ### `$module` {#module} From e20fa17316d2335d3843043550b1a2f22fa09c5e Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Wed, 13 Aug 2025 15:14:08 +0100 Subject: [PATCH 24/57] Draft /sur/engine docs --- .../reference/wasm-interpreter-data-types.md | 267 +++++++++++++++++- 1 file changed, 266 insertions(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md index 7215f7f8..8e1307e8 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md @@ -1 +1,266 @@ -# Wasm Interpeter Data Types +# Wasm Interpreter Data Types + +{??? not sure abt intro - not very deep / clear, LLM smell} + +UrWasm's engine layer, `+engine-sur`, contains the interpreter data types that represent Wasm modules in their executable form. + +While `+wasm-sur` implements the WebAssembly Core Specification, `+engine-sur` provides the runtime representation needed for execution, with optimized module structure and execution state management. + +### `+engine-sur` {#engine-sur} + +```hoon +++ engine-sur + =, wasm-sur + |% +``` + +Wrapper arm around the engine types, making them addressable by limb resolution paths like `module:engine-sur`. Also exposes the `+wasm-sur` namespace so it can refer to types like `$type-section` directly. + +### `$module` {#module} + +```hoon ++$ module + $: + =type-section + :: + =import-section :: Changed + =function-section :: Changed to include code + :: + =table-section + =memory-section + =global-section + =export-section + =start-section + =elem-section + :: =datacnt-section :: Removed + :: =code-section :: Code moved to function section + =data-section + == +``` + +Wasm [`$module`](./wasm-data-types.md#module) as seen by the engine. Some sections have been removed or modified for efficiency: +- [`$code-section](./wasm-data-types.md#code-section) is merged into the function section. +- [`$datacnt-section](./wasm-data-types.md#datacnt-section) is removed as it's not needed during execution. +- [`$import-section](./wasm-data-types.md#import-section) is restructured for runtime resolution. + +### `$function` {#function} + +```hoon ++$ function + $: type-id=@ + locals=(list valtype) + =expression + == +``` + +Unlike `+wasm-sur`'s [`$function`](./wasm-data-types.md#function), this includes both the function signature and its implementation merged together: +- `.type-id`: Index into the [`$type-section`](./wasm-data-types.md#type-section) for this function's signature. +- `.locals`: Local variables for this function. +- [`.expression`](./wasm-data-types.md#expression): The function body as a sequence of [`$instruction`s](./wasm-data-types.md#instruction). + +### `$function-section` {#function-section} + +```hoon ++$ function-section + (list function) +``` + +List of [`$function`s](#function) in the [`$module`](#module). + +### `$import-section` {#import-section} + +```hoon ++$ import-section + $: + funcs=(list [[mod=cord name=cord] type-id=@]) + tables=(list [[mod=cord name=cord] t=table]) + memos=(list [[mod=cord name=cord] l=limits]) + globs=(list [[mod=cord name=cord] v=valtype m=?(%con %var)]) + == +``` + +Restructured import section organized by import type for efficient runtime resolution: +- `.funcs`: Imported functions with module name, export name, and type signature by index. +- `.tables`: Imported [`$table`s](./wasm-data-types.md#table) with their specifications. +- `.memos`: Imported memories with size [`$limits`](./wasm-data-types.md#limits). +- `.globs`: Imported global variables with [value type](./wasm-data-types.md#valtype) and mutability. + +### `$store` {#store} + +```hoon ++$ store + $: =shop :: resolved imports + =module :: engine representation of module + mem=(unit [buffer=@ n-pages=@]) :: single membuffer + tables=(list (list $>(%ref coin-wasm))) :: tables + globals=(list coin-wasm) + == +``` + +Complete module store containing: +- `.shop`: Resolved import dependencies (see [`$shop`](#shop)). +- `.module`: The engine's [`$module`](#module). +- `.mem`: Optional memory buffer with page count. +- `.tables`: Table instances containing function references. +- `.globals`: Global variable values. + +### `$local-state` {#local-state} + +```hoon ++$ local-state [=stack locals=(list val) =store] +``` + +Execution state for a function call: +- `.stack`: Current execution stack (see [`$stack`](#stack)). +- `.locals`: Local variable values for current function. +- `.store`: Module store containing all persistent state. + +### `$stack` {#stack} + +```hoon ++$ stack [br=branch va=(pole val)] +``` + +Execution stack with: +- `.br`: Current branch state for control flow (see [`$branch`](#branch)). +- `.va`: Stack of values. + +### `$val` {#val} + +```hoon ++$ val + $~ `@`0 + $@ @ :: numerical value + $>(%ref coin-wasm) :: reference +``` + +Runtime value on the stack, which can be either: +- A raw atom. +- A typed reference. + +### `$branch` {#branch} + +```hoon ++$ branch + $~ ~ + $@ ~ + $% [%retr ~] :: return to the caller + [%targ i=@] :: targeted block + [%trap ~] :: deterministic crash + :: + $: %bloq :: blocked on import request + [[mod=cord name=cord] =request] + =module + mem=(unit [buffer=@ n-pages=@]) :: single membuffer + tables=(list (list $>(%ref coin-wasm))) :: tables + globals=(list coin-wasm) + == == +``` + +Branch state for control flow management: +- `~`: Normal execution (no branch pending). +- `%retr`: Return to caller function. +- `%targ`: Branch to specific block label `.i`. +- `%trap`: Execution trapped (deterministic crash). +- `%bloq`: Blocked waiting for import resolution, containing the [`$request`](#request) details and current execution state. + +### `$result` {#result} + +```hoon ++$ result + $% + [%0 out=(list coin-wasm) st=store] :: success + :: + $: %1 :: block + [[mod=cord name=cord] =request] :: /module/name, request + =module + mem=(unit [buffer=@ n-pages=@]) + tables=(list (list $>(%ref coin-wasm))) + globals=(list coin-wasm) + == + :: + [%2 st=store] :: trap, crash + == +``` + +Result of module instantiation or function invocation: +- `%0`: Successful execution with output values and updated [`$store`](#store). +- `%1`: Blocked on import [`$request`](#request), containing request details and current state for resumption. +- `%2`: Crashed with final `$store` state. + +### `$request` {#request} + +```hoon ++$ request + $% + [%func args=(list coin-wasm)] :: typed values for the call + :: + $: %tabl + args=(list coin-wasm) + $= instr + $~ [%table-size `@`0] + $> + $? %call-indirect %table-get + %table-set %table-init + %table-copy %table-grow + %table-size %table-fill + == + instr-short + == + :: + $: %memo + args=(list coin-wasm) + $= instr + $~ [%memory-size %0] + $? $> $? %load %store + %memory-size %memory-grow + %memory-init %memory-copy + %memory-fill + == + instr-short + :: + $: %vec + $> $? %load %load-lane + %store %store-lane + == + instr-vec + == == == + :: + $: %glob + args=(list coin-wasm) + $= instr + $~ [%global-get `@`0] + $>(?(%global-get %global-set) instr-short) + == + == +``` + +Import request types: +- `%func`: Function call with typed argument values. +- `%tabl`: Table operation with arguments and specific table instruction. +- `%memo`: Memory operation, including vector operations and standard memory instructions. +- `%glob`: Global variable. + +### `$shop` {#shop} + +```hoon ++$ shop (list item) +``` + +List of resolved import [`$item`s](#item) representing available external dependencies. + +### `$item` {#item} + +```hoon ++$ item + %+ pair (list coin-wasm) + $: =module + mem=(unit [buffer=@ n-pages=@]) :: single membuffer + tables=(list (list $>(%ref coin-wasm))) :: tables + globals=(list coin-wasm) + == +``` + +Resolved import item containing: +- A list of values to push onto the stack when this import is invoked. +- Complete module state including memory, tables, and globals that this import provides access to. From 15a35c1f0a89852492021114048d3b81f4a91496 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Thu, 14 Aug 2025 11:45:27 +0100 Subject: [PATCH 25/57] Draft /sur/lia.hoon docs --- .claude/settings.local.json | 5 +- .../reference/lia-data-types.md | 220 ++++++++++++++++++ .../reference/wasm-data-types.md | 2 +- .../reference/wasm-interpreter-data-types.md | 2 + 4 files changed, 227 insertions(+), 2 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 009b64a9..9e4de14b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -3,7 +3,10 @@ "allow": [ "WebSearch", "WebFetch(domain:webassembly.github.io)", - "WebFetch(domain:pengowray.github.io)" + "WebFetch(domain:pengowray.github.io)", + "WebFetch(domain:gist.github.com)", + "WebFetch(domain:gist.github.com)", + "WebFetch(domain:gist.github.com)" ], "deny": [], "ask": [] diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md index abb85df9..71f21d25 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md @@ -1 +1,221 @@ # Lia Data Types + +The `+lia-sur` core builds on top of `+wasm-sur` and `+engine-sur` to define Lia's monadic, deterministic approach to making Wasm function calls and handling their results. + +### `+lia-sur` {#lia-sur} + +```hoon +++ lia-sur + =, wasm-sur + =, engine-sur + |% + :: ... +:: ... +``` + +Wrapper arm around the Lia core, making its arms and types addressable by limb resolution paths like `lia-value:lia-sur`. Also exposes the `+wasm-sur` and `+engine-sur` namespaces so this core can access the underlying Wasm types. + +### `+lia-value` {#lia-value} + +```hoon +++ lia-value + $~ [%i32 0] + $% [%octs octs] + $<(%ref coin-wasm) + == +``` + +Lia value type. Can be: +- 32-bit integer `0`. +- `%octs`: Byte data with length and content (see [`$octs`](./wasm-data-types.md#octs)). +- Any [`$coin-wasm`](./wasm-data-types.md#coin-wasm) except references. That leaves integers, floats, vectors, and binary data. + +### `+import` {#import} + +```hoon +++ import + |$ [acc] + %+ pair acc + %+ map (pair cord cord) + $- (list coin-wasm) + (script-raw-form (list coin-wasm) acc) +``` + +Wasm module import. + +Pair of the given `$acc` accumulator type with a map of imports to functions. Each `(pair cord cord)` key in the map is a cell of \[module-name export-name]. Each value in the map is a gate that takes a list of [`$coin-wasm`](./wasm-data-types.md#coin-wasm) arguments and returns the script. + +### `+lia-state` {#lia-state} + +```hoon +++ lia-state + |$ [acc] + (trel store (list (list lia-value)) (import acc)) +``` + +Execution state for a Lia script, returning a tuple of: +- [`$store`](./wasm-interpreter-data-types.md#store): Wasm module state. +- Stack of [`+lia-value`s](#lia-value) representing the current script state. +- [`+import`](#import): Available import functions and their implementations. + +### `+script-yield` {#script-yield} + +```hoon +++ script-yield + |$ [a] + $% [%0 p=a] + [%1 name=term args=(list lia-value)] + [%2 ~] + == +``` + +Result of executing a Lia script step: +- `%0`: Step completed with result of type `$a`. +- `%1`: Step blocked on external call to function `.name`, with the provided list of `.args` from the previous step. +- `%2`: Step crashed or errored. + +### `+script-result` {#script-result} + +```hoon +++ script-result + |$ [m-yil m-acc] + [(script-yield m-yil) (lia-state m-acc)] +``` + +Mold for the complete result of script execution including: +- [`$script-yield`](#script-yield) with the execution outcome. +- [`$lia-state`](#lia-state) with updated state. + +### `+script-raw-form` {#script-raw-form} + +```hoon +++ script-raw-form + |* [yil=mold acc=mold] + $-((lia-state acc) (script-result yil acc)) +``` + +Raw form of a Lia script: a gate that takes a [`$lia-state`](#lia-state) and produces a [`$script-result`](#script-result). This represents a stateful computation in the Lia monad. + +### `+script` {#script} + +```hoon +++ script + |* [m-yil=mold m-acc=mold] + |% + :: +output + :: +yield + :: +form + :: +m-sat + :: +return + :: +try + :: +catch + -- +``` + +Monadic interface for Lia scripts with yield mold `.m-yil` and accumulator mold `.m-acc`. + +#### `+output` {#output} + +```hoon +++ output (script-result m-yil m-acc) +``` + +Final `$script-result` of this script. + +#### `+yield` {#yield} + +```hoon +++ yield (script-yield m-yil) +``` + +Final `$script-yield` of this script. + +#### `+form` {#form} + +```hoon +++ form (script-raw-form m-yil m-acc) +``` + +Built script mold, analogous to `+form:m` from thread [strands](../../../urbit-os/base/threads/basics/fundamentals.md#strands). + +#### `+m-sat` {#m-sat} + +```hoon +++ m-sat (lia-state m-acc) +``` + +Execution state for this script with the provided `.m-acc`. + +#### `+return` {#return} + +```hoon +++ return :: pure + |= arg=m-yil + ^- form + |= s=m-sat + [0+arg s] +``` + +Monadic (pure) return: lifts a value into the Lia monad without changing script state. + +#### `+try` {#try} + +```hoon +++ try :: monadic bind + |* m-mond=mold + |= [mond=(script-raw-form m-mond m-acc) cont=$-(m-mond form)] + ^- form + |= s=m-sat + =^ mond-yil=(script-yield m-mond) s (mond s) + ^- output + ?. ?=(%0 -.mond-yil) [mond-yil s] + ((cont p.mond-yil) s) +``` + +Monadic bind: sequences two computations, passing the result of the first to the second if successful (`%0`). Handles early termination for blocked (`%1`) or crashed (`%2`) states. + +#### `+catch` {#catch} + +```hoon +++ catch :: bind either + |* m-mond=mold + |= $: $: try=(script-raw-form m-mond m-acc) + err=(script-raw-form m-mond m-acc) + == + cont=$-(m-mond form) + == + ^- form + |= s=m-sat + =^ try-yil=(script-yield m-mond) s (try s) + ^- output + ?: ?=(%0 -.try-yil) + ((cont p.try-yil) s) + ?: ?=(%1 -.try-yil) + [try-yil s] + =^ err-yil s (err s) + ?. ?=(%0 -.err-yil) [err-yil s] + ((cont p.err-yil) s) +``` + +Error handling combinator: attempts the first computation, and if it crashes (`%2`), tries the error handler. Blocked states (`%1`) are propagated immediately. + +### `$seed` {#seed} + +```hoon ++$ seed + $: + module=octs + past=(script-raw-form (list lia-value) *) + shop=(list (list lia-value)) + import=(import *) + == +``` + +Complete Lia interpreter state containing all necessary components for module execution: +- `.module`: Wasm module binary data. +- `.past`: Previously executed script that established the current state. +- `.shop`: External results accumulator - lists of values from resolved import function calls. +- `.import`: Map of available import functions that the module can call. + +This represents the "formal state" of the Lia interpreter, suitable for caching and resuming if necessary. + diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 96cec64d..01e8ed75 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -7,7 +7,7 @@ The first part implements the [Structure chapter](https://www.w3.org/TR/2022/WD- The second part implements Wasm's binary-format opcodes. -### `$octs` (pair @ud @) +### `$octs` {#octs} ```hoon +$ octs (pair @ud @) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md index 8e1307e8..72b2dbe2 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md @@ -12,6 +12,8 @@ While `+wasm-sur` implements the WebAssembly Core Specification, `+engine-sur` p ++ engine-sur =, wasm-sur |% + :: ... +:: ... ``` Wrapper arm around the engine types, making them addressable by limb resolution paths like `module:engine-sur`. Also exposes the `+wasm-sur` namespace so it can refer to types like `$type-section` directly. From e7589e5070ce032d5b403f8682c4d71d82f25a56 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Thu, 14 Aug 2025 11:48:48 +0100 Subject: [PATCH 26/57] Add /lib/wasm skeleton --- .../reference/lib-wasm-lia.md | 31 ++ .../reference/lib-wasm-parser.md | 157 +++++++ .../reference/lib-wasm-runner-engine.md | 26 ++ .../reference/lib-wasm-runner-op-def.md | 126 ++++++ .../reference/lib-wasm-validator.md | 31 ++ .../wasm-walkthrough/reference/wasm-libs.md | 389 ------------------ 6 files changed, 371 insertions(+), 389 deletions(-) create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md create mode 100644 content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md delete mode 100644 content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md new file mode 100644 index 00000000..92344e2b --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md @@ -0,0 +1,31 @@ + +## /lib/wasm/lia + +++ run-once + ++ init +++ run + ++ init + +++ arrows +* [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) + ++ m-sat (lia-state m-acc) + ++ call + ++ call-1 + ++ memread + ++ memwrite + ++ call-ext + ++ global-set + ++ global-get + ++ memory-size + ++ memory-grow :: returns old size in pages + ++ get-acc + ++ set-acc + ++ get-all-local-globals + ++ set-all-local-globals + +++ runnable (script (list lia-value) *) +++ cw-to-atom +++ types-atoms-to-coins +++ valtype-from-coin +++ page-size ^\~((bex 16)) +++ yield-need diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md new file mode 100644 index 00000000..50b42cf6 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -0,0 +1,157 @@ + +## /lib/wasm/parser + +++ parser + ++ main + ++ r + ++ womp + ++ bild + ++ bonk + ++ feel + ++ u-n + ++ s-n + ++ u32 (u-n 32) + ++ u64 (u-n 64) + ++ f32 + ++ f64 + ++ vec + ++ name (cook crip (vec next)) + ++ vec-u32 (vec u32) + ++ num-type + ++ vec-type (cold %v128 (just '\7b')) + ++ ref-type + ++ valtype + ++ func-type + ++ limits + ++ expr + ++ expr-pair + ++ end (just '\0b') + ++ else (just '\05') + ++ const-i32 (just '\41') + ++ const-i64 (just '\42') + ++ const-f32 (just '\43') + ++ const-f64 (just '\44') + ++ block-op (just '\02') + ++ loop-op (just '\03') + ++ if-op (just '\04') + ++ form-ranges + ++ instr + ++ select-vec + ++ br-table + ++ instr-zero (sear op-map next) + ++ block + ++ loop + ++ if + ++ block-type + ++ handle-one-arg-i32 + ++ handle-two-args-i32 + ++ handle-br-table + ++ handle-block + ++ get-valtype + ++ handle-loop + ++ handle-if + ++ handle-const-f64 + ++ handle-const-f32 + ++ handle-const-i32 + ++ handle-const-i64 + ++ fc + ++ zero-args (sear handle-zero u32) + ++ one-arg (sear handle-one ;\~(plug u32 u32)) + ++ two-args (sear handle-two ;\~(plug u32 u32 u32)) + ++ handle-zero + ++ handle-one + ++ handle-two + ++ fd + ++ memarg + ++ mem-lane + ++ const + ++ shuffle + ++ lane + ++ type-section + ++ import-section + ++ import + ++ import-desc + ++ import-func ;\~(plug (cold %func (just '\00')) u32) + ++ import-tabl ;\~(plug (cold %tabl (just '\01')) ref-type limits) + ++ import-memo ;\~(plug (cold %memo (just '\02')) limits) + ++ import-glob + ++ con-var + ++ function-section + ++ table-section + ++ table ;\~(plug ref-type limits) + ++ memory-section + ++ global-section + ++ global + ++ const-expr ;\~(sfix const-instr end) :: single instruction + ++ const-instr + ++ export-section + ++ export + ++ start-section + ++ elem-section + ++ elem + ++ elem-kind (just '\00') + ++ elem-0 + ++ elem-1 + ++ elem-2 + ++ elem-3 + ++ elem-4 + ++ elem-5 + ++ elem-6 + ++ elem-7 + ++ handle-elem-0 + ++ handle-elem-1 + ++ handle-elem-2 + ++ handle-elem-3 + ++ handle-elem-4 + ++ handle-elem-5 + ++ handle-elem-6 + ++ handle-elem-7 + ++ code-section + ++ code (bonk (vec next) ;\~(pfix u32 func)) + ++ func + ++ locals ;\~(plug u32 valtype) + ++ handle-locals + ++ data-section + ++ data + ++ to-octs + ++ datacnt-section + ++ module + ++ module-contents + ++ check + ++ customs + ++ magic (jest '\00asm') + ++ version + ++ op-map + ++ simd-map + ++ nearest + ++ sqrt + ++ div + ++ pmin + ++ pmax + ++ avgr + ++ ceil + ++ floor + ++ all-true + ++ bitmask + ++ narrow + ++ shl + ++ extadd + ++ convert + ++ mul + ++ splat + ++ eq + ++ ne + ++ abs + ++ neg + ++ trunc + ++ lt + ++ gt + ++ le + ++ ge + ++ shr + ++ min + ++ max + ++ add + ++ sub + ++ extend + ++ extmul diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md new file mode 100644 index 00000000..b3c4391e --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md @@ -0,0 +1,26 @@ + +## /lib/wasm/runner/engine + +++ engine + ++ get-types + ++ mint + ++ make-export-map + ++ find-func-id + ++ conv + ++ import-upd + ++ prep + ++ instantiate + ++ init-globals + ++ init-table + ++ init-elems + ++ init-mem + ++ init-data + ++ start + ++ wasm-need + ++ wasm-bind + ++ invoke + ++ invoke-id + ++ call + ++ eval + ++ dec-br + ++ apply diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md new file mode 100644 index 00000000..2687c631 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md @@ -0,0 +1,126 @@ + +## /lib/wasm/runner/op-def + +++ op-def + ++ mayb + ++ sure + ++ torn + ++ lane-size + ++ fuse :: from \~paldev + ++ chap + ++ page-size ^\~((bex 16)) + ++ place + ++ lim-min + ++ lim-max + ++ lte-lim + ++ change + ++ to-si + ++ en-si + ++ sat + ++ coin-to-val + ++ val-to-coin + ++ snug + ++ shot + ++ buy + ++ grab + ++ func + ++ table + ++ memo + ++ glob + ++ mem-store + ++ mem-load + ++ kind + ++ fetch-gate + ++ fetch + ++ dbug + ++ print-tee + ++ select + ++ null + ++ unreachable + ++ nop |=(local-state +<) + ++ return + ++ drop + ++ ref + ++ ref-null + ++ ref-is-null + ++ ref-func + ++ load + ++ store + ++ const + ++ get + ++ set + ++ branch + ++ table + ++ table-get + ++ table-set + ++ table-init + ++ elem-drop + ++ table-copy + ++ table-grow + ++ table-size + ++ table-fill + ++ memo + ++ memory-size + ++ memory-grow + ++ memory-init + ++ data-drop + ++ memory-copy + ++ memory-fill + ++ unar + ++ clz + ++ ctz + ++ popcnt + ++ abs + ++ neg + ++ sqrt + ++ ceil + ++ floor + ++ trunc + ++ nearest + ++ eqz + ++ wrap + ++ extend + ++ convert + ++ demote + ++ promote + ++ reinterpret + ++ bina + ++ add + ++ sub + ++ mul + ++ div + ++ rem + ++ and + ++ or + ++ xor + ++ shl + ++ shr + ++ rotl + ++ rotr + ++ min + ++ max + ++ copysign + ++ eq + ++ ne + ++ lt + ++ gt + ++ le + ++ ge + ++ simd + ++ rope + ++ fetch-vec + ++ load + ++ load-lane + ++ store + ++ store-lane + ++ const + ++ shuffle + ++ extract + ++ replace + ++ plain + ++ kind + ++ vec-unar + ++ vec-bina + ++ get-op-unar + ++ get-op-bina + ++ get-size diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md new file mode 100644 index 00000000..6d939a59 --- /dev/null +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md @@ -0,0 +1,31 @@ + +## /lib/wasm/validator + +++ validator + ++ output + ++ result-form + ++ result + ++ bind + ++ snug + ++ validate-module + ++ v-import-section + ++ validate-limits + ++ v-function-section + ++ v-table-section + ++ v-memory-section + ++ v-global-section + ++ v-export-section + ++ v-start-section + ++ v-elem-section + ++ v-datacnt-section + ++ v-code-section + ++ v-data-section + ++ validate-code + ++ validate-expr + ++ validate-instr + ++ get-type + ++ get-type-vec + ++ from-coin + ++ byte-width + ++ dim-lane + ++ unpack diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md deleted file mode 100644 index 2c63980e..00000000 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-libs.md +++ /dev/null @@ -1,389 +0,0 @@ -# UrWasm Library Reference - -nested core structure - -/lib/wasm/parser/hoon :: Wasm parser -/lib/wasm/validator/hoon :: Wasm validator -/lib/wasm/runner/op-def/hoon :: Wasm operator definitions -/lib/wasm/runner/engine/hoon :: Wasm interpreter -/lib/wasm/lia/hoon :: Lia interpreter - -foobar - - * Stateless UrWasm: `+run-once` - * Stateful UrWasm: `+run` - -*** - -## /lib/wasm/runner/engine - -++ engine - ++ get-types - ++ mint - ++ make-export-map - ++ find-func-id - ++ conv - ++ import-upd - ++ prep - ++ instantiate - ++ init-globals - ++ init-table - ++ init-elems - ++ init-mem - ++ init-data - ++ start - ++ wasm-need - ++ wasm-bind - ++ invoke - ++ invoke-id - ++ call - ++ eval - ++ dec-br - ++ apply - - -## /lib/wasm/runner/op-def - -++ op-def - ++ mayb - ++ sure - ++ torn - ++ lane-size - ++ fuse :: from \~paldev - ++ chap - ++ page-size ^\~((bex 16)) - ++ place - ++ lim-min - ++ lim-max - ++ lte-lim - ++ change - ++ to-si - ++ en-si - ++ sat - ++ coin-to-val - ++ val-to-coin - ++ snug - ++ shot - ++ buy - ++ grab - ++ func - ++ table - ++ memo - ++ glob - ++ mem-store - ++ mem-load - ++ kind - ++ fetch-gate - ++ fetch - ++ dbug - ++ print-tee - ++ select - ++ null - ++ unreachable - ++ nop |=(local-state +<) - ++ return - ++ drop - ++ ref - ++ ref-null - ++ ref-is-null - ++ ref-func - ++ load - ++ store - ++ const - ++ get - ++ set - ++ branch - ++ table - ++ table-get - ++ table-set - ++ table-init - ++ elem-drop - ++ table-copy - ++ table-grow - ++ table-size - ++ table-fill - ++ memo - ++ memory-size - ++ memory-grow - ++ memory-init - ++ data-drop - ++ memory-copy - ++ memory-fill - ++ unar - ++ clz - ++ ctz - ++ popcnt - ++ abs - ++ neg - ++ sqrt - ++ ceil - ++ floor - ++ trunc - ++ nearest - ++ eqz - ++ wrap - ++ extend - ++ convert - ++ demote - ++ promote - ++ reinterpret - ++ bina - ++ add - ++ sub - ++ mul - ++ div - ++ rem - ++ and - ++ or - ++ xor - ++ shl - ++ shr - ++ rotl - ++ rotr - ++ min - ++ max - ++ copysign - ++ eq - ++ ne - ++ lt - ++ gt - ++ le - ++ ge - ++ simd - ++ rope - ++ fetch-vec - ++ load - ++ load-lane - ++ store - ++ store-lane - ++ const - ++ shuffle - ++ extract - ++ replace - ++ plain - ++ kind - ++ vec-unar - ++ vec-bina - ++ get-op-unar - ++ get-op-bina - ++ get-size - -## /lib/wasm/lia - -++ run-once - ++ init -++ run - ++ init - -++ arrows -* [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - ++ m-sat (lia-state m-acc) - ++ call - ++ call-1 - ++ memread - ++ memwrite - ++ call-ext - ++ global-set - ++ global-get - ++ memory-size - ++ memory-grow :: returns old size in pages - ++ get-acc - ++ set-acc - ++ get-all-local-globals - ++ set-all-local-globals - -++ runnable (script (list lia-value) *) -++ cw-to-atom -++ types-atoms-to-coins -++ valtype-from-coin -++ page-size ^\~((bex 16)) -++ yield-need - -## /lib/wasm/parser - -++ parser - ++ main - ++ r - ++ womp - ++ bild - ++ bonk - ++ feel - ++ u-n - ++ s-n - ++ u32 (u-n 32) - ++ u64 (u-n 64) - ++ f32 - ++ f64 - ++ vec - ++ name (cook crip (vec next)) - ++ vec-u32 (vec u32) - ++ num-type - ++ vec-type (cold %v128 (just '\7b')) - ++ ref-type - ++ valtype - ++ func-type - ++ limits - ++ expr - ++ expr-pair - ++ end (just '\0b') - ++ else (just '\05') - ++ const-i32 (just '\41') - ++ const-i64 (just '\42') - ++ const-f32 (just '\43') - ++ const-f64 (just '\44') - ++ block-op (just '\02') - ++ loop-op (just '\03') - ++ if-op (just '\04') - ++ form-ranges - ++ instr - ++ select-vec - ++ br-table - ++ instr-zero (sear op-map next) - ++ block - ++ loop - ++ if - ++ block-type - ++ handle-one-arg-i32 - ++ handle-two-args-i32 - ++ handle-br-table - ++ handle-block - ++ get-valtype - ++ handle-loop - ++ handle-if - ++ handle-const-f64 - ++ handle-const-f32 - ++ handle-const-i32 - ++ handle-const-i64 - ++ fc - ++ zero-args (sear handle-zero u32) - ++ one-arg (sear handle-one ;\~(plug u32 u32)) - ++ two-args (sear handle-two ;\~(plug u32 u32 u32)) - ++ handle-zero - ++ handle-one - ++ handle-two - ++ fd - ++ memarg - ++ mem-lane - ++ const - ++ shuffle - ++ lane - ++ type-section - ++ import-section - ++ import - ++ import-desc - ++ import-func ;\~(plug (cold %func (just '\00')) u32) - ++ import-tabl ;\~(plug (cold %tabl (just '\01')) ref-type limits) - ++ import-memo ;\~(plug (cold %memo (just '\02')) limits) - ++ import-glob - ++ con-var - ++ function-section - ++ table-section - ++ table ;\~(plug ref-type limits) - ++ memory-section - ++ global-section - ++ global - ++ const-expr ;\~(sfix const-instr end) :: single instruction - ++ const-instr - ++ export-section - ++ export - ++ start-section - ++ elem-section - ++ elem - ++ elem-kind (just '\00') - ++ elem-0 - ++ elem-1 - ++ elem-2 - ++ elem-3 - ++ elem-4 - ++ elem-5 - ++ elem-6 - ++ elem-7 - ++ handle-elem-0 - ++ handle-elem-1 - ++ handle-elem-2 - ++ handle-elem-3 - ++ handle-elem-4 - ++ handle-elem-5 - ++ handle-elem-6 - ++ handle-elem-7 - ++ code-section - ++ code (bonk (vec next) ;\~(pfix u32 func)) - ++ func - ++ locals ;\~(plug u32 valtype) - ++ handle-locals - ++ data-section - ++ data - ++ to-octs - ++ datacnt-section - ++ module - ++ module-contents - ++ check - ++ customs - ++ magic (jest '\00asm') - ++ version - ++ op-map - ++ simd-map - ++ nearest - ++ sqrt - ++ div - ++ pmin - ++ pmax - ++ avgr - ++ ceil - ++ floor - ++ all-true - ++ bitmask - ++ narrow - ++ shl - ++ extadd - ++ convert - ++ mul - ++ splat - ++ eq - ++ ne - ++ abs - ++ neg - ++ trunc - ++ lt - ++ gt - ++ le - ++ ge - ++ shr - ++ min - ++ max - ++ add - ++ sub - ++ extend - ++ extmul - - -## /lib/wasm/validator - -++ validator - ++ output - ++ result-form - ++ result - ++ bind - ++ snug - ++ validate-module - ++ v-import-section - ++ validate-limits - ++ v-function-section - ++ v-table-section - ++ v-memory-section - ++ v-global-section - ++ v-export-section - ++ v-start-section - ++ v-elem-section - ++ v-datacnt-section - ++ v-code-section - ++ v-data-section - ++ validate-code - ++ validate-expr - ++ validate-instr - ++ get-type - ++ get-type-vec - ++ from-coin - ++ byte-width - ++ dim-lane - ++ unpack From 4d3f142a60d0974c0036a0244c5d22720b556aea Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Thu, 14 Aug 2025 13:20:17 +0100 Subject: [PATCH 27/57] Ignore .claude --- .claude/settings.local.json | 14 -------------- .gitignore | 3 +++ 2 files changed, 3 insertions(+), 14 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 9e4de14b..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "permissions": { - "allow": [ - "WebSearch", - "WebFetch(domain:webassembly.github.io)", - "WebFetch(domain:pengowray.github.io)", - "WebFetch(domain:gist.github.com)", - "WebFetch(domain:gist.github.com)", - "WebFetch(domain:gist.github.com)" - ], - "deny": [], - "ask": [] - } -} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4fa15125..dec0a36f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +#claude +.claude + # vim .tags From c68a2664ef209e3d4e8b7c09c9605575e0a5c2db Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 10:50:47 +0100 Subject: [PATCH 28/57] Draft wasm-parser docs --- .../reference/lib-wasm-parser.md | 1766 +++++++++++++++-- 1 file changed, 1612 insertions(+), 154 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md index 50b42cf6..457c6117 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -1,157 +1,1615 @@ +# Wasm Parser -## /lib/wasm/parser +The `/lib/wasm/parser.hoon` library converts Wasm bytecode into UrWasm's Hoon types defined in [`+wasm-sur`](./wasm-data-types.md), which is nested in the imported [`/sur/wasm/lia.hoon`](./lia-data-types.md) file. This library implements parsing rules that follow the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/index.html) binary format. +{TODO Implements WebAssembly's [LEB128](https://en.wikipedia.org/wiki/LEB128) unsigned integer encoding.} + +## `+parser` {#parser} + +```hoon +|% ++ parser - ++ main - ++ r - ++ womp - ++ bild - ++ bonk - ++ feel - ++ u-n - ++ s-n - ++ u32 (u-n 32) - ++ u64 (u-n 64) - ++ f32 - ++ f64 - ++ vec - ++ name (cook crip (vec next)) - ++ vec-u32 (vec u32) - ++ num-type - ++ vec-type (cold %v128 (just '\7b')) - ++ ref-type - ++ valtype - ++ func-type - ++ limits - ++ expr - ++ expr-pair - ++ end (just '\0b') - ++ else (just '\05') - ++ const-i32 (just '\41') - ++ const-i64 (just '\42') - ++ const-f32 (just '\43') - ++ const-f64 (just '\44') - ++ block-op (just '\02') - ++ loop-op (just '\03') - ++ if-op (just '\04') - ++ form-ranges - ++ instr - ++ select-vec - ++ br-table - ++ instr-zero (sear op-map next) - ++ block - ++ loop - ++ if - ++ block-type - ++ handle-one-arg-i32 - ++ handle-two-args-i32 - ++ handle-br-table - ++ handle-block - ++ get-valtype - ++ handle-loop - ++ handle-if - ++ handle-const-f64 - ++ handle-const-f32 - ++ handle-const-i32 - ++ handle-const-i64 - ++ fc - ++ zero-args (sear handle-zero u32) - ++ one-arg (sear handle-one ;\~(plug u32 u32)) - ++ two-args (sear handle-two ;\~(plug u32 u32 u32)) - ++ handle-zero - ++ handle-one - ++ handle-two - ++ fd - ++ memarg - ++ mem-lane - ++ const - ++ shuffle - ++ lane - ++ type-section - ++ import-section - ++ import - ++ import-desc - ++ import-func ;\~(plug (cold %func (just '\00')) u32) - ++ import-tabl ;\~(plug (cold %tabl (just '\01')) ref-type limits) - ++ import-memo ;\~(plug (cold %memo (just '\02')) limits) - ++ import-glob - ++ con-var - ++ function-section - ++ table-section - ++ table ;\~(plug ref-type limits) - ++ memory-section - ++ global-section - ++ global - ++ const-expr ;\~(sfix const-instr end) :: single instruction - ++ const-instr - ++ export-section - ++ export - ++ start-section - ++ elem-section - ++ elem - ++ elem-kind (just '\00') - ++ elem-0 - ++ elem-1 - ++ elem-2 - ++ elem-3 - ++ elem-4 - ++ elem-5 - ++ elem-6 - ++ elem-7 - ++ handle-elem-0 - ++ handle-elem-1 - ++ handle-elem-2 - ++ handle-elem-3 - ++ handle-elem-4 - ++ handle-elem-5 - ++ handle-elem-6 - ++ handle-elem-7 - ++ code-section - ++ code (bonk (vec next) ;\~(pfix u32 func)) - ++ func - ++ locals ;\~(plug u32 valtype) - ++ handle-locals - ++ data-section - ++ data - ++ to-octs - ++ datacnt-section - ++ module - ++ module-contents - ++ check - ++ customs - ++ magic (jest '\00asm') - ++ version - ++ op-map - ++ simd-map - ++ nearest - ++ sqrt - ++ div - ++ pmin - ++ pmax - ++ avgr - ++ ceil - ++ floor - ++ all-true - ++ bitmask - ++ narrow - ++ shl - ++ extadd - ++ convert - ++ mul - ++ splat - ++ eq - ++ ne - ++ abs - ++ neg - ++ trunc - ++ lt - ++ gt - ++ le - ++ ge - ++ shr - ++ min - ++ max - ++ add - ++ sub - ++ extend - ++ extmul + =/ sur wasm-sur + |% + :: ... + -- +-- +``` + +Parser core. Exposes the nested `+wasm-sur` namespace as `.sur`. + +## `+main` {#main} + +```hoon +++ main + |= wasm=octs + =, sur + ^- module + =| out=module + =/ bytes=tape (trip q.wasm) + :: add trailing zeros + =. bytes + %+ weld bytes + ^- tape + (reap (sub p.wasm (lent bytes)) '\00') + (scan bytes module:r) +``` + +Main parsing function that takes a Wasm binary as [`$octs`](./wasm-data-types.md#octs) and returns a parsed [`$module`](./wasm-data-types.md#module). Extends the octet stream with trailing zeros to ensure proper parsing then applies the [`+module:r`](#module) parsing rule. + +## `+r` {#r} + +Parsing rule core. Parsing rules often use the same name as the types in `/sur/wasm.hoon`, e.g. `+num-type:r` is the parsing rule that produces a `$num-type:sur`. + +### `+womp` {#womp} + +```hoon +++ womp + |* rul=rule + $_ =+ vex=(rul) + ?> ?=(^ q.vex) + p.u.q.vex +``` + +Returns a mold of the product of the given [`$rule`](../../../hoon/stdlib/3g.md#rule). + +### `+bild` {#bild} + +```hoon +++ bild + |* [vex=edge gat=_=>(rule |*(* *rule))] + ?~ q.vex + vex + %. [vex (gat p.u.q.vex)] + (comp |*([a=* b=*] b)) +``` + +Connects an [`$edge`](../../../hoon/stdlib/3g.md#edge) (parsing output) with a rule and a rule-producing gate, returning the result of the rule produced by slamming the gate with the result of the first rule. + +Used for conditional parsing based on previously parsed values. + +### `+bonk` {#bonk} + +```hoon +++ bonk + |* [tet=rule fes=rule] + |= tub=nail + ^+ (fes) + =+ try=(tet tub) + ?~ q.try try + =+ zen=(fes tub) + ?~ q.zen zen + ?: =(q.u.q.try q.u.q.zen) + zen + (fail tub) +``` + +Rule modifier. Applies two rules to a [`$nail`](../../../hoon/stdlib/3g.md#nail), failing if either rule fails to parse or if the rules return different continuations. Returns the result of the second rule otherwise. + +### `+feel` {#feel} + +```hoon +++ feel + |* [a=* sef=rule] + |= tub=nail + =+ vex=(sef tub) + ?~ q.vex vex + ?: =(a p.u.q.vex) + vex + [p=p.vex q=~] +``` + +Rule modifier. Tests equality of the parsing result with a given noun. Only succeeds if the parsed value `.p.u.q.vex` exactly matches the expected value `.a`. + +### `+u-n` {#u-n} + +```hoon +++ u-n + |= n-bits=@ + =* this $ + %+ knee *@ + |. ~+ + ;~ pose + :: multiple byte case + ?: (lte n-bits 7) fail + %+ cook + |= [n=@ m=@] + %+ add + (mul 128 m) + (sub n 128) + ;~ plug + (shim 128 255) + this(n-bits (sub n-bits 7)) + == + :: single byte case + (cook ,@ (shim 0 (dec (bex (min n-bits 7))))) + == +``` + +Parse `@` integer with bitwidth $$n$$ as an atom. Handles both single-byte and multi-byte cases recursively. + +### `+s-n` {#s-n} + +```hoon +++ s-n + |= n-bits=@ + =* this $ + %+ knee *@s + |. ~+ + ;~ pose + :: single byte: positive + (cook (cury new:si &) (shim 0 (dec (bex (min (dec n-bits) 6))))) + :: single byte: negative + %+ cook + |= n=@ + =, si + (dif (new & n) --128) + ;~ simu + (shim 64 127) + (shim (sub 128 (min 128 (bex (dec n-bits)))) 127) + == + :: multiple bytes + ?: (lte n-bits 7) fail + %+ cook + |= [n=@s m=@s] + =, si + (sum (dif n --128) (pro --128 m)) + ;~ plug + (cook (cury new:si &) (shim 128 255)) + this(n-bits (sub n-bits 7)) + == + == +``` + +Parse `@s` integer with bitwidth $$n$$. Implements WebAssembly's signed LEB128 integer encoding with proper sign extension handling for positive and negative integers. + +### `+u32` {#u32} + +```hoon +++ u32 (u-n 32) +``` + +Parse 32-bit unsigned integer. + +### `+u64` {#u64} + +```hoon +++ u64 (u-n 64) +``` + +Parse 64-bit unsigned integer. + +### `+f32` {#f32} + +```hoon +++ f32 + %+ cook + |= =(list @) + ;; @rs + (rep 3 list) + (stun [4 4] next) +``` + +Parse 32-bit float. + +Reads exactly 4 bytes and reconstructs them into a `@rs` atom. + +### `+f64` {#f64} + +```hoon +++ f64 + %+ cook + |= =(list @) + ;; @rd + (rep 3 list) + (stun [8 8] next) +``` + +Parse 64-bit float. + +Reads exactly 8 bytes and reconstructs them into a `@rd` atom. + +### `+vec` {#vec} + +```hoon +++ vec + |* rul=rule + ;~ bild + u32 + |= n=@ + (stun [n n] rul) + == +``` + +Parses a Wasm vector. + +First parses a u32 length, then parses exactly that many instances of the given rule. This is the standard WebAssembly encoding for variable-length sequences. + +### `+name` {#name} + +```hoon +++ name (cook crip (vec next)) +``` + +Parse Wasm name (UTF-8 string). + +Uses `+vec` to get the length and bytes, then converts the parsed `$rule` to a `@t`. + +### `+vec-u32` {#vec-u32} + +```hoon +++ vec-u32 (vec u32) +``` + +Parse vector of 32-bit unsigned integers. + +### `+num-type` {#num-type} + +```hoon +++ num-type + %+ cook |=(num-type:sur +<) + ;~ pose + (cold %i32 (just '\7f')) + (cold %i64 (just '\7e')) + (cold %f32 (just '\7d')) + (cold %f64 (just '\7c')) + == +``` + +Parse Wasm number type. + +Maps binary opcodes to [`$num-type`](./wasm-data-types.md#num-type) values. + +### `+vec-type` {#vec-type} + +```hoon +++ vec-type (cold %v128 (just '\7b')) +``` + +Parse Wasm vector type. + +### `+ref-type` {#ref-type} + +```hoon +++ ref-type + %+ cook |=(ref-type:sur +<) + ;~ pose + (cold %extn (just '\6f')) + (cold %func (just '\70')) + == +``` + +Parse Wasm reference type. + +Maps binary opcodes to [`$ref-type`](./wasm-data-types.md#ref-type) values. + +### `+valtype` {#valtype} + +```hoon +++ valtype + %+ cook |=(valtype:sur +<) + ;~(pose num-type vec-type ref-type) +``` + +Parse Wasm value type. + +Homogenizes results of `+num-type:r`, `+vec-type:r`, and `+ref-type:r` parsers into [`$valtype`s](./wasm-data-types.md#valtype). + +### `+func-type` {#func-type} + +```hoon +++ func-type + %+ cook |=(func-type:sur +<) + ;~ pfix + (just '\60') + ;~(plug (vec valtype) (vec valtype)) + == +``` + +Parse Wasm function. + +Expects the function type opcode `\60`, followed by parameter types and result types as vectors. (See [`$func-type`](./wasm-data-types.md#func-type).) + +### `+limits` {#limits} + +```hoon +++ limits + %+ cook |=(limits:sur +<) + ;~ pose + ;~(plug (cold %flor (just '\00')) u32) + ;~(plug (cold %ceil (just '\01')) u32 u32) + == +``` + +Parse Wasm memory/table limits. + +Either minimum only (`%flor`) or minimum and maximum (`%ceil`). + +## Instruction and Expression Parsing Rules + +### `+expr` {#expr} + +```hoon +++ expr + %+ knee *expression:sur + |. ~+ + ;~(sfix (star instr) end) +``` + +Parse Wasm expression as a sequence of instructions terminated by an [`+end`](#end) opcode. + +### `+expr-pair` {#expr-pair} + +```hoon +++ expr-pair + %+ knee [*expression:sur *expression:sur] + |. ~+ + ;~ plug + (star instr) + ;~ pose + (cold ~ end) + (ifix [else end] (star instr)) + == + == +``` + +Parse a pair of [`$expression`s](./wasm-data-types.md#expression) for [`+if`](#if) statements. + +First expression (true branch), followed by optional [`+else`](#else) and second expression (false branch). + +### `+end` {#end} + +{TODO change `\0b` in prose to `0x0b` as in actual Wasm binary} + +```hoon +++ end (just '\0b') +``` + +Parse Wasm `end` opcode (`\0b`). + +### `+else` {#else} + +```hoon +++ else (just '\05') +``` + +Parse Wasm `else` opcode (`\05`). + +### `+const-i32` {#const-i32} + +```hoon +++ const-i32 (just '\41') +``` + +Parse Wasm `i32.const` opcode (`\41`). + +### `+const-i64` {#const-i64} + +```hoon +++ const-i64 (just '\42') +``` + +Parse Wasm `i64.const` opcode (`\42`). + +### `+const-f32` {#const-f32} + +```hoon +++ const-f32 (just '\43') +``` + +Parse Wasm `f32.const` opcode (`\43`). + +### `+const-f64` {#const-f64} + +```hoon +++ const-f64 (just '\44') +``` + +Parse Wasm `f64.const` opcode (`\44`). + +### `+block-op` {#block-op} + +```hoon +++ block-op (just '\02') +``` + +Parse Wasm `block` opcode (`\02`). + +### `+loop-op` {#loop-op} + +```hoon +++ loop-op (just '\03') +``` + +Parse Wasm `loop` opcode (`\03`). + +### `+if-op` {#if-op} + +```hoon +++ if-op (just '\04') +``` + +Parse Wasm `if` opcode (`\04`). + +### `+form-ranges` {#form-ranges} + +```hoon +++ form-ranges + |= l=(list @) + ^- (list ?(@ [@ @])) + ?~ l ~ + =+ a=i.l + =+ b=i.l + |- ^- (list ?(@ [@ @])) + ?~ t.l + :_ ~ + ?: =(a b) a + [a b] + ?> (gth i.t.l b) + ?: =(i.t.l +(b)) + $(b i.t.l, t.l t.t.l) + :- ?: =(a b) a + [a b] + $(a i.t.l, b i.t.l, t.l t.t.l) +``` + +Helper function that converts a list of sorted integers into a list of ranges (`?(@ [@ @])`). + +??? - Used to optimize parsing by creating efficient lookup tables for opcodes. + +### `+instr` {#instr} + +```hoon +++ instr + ~+ %- stew ^. stet + ;: welp + ^. limo + :~ + ['\fc' ;~(pfix next fc)] + ['\fd' ;~(pfix next fd)] + ['\1c' select-vec] + ['\0e' br-table] + ['\02' block] + ['\03' loop] + ['\04' if] + ['\d0' ;~(pfix next (stag %ref-null ref-type))] + ['\d2' ;~(pfix next (stag %ref-func u32))] + == + :: + %- turn :_ (late instr-zero) + %- form-ranges + %+ skim (gulf 0 255) + |=(n=@ ?=(^ (op-map n))) + :: + %+ turn + %- form-ranges + %+ skim (gulf 0 255) + |=(n=@ ?=(^ (handle-one-arg-i32 n 0))) + %- late + %+ sear handle-one-arg-i32 + ;~(plug next u32) + :: + ^. limo + :~ + ['\41' (cook handle-const-i32 ;~(pfix next (s-n 32)))] + ['\42' (cook handle-const-i64 ;~(pfix next (s-n 64)))] + ['\43' (cook handle-const-f32 ;~(pfix next f32))] + ['\44' (cook handle-const-f64 ;~(pfix next f64))] + == + :: + %+ turn + %- form-ranges + %+ skim (gulf 0 255) + |=(n=@ ?=(^ (handle-two-args-i32 n 0 0))) + %- late + %+ sear handle-two-args-i32 + ;~(plug next u32 u32) + :: + == +``` + +Main instruction parser. Uses `+stew` parser to switch on the given text to the appropriate parser. + +### `+select-vec` {#select-vec} + +```hoon +++ select-vec + %+ cook |=(instruction:sur +<) + ;~ pfix + next + %+ stag %select + %+ stag %~ + (vec valtype) + == +``` + +??? - Parse Wasm `select` expression with optional type annotation for vectors. + +### `+br-table` {#br-table} + +```hoon +++ br-table + %+ cook handle-br-table + ;~(pfix next ;~(plug vec-u32 u32)) +``` + +Parse Wasm `br_table` (branch table) expression with vector of labels and default label. + +### `+instr-zero` {#instr-zero} + +```hoon +++ instr-zero (sear op-map next) +``` + +Parse instructions with zero arguments by looking up the opcode in the [opcode map](#op-map). + +### `+block` {#block} + +```hoon +++ block + %+ cook handle-block + ;~(pfix next ;~(plug block-type expr)) +``` + +Parse Wasm `block` expression with [block type](#block-type) and body [expression](#expr). + +### `+loop` {#loop} + +```hoon +++ loop + %+ cook handle-loop + ;~(pfix next ;~(plug block-type expr)) +``` + +Parse Wasm `loop` expression with block type and body expression. + +### `+if` {#if} + +```hoon +++ if + %+ cook handle-if + ;~ pfix + next + ;~(plug block-type expr-pair) + == +``` + +Parse Wasm `if` expression with block type and true/false expression pair. + +### `+block-type` {#block-type} + +```hoon +++ block-type + %+ cook |=(block-type:sur +<) + ;~ pose + (cold [~ ~] (just '\40')) + ;~(plug (easy ~) (sear get-valtype next) (easy ~)) + :: + %+ sear + |= a=@s + ^- (unit @) + ?. (syn:si a) ~ + `(abs:si a) + (s-n 33) + :: + == +``` + +Parse Wasm [`$block-type`](./wasm-data-types.md#block-type). + +## Handler Functions + +### `+handle-one-arg-i32` {#handle-one-arg-i32} + +```hoon +++ handle-one-arg-i32 + |= [op=char arg=@] + ^- (unit instruction:sur) + ?+ op ~ + %0xc `[%br arg] + %0xd `[%br-if arg] + %0x10 `[%call arg] + %0x20 `[%local-get arg] + %0x21 `[%local-set arg] + %0x22 `[%local-tee arg] + %0x23 `[%global-get arg] + %0x24 `[%global-set arg] + %0x25 `[%table-get arg] + %0x26 `[%table-set arg] + %0x3f `[%memory-size ?>(=(arg 0) %0)] + %0x40 `[%memory-grow ?>(=(arg 0) %0)] + == +``` + +Handle Wasm instructions that take one 32-bit argument. + +Maps opcodes to their corresponding [`$instruction`](./wasm-data-types.md#instruction) representations. + +### `+handle-two-args-i32` {#handle-two-args-i32} + +```hoon +++ handle-two-args-i32 + |= [op=char arg1=@ arg2=@] + ^- (unit instruction:sur) + ?+ op ~ + %0x11 + `[%call-indirect arg1 arg2] + :: + %0x28 + `[%load %i32 [arg1 arg2] ~ ~] + :: + %0x29 + `[%load %i64 [arg1 arg2] ~ ~] + :: + %0x2a + `[%load %f32 [arg1 arg2] ~ ~] + :: + %0x2b + `[%load %f64 [arg1 arg2] ~ ~] + :: + %0x2c + `[%load %i32 [arg1 arg2] `%8 `%s] + :: + %0x2d + `[%load %i32 [arg1 arg2] `%8 `%u] + :: + %0x2e + `[%load %i32 [arg1 arg2] `%16 `%s] + :: + %0x2f + `[%load %i32 [arg1 arg2] `%16 `%u] + :: + %0x30 + `[%load %i64 [arg1 arg2] `%8 `%s] + :: + %0x31 + `[%load %i64 [arg1 arg2] `%8 `%u] + :: + %0x32 + `[%load %i64 [arg1 arg2] `%16 `%s] + :: + %0x33 + `[%load %i64 [arg1 arg2] `%16 `%u] + :: + %0x34 + `[%load %i64 [arg1 arg2] `%32 `%s] + :: + %0x35 + `[%load %i64 [arg1 arg2] `%32 `%u] + :: + %0x36 + `[%store %i32 [arg1 arg2] ~] + :: + %0x37 + `[%store %i64 [arg1 arg2] ~] + :: + %0x38 + `[%store %f32 [arg1 arg2] ~] + :: + %0x39 + `[%store %f64 [arg1 arg2] ~] + :: + %0x3a + `[%store %i32 [arg1 arg2] `%8] + :: + %0x3b + `[%store %i32 [arg1 arg2] `%16] + :: + %0x3c + `[%store %i64 [arg1 arg2] `%8] + :: + %0x3d + `[%store %i64 [arg1 arg2] `%16] + :: + %0x3e + `[%store %i64 [arg1 arg2] `%32] + == +:: +``` + +Handle Wasm instructions that take two 32-bit immediate arguments. + +### `+handle-br-table` {#handle-br-table} + +```hoon +++ handle-br-table + |= [vec=(list @) i=@] + ^- instruction:sur + [%br-table vec i] +``` + +Handle Wasm `br_table` expression (switch statement) by constructing the list of branches with a default index. + +### `+handle-block` {#handle-block} + +```hoon +++ handle-block + |= [type=block-type:sur body=expression:sur] + ^- $>(%block instruction:sur) + [%block type body] +``` + +Handle Wasm `block` expression. + +### `+get-valtype` {#get-valtype} + +```hoon +++ get-valtype + |= byte=@ + ^- (unit valtype:sur) + ?+ byte ~ + %0x7f `%i32 + %0x7e `%i64 + %0x7d `%f32 + %0x7c `%f64 + == +``` + +Map byte values to value types for block type parsing. + +Map opcodes to value types to construct [`$valtype`s](./wasm-data-types.md#valtype) + +### `+handle-loop` {#handle-loop} + +```hoon +++ handle-loop + |= [type=block-type:sur body=expression:sur] + ^- instruction:sur + [%loop type body] +``` + +Handle Wasm `loop` expression. + +### `+handle-if` {#handle-if} + +```hoon +++ handle-if + |= $: type=block-type:sur + body-true=expression:sur + body-false=expression:sur + == + ^- instruction:sur + [%if type body-true body-false] +``` + +Handle Wasm `if` expression construction with true and false branches. + +### `+handle-const-f64` {#handle-const-f64} + +```hoon +++ handle-const-f64 + |= i=@rd + ^- instruction:sur + [%const %f64 i] +``` + +Handle Wasm `f64.const` expression. + +### `+handle-const-f32` {#handle-const-f32} + +```hoon +++ handle-const-f32 + |= i=@rs + ^- instruction:sur + [%const %f32 i] +``` + +Handle Wasm `f32.const` expression. + +### `+handle-const-i32` {#handle-const-i32} + +```hoon +++ handle-const-i32 + |= i=@s + ^- instruction:sur + =; i-unsigned=@ + [%const %i32 i-unsigned] + =, si + ?: (syn i) + +:(old i) + (sub (bex 32) +:(old i)) +``` + +Handle Wasm `i32.const` expression with signed to unsigned conversion. + +### `+handle-const-i64` {#handle-const-i64} + +```hoon +++ handle-const-i64 + |= i=@s + ^- instruction:sur + =; i-unsigned=@ + [%const %i64 i-unsigned] + =, si + ?: (syn i) + +:(old i) + (sub (bex 64) +:(old i)) +``` + +Handle Wasm `i64.const` expression with signed to unsigned conversion. + +## `+fc` {#fc} + +`0xFC` extension parser for saturating truncation instructions. + +```hoon +++ fc + |^ + %+ cook |=(instruction:sur +<) + ;~ pose + zero-args + one-arg + two-args + == +``` + +Parser for Wasm instructions prefixed with `0xFC`, which includes memory and table operations. + +### `+zero-args` {#zero-args} + +```hoon +++ zero-args (sear handle-zero u32) +``` + +Parse extended instructions with zero additional arguments. + +### `+one-arg` {#one-arg} + +```hoon +++ one-arg (sear handle-one ;~(plug u32 u32)) +``` + +Parse extended instructions with one additional argument. + +### `+two-args` {#two-args} + +```hoon +++ two-args (sear handle-two ;~(plug u32 u32 u32)) +``` + +Parse extended instructions with two additional arguments. + +### `+handle-zero` {#handle-zero} + +```hoon +++ handle-zero + |= op=@ + ^- (unit instruction:sur) + ?. (lte op 7) ~ + :- ~ + :* + %trunc + :: Type + ?:((lte op 3) %i32 %i64) + :: Source type + `?:(=(0 (mod (div op 2) 2)) %f32 %f64) + :: Mode + `?:(=(0 (mod op 2)) %s %u) + :: + & :: saturated + == +``` + +Handle saturating truncation instructions (opcodes 0-7). + +### `+handle-one` {#handle-one} + +```hoon +++ handle-one + |= [op=@ arg=@] + ^- (unit instruction:sur) + ?+ op ~ + %9 `[%data-drop arg] + %11 `[%memory-fill ?>(?=(%0 arg) arg)] + %13 `[%elem-drop arg] + %15 `[%table-grow arg] + %16 `[%table-size arg] + %17 `[%table-fill arg] + == +``` + +Handle extended instructions with one argument. + +### `+handle-two` {#handle-two} + +```hoon +++ handle-two + |= [op=@ arg1=@ arg2=@] + ^- (unit instruction:sur) + ?+ op ~ + %8 `[%memory-init arg1 ?>(?=(%0 arg2) arg2)] + %10 `[%memory-copy ?>(?=(%0 arg1) arg1) ?>(?=(%0 arg2) arg2)] + %12 `[%table-init arg1 arg2] + %14 `[%table-copy arg1 arg2] + == +``` + +Handle extended instructions with two arguments. + +## `+fd` {#fd} + +0xFD extension parser for SIMD (vector) instructions. + +```hoon +++ fd + |^ + :: Opcode and immediate parameters + ;~ pose + (sear memarg ;~(plug u32 u32 u32)) + (sear mem-lane ;~(plug u32 ;~(plug u32 u32) next)) + (cook const ;~(pfix (feel 12 u32) (stun [16 16] next))) + (cook shuffle ;~(pfix (feel 13 u32) (stun [16 16] next))) + (sear lane ;~(plug u32 next)) + (sear simd-map u32) + == +``` + +Parser for Wasm SIMD instructions. + +### `+memarg` {#memarg} + +```hoon +++ memarg + |= [op=@ mem=[@ @]] + ^- (unit instruction:sur) + =; =(unit instr-vec:sur) + ?~ unit ~ + `[%vec u.unit] + ?+ op ~ + %0 `[%load mem ~] + %1 `[%load mem ~ %8 %extend %s] + %2 `[%load mem ~ %8 %extend %u] + %3 `[%load mem ~ %16 %extend %s] + %4 `[%load mem ~ %16 %extend %u] + %5 `[%load mem ~ %32 %extend %s] + %6 `[%load mem ~ %32 %extend %u] + %7 `[%load mem ~ %8 %splat] + %8 `[%load mem ~ %16 %splat] + %9 `[%load mem ~ %32 %splat] + %10 `[%load mem ~ %64 %splat] + %92 `[%load mem ~ %32 %zero] + %93 `[%load mem ~ %64 %zero] + %11 `[%store mem] + == +:: +``` + +Handle SIMD memory instructions (vector loads/stores with memory arguments). + +### `+mem-lane` {#mem-lane} + +```hoon +++ mem-lane + |= [op=@ mem=[@ @] l=@] + ^- (unit instruction:sur) + =; =(unit instr-vec:sur) + ?~ unit ~ + `[%vec u.unit] + ?+ op ~ + %84 `[%load-lane mem %8 l] + %85 `[%load-lane mem %16 l] + %86 `[%load-lane mem %32 l] + %87 `[%load-lane mem %64 l] + %88 `[%store-lane mem %8 l] + %89 `[%store-lane mem %16 l] + %90 `[%store-lane mem %32 l] + %91 `[%store-lane mem %64 l] + == +:: +``` + +Handle SIMD lane-specific memory operations. + +### `+const` {#const} + +```hoon +++ const + |= =(list @) + ^- instruction:sur + :^ %vec %const %v128 + (rep 3 list) +``` + +Handle SIMD constant vectors (`v128.const`). + +### `+shuffle` {#shuffle} + +```hoon +++ shuffle + |= =(list @) + ^- instruction:sur + [%vec %shuffle list] +``` + +Handle SIMD shuffle operations with lane indices. + +### `+lane` {#lane} + +```hoon +++ lane + |= [op=@ l=@] + ^- (unit instruction:sur) + =; =(unit instr-vec:sur) + ?~ unit ~ + `[%vec u.unit] + ?+ op ~ + %21 `[%extract %i8 l %s] + %22 `[%extract %i8 l %u] + %23 `[%replace %i8 l] + %24 `[%extract %i16 l %s] + %25 `[%extract %i16 l %u] + %26 `[%replace %i16 l] + %27 `[%extract %i32 l %u] + %28 `[%replace %i32 l] + %29 `[%extract %i64 l %u] + %30 `[%replace %i64 l] + %31 `[%extract %f32 l %u] + %32 `[%replace %f32 l] + %33 `[%extract %f64 l %u] + %34 `[%replace %f64 l] + == +``` + +Handle SIMD lane extract/replace operations. + +## Section Parsers + +### `+type-section` {#type-section} + +```hoon +++ type-section + %+ cook |=(type-section:sur +<) + (vec func-type) +``` + +Parse Wasm module [`$type-section`](./wasm-data-types.md#type-section) containing function signatures. + +### `+import-section` {#import-section} + +```hoon +++ import-section + %+ cook |=(import-section:sur +<) + (vec import) +``` + +Parse Wasm module [`$import-section`](./wasm-data-types.md#import-section) containing module dependencies. + +### `+import` {#import} + +```hoon +++ import + %+ cook |=(import:sur +<) + ;~ plug + name + name + import-desc + == +``` + +Parse individual module [`$import`](./wasm-data-types.md#import) entry with module name, import name, and description. + +### `+import-desc` {#import-desc} + +```hoon +++ import-desc + ;~ pose + import-func + import-tabl + import-memo + import-glob + == +``` + +Parse module import description (function, table, memory, or global). + +### `+import-func` {#import-func} + +```hoon +++ import-func ;~(plug (cold %func (just '\00')) u32) +``` + +Parse function import with type index. + +### `+import-tabl` {#import-tabl} + +```hoon +++ import-tabl ;~(plug (cold %tabl (just '\01')) ref-type limits) +``` + +Parse table import with [reference type](./wasm-data-types.md#ref-type) and [`$limits`](./wasm-data-types.md#limits). + +### `+import-memo` {#import-memo} + +```hoon +++ import-memo ;~(plug (cold %memo (just '\02')) limits) +``` + +Parse memory import with size limits. + +### `+import-glob` {#import-glob} + +```hoon +++ import-glob + ;~ plug + (cold %glob (just '\03')) + valtype + con-var + == +``` + +Parse global import with value type and mutability. + +### `+con-var` {#con-var} + +```hoon +++ con-var + ;~ pose + (cold %con (just '\00')) + (cold %var (just '\01')) + == +``` + +Parse constant/variable mutability flag. + +### `+function-section` {#function-section} + +```hoon +++ function-section + %+ cook |=(function-section:sur +<) + (vec u32) +``` + +Parse Wasm module [`$function-section`](./wasm-data-types.md#function-section) with type indices. + +### `+table-section` {#table-section} + +```hoon +++ table-section + %+ cook |=(table-section:sur +<) + (vec table) +``` + +Parse Wasm module [`$table-section`](./wasm-data-types.md#table-section). + +### `+table` {#table} + +```hoon +++ table ;~(plug ref-type limits) +``` + +Parse table definition with reference type and size limits. + +### `+memory-section` {#memory-section} + +```hoon +++ memory-section + %+ cook |=(memory-section:sur +<) + (vec limits) +``` + +Parse Wasm module [`$memory-section`](./wasm-data-types.md#memory-section) with size limits. + +### `+global-section` {#global-section} + +```hoon +++ global-section + %+ cook |=(global-section:sur +<) + (vec global) +``` + +Parse Wasm module [`$global-section`](./wasm-data-types.md#global-section). + +### `+global` {#global} + +```hoon +++ global + %+ cook |=(global:sur +<) + ;~ plug + valtype + con-var + const-expr + == +``` + +Parse [`$global`](./wasm-data-types.md#global) variable with type, mutability, and initial value. + +### `+const-expr` {#const-expr} + +```hoon +++ const-expr ;~(sfix const-instr end) :: single instruction +``` + +Parse constant expression (single constant instruction followed by end). + +### `+const-instr` {#const-instr} + +```hoon +++ const-instr +%+ sear + |= i=instruction:sur + ^- (unit const-instr:sur) + ?. ?=(const-instr:sur i) + ~ + `i +instr +``` + +Parse instructions that can appear in constant expressions. + +### `+export-section` {#export-section} + +```hoon +++ export-section + %+ cook export-section:sur + (vec export) +``` + +Parse Wasm export section. + +### `+export` {#export} + +```hoon +++ export + ;~ plug + name + %+ cook |=(export-desc:sur +<) + ;~ pose + ;~(plug (cold %func (just '\00')) u32) + ;~(plug (cold %tabl (just '\01')) u32) + ;~(plug (cold %memo (just '\02')) u32) + ;~(plug (cold %glob (just '\03')) u32) + == + == +``` + +Parse export entry with name and description. + +### `+start-section` {#start-section} + +```hoon +++ start-section + %+ cook |=(start-section:sur +<) + (stag ~ u32) +``` + +Parse Wasm start section with start function index. + +### `+elem-section` {#elem-section} + +```hoon +++ elem-section + %+ cook |=(elem-section:sur +<) + (vec elem) +``` + +Parse Wasm element section for table initialization. + +### `+elem` {#elem} + +```hoon +++ elem + ;~ pose + elem-0 + elem-1 + elem-2 + elem-3 + elem-4 + elem-5 + elem-6 + elem-7 + == +``` + +Parse element segment in one of eight different formats (Wasm specification variations). + +### `+elem-kind` {#elem-kind} + +```hoon +++ elem-kind (just '\00') +``` + +Parse element kind (currently only function references supported). + +### `+elem-0` through +elem-7 {#elem-variants} + +```hoon +++ elem-0 + %+ cook handle-elem-0 + ;~ pfix (just '\00') + ;~(plug const-expr (vec u32)) + == +``` + +Parse different element segment formats. Each format has different combinations of: +- Active/passive/declarative mode +- Table index specification +- Element type annotation +- Initialization expression vs function indices + +### `+handle-elem-0` through +handle-elem-7 {#handle-elem-variants} + +Handler functions that convert parsed element data into the standard [`$elem`](./wasm-data-types.md#elem) format, normalizing the different binary representations. + +### `+code-section` {#code-section} + +```hoon +++ code-section + %+ cook |=(code-section:sur +<) + (vec code) +``` + +Parse Wasm code section containing function implementations. + +### `+code` {#code} + +```hoon +++ code (bonk (vec next) ;~(pfix u32 func)) +``` + +Parse code entry with size validation and function body. + +### `+func` {#func} + +```hoon +++ func + ;~ plug + (cook handle-locals (vec locals)) + expr + == +``` + +Parse function implementation with local variable declarations and body. + +### `+locals` {#locals} + +```hoon +++ locals ;~(plug u32 valtype) +``` + +Parse local variable declaration (count and type). + +### `+handle-locals` {#handle-locals} + +```hoon +++ handle-locals + |= l=(list [n=@ v=valtype:sur]) + ^- (list valtype:sur) + ?~ l ~ + %+ weld (reap n.i.l v.i.l) + $(l t.l) +``` + +Expand compressed local variable declarations into full list. + +### `+data-section` {#data-section} + +```hoon +++ data-section + %+ cook |=(data-section:sur +<) + (vec data) +``` + +Parse Wasm data section for memory initialization. + +### `+data` {#data} + +```hoon +++ data + %+ cook |=(data:sur +<) + ;~ pose + ;~ plug + (cold %acti (just '\00')) + const-expr + (cook to-octs (vec next)) + == + :: + ;~ plug + (cold %pass (just '\01')) + (cook to-octs (vec next)) + == + :: + ;~ plug + (cold %acti (just '\02')) + ;~ pfix + u32 + ;~ plug + const-expr + (cook to-octs (vec next)) + == == == == +``` + +Parse data segment in active or passive mode with initialization data. + +### `+to-octs` {#to-octs} + +```hoon +++ to-octs + |= =tape + ^- octs + :- (lent tape) + (rep 3 tape) +``` + +Convert tape to octets format. + +### `+datacnt-section` {#datacnt-section} + +```hoon +++ datacnt-section + %+ cook |=(datacnt-section:sur +<) + (stag ~ u32) +``` + +Parse Wasm data count section. + +### `+module` {#module} + +```hoon +++ module + %+ cook |=(module:sur +<) + ;~ pfix + magic + version + (ifix [customs customs] module-contents) + == +``` + +Parse complete Wasm module with magic number, version, and sections. + +### `+module-contents` {#module-contents} + +```hoon +++ module-contents + ;~ (glue customs) + (check 1 type-section *type-section:sur) + (check 2 import-section *import-section:sur) + (check 3 function-section *function-section:sur) + (check 4 table-section *table-section:sur) + (check 5 memory-section *memory-section:sur) + (check 6 global-section *global-section:sur) + (check 7 export-section *export-section:sur) + (check 8 start-section *start-section:sur) + (check 9 elem-section *elem-section:sur) + (check 12 datacnt-section *datacnt-section:sur) + (check 10 code-section *code-section:sur) + (check 11 data-section *data-section:sur) + == +``` + +Parse module contents with all sections in order, allowing for missing optional sections. + +### `+check` {#check} + +```hoon +++ check + |* [id=@ sec=rule def=*] + ;~ pose + :: section present + ;~ pfix + (just `@`id) + (bonk (vec next) ;~(pfix u32 sec)) + == + :: section missing + (easy `(womp sec)`def) + == +``` + +Check for optional section presence, providing default values for missing sections. + +### `+customs` {#customs} + +```hoon +++ customs + %- star + ;~ plug + (just '\00') + (vec next) + == +``` + +Parse custom sections (ignored during parsing). + +### `+magic` {#magic} + +```hoon +++ magic (jest '\00asm') +``` + +Parse Wasm magic number (`\00asm`). + +### `+version` {#version} + +```hoon +++ version + ;~ plug + (just '\01') + (just '\00') :: leading zeros shenanigans + (just '\00') + (just '\00') + == +``` + +Parse Wasm version number (currently version 1). + +## `+op-map` {#op-map} + +```hoon +++ op-map + |= op=char + ~+ + ^- (unit instruction:sur) + ?+ op ~ + %0x0 `[%unreachable ~] + %0x1 `[%nop ~] + %0xf `[%return ~] + %0x1a `[%drop ~] + %0x1b `[%select ~] + :: [more opcodes...] + == +``` + +Maps single-byte Wasm opcodes to their corresponding [`$instruction`](./wasm-data-types.md#instruction) representations. Covers all basic Wasm instructions including: +- Control flow (`unreachable`, `nop`, `return`) +- Stack manipulation (`drop`, `select`) +- Arithmetic operations (`add`, `sub`, `mul`, `div`) +- Comparison operations (`eq`, `ne`, `lt`, `gt`, `le`, `ge`) +- Bitwise operations (`and`, `or`, `xor`, `shl`, `shr`) +- Type conversion operations (`extend`, `convert`, `reinterpret`) + +## `+simd-map` {#simd-map} + +```hoon +++ simd-map + |= op=@ + ~+ + |^ + ^- (unit instruction:sur) + =; =(unit instr-vec:sur) + ?~ unit ~ + `[%vec u.unit] + ?+ op ~ + %14 `[%swizzle ~] + %98 `[%popcnt ~] + :: [more SIMD opcodes...] + == +``` + +Maps SIMD/vector instruction opcodes to their corresponding vector instruction representations. Includes helper functions for different categories of vector operations: + +### `+nearest`, +sqrt, +div, +pmin, +pmax {#simd-float-ops} + +Floating-point vector operations with type-specific handling. + +### `+avgr`, +ceil, +floor {#simd-rounding-ops} + +Vector rounding and averaging operations. + +### `+all-true`, +bitmask {#simd-reduction-ops} + +Vector reduction operations that produce scalar results. + +### `+narrow`, +shl, +extadd, +convert {#simd-width-ops} + +Vector operations that change lane width or perform type conversions. + +### `+mul`, +splat, +eq, +ne, +abs, +neg, +trunc {#simd-basic-ops} + +Basic vector arithmetic and comparison operations. + +### `+lt`, +gt, +le, +ge {#simd-comparison-ops} + +Vector comparison operations with signed/unsigned variants. + +### `+shr`, +min, +max {#simd-minmax-ops} + +Vector shift and min/max operations. + +### `+add`, +sub {#simd-arithmetic-ops} + +Vector addition and subtraction with optional saturation. + +### `+extend`, +extmul {#simd-extend-ops} + +Vector lane extension and extended multiplication operations. + +Each SIMD operation handler correctly maps the opcode to the appropriate lane type and operation mode (signed/unsigned, saturation, etc.). From dce96a5c540bf65df842ba233c00b702914ea89c Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 11:14:37 +0100 Subject: [PATCH 29/57] Finish draft wasm parser --- .../reference/lib-wasm-parser.md | 94 +++++-------------- 1 file changed, 25 insertions(+), 69 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md index 457c6117..806835ee 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -1219,7 +1219,7 @@ Parse [`$global`](./wasm-data-types.md#global) variable with type, mutability, a ++ const-expr ;~(sfix const-instr end) :: single instruction ``` -Parse constant expression (single constant instruction followed by end). +Parse constant [`$expression`](./wasm-data-types.md#expression) (single constant instruction followed by end). ### `+const-instr` {#const-instr} @@ -1234,7 +1234,7 @@ Parse constant expression (single constant instruction followed by end). instr ``` -Parse instructions that can appear in constant expressions. +Parse [`$instruction`s](./wasm-data-types.md#instruction) that can appear in [constant instructions](./wasm-data-types.md#const-instr). ### `+export-section` {#export-section} @@ -1272,7 +1272,7 @@ Parse export entry with name and description. (stag ~ u32) ``` -Parse Wasm start section with start function index. +Parse Wasm module [`$start-section`](./wasm-data-types.md#start-section) with start function index. ### `+elem-section` {#elem-section} @@ -1282,7 +1282,7 @@ Parse Wasm start section with start function index. (vec elem) ``` -Parse Wasm element section for table initialization. +Parse Wasm module [`$elem-section`](./wasm-data-types.md#elem-section) for table initialization. ### `+elem` {#elem} @@ -1300,7 +1300,11 @@ Parse Wasm element section for table initialization. == ``` -Parse element segment in one of eight different formats (Wasm specification variations). +Parse element segment in one of eight different formats. Each format has different combinations of: +- Active/passive/declarative mode. +- Table index specification. +- Element type annotation. +- Initialization [`$expression`](./wasm-data-types.md#expression) vs [`$function`](./wasm-data-types.md#function-section) indices. ### `+elem-kind` {#elem-kind} @@ -1308,7 +1312,7 @@ Parse element segment in one of eight different formats (Wasm specification vari ++ elem-kind (just '\00') ``` -Parse element kind (currently only function references supported). +Parse element kind (currently only function references references supported). ### `+elem-0` through +elem-7 {#elem-variants} @@ -1320,11 +1324,7 @@ Parse element kind (currently only function references supported). == ``` -Parse different element segment formats. Each format has different combinations of: -- Active/passive/declarative mode -- Table index specification -- Element type annotation -- Initialization expression vs function indices +Parse different element segment formats. ### `+handle-elem-0` through +handle-elem-7 {#handle-elem-variants} @@ -1338,7 +1338,7 @@ Handler functions that convert parsed element data into the standard [`$elem`](. (vec code) ``` -Parse Wasm code section containing function implementations. +Parse Wasm module [`$code-section`](./wasm-data-types.md#code-section) containing function implementations. ### `+code` {#code} @@ -1366,7 +1366,7 @@ Parse function implementation with local variable declarations and body. ++ locals ;~(plug u32 valtype) ``` -Parse local variable declaration (count and type). +Parse local variable declaration (count and [`$valtype`](./wasm-data-types.md#valtype)). ### `+handle-locals` {#handle-locals} @@ -1389,7 +1389,7 @@ Expand compressed local variable declarations into full list. (vec data) ``` -Parse Wasm data section for memory initialization. +Parse Wasm module [`$data-section`](./wasm-data-types.md#data-section) section for memory initialization. ### `+data` {#data} @@ -1418,7 +1418,7 @@ Parse Wasm data section for memory initialization. == == == == ``` -Parse data segment in active or passive mode with initialization data. +Parse [`$data`](./wasm-data-types.md#data) segment in active or passive mode with initialization data. ### `+to-octs` {#to-octs} @@ -1430,7 +1430,7 @@ Parse data segment in active or passive mode with initialization data. (rep 3 tape) ``` -Convert tape to octets format. +Convert tape to `$octs` format. ### `+datacnt-section` {#datacnt-section} @@ -1440,7 +1440,7 @@ Convert tape to octets format. (stag ~ u32) ``` -Parse Wasm data count section. +Parse Wasm module [data count](./wasm-data-types.md#datacnt-section) section. ### `+module` {#module} @@ -1454,7 +1454,7 @@ Parse Wasm data count section. == ``` -Parse complete Wasm module with magic number, version, and sections. +Parse complete Wasm [`$module`](./wasm-data-types.md#module) with [`+magic`](#magic) number, [`+version`](#version), and sections. ### `+module-contents` {#module-contents} @@ -1476,7 +1476,7 @@ Parse complete Wasm module with magic number, version, and sections. == ``` -Parse module contents with all sections in order, allowing for missing optional sections. +Parse Wasm [`$module`](./wasm-data-types.md#module) contents. ### `+check` {#check} @@ -1494,7 +1494,7 @@ Parse module contents with all sections in order, allowing for missing optional == ``` -Check for optional section presence, providing default values for missing sections. +Check for optional Wasm module sections, providing default values for missing sections. ### `+customs` {#customs} @@ -1507,7 +1507,7 @@ Check for optional section presence, providing default values for missing sectio == ``` -Parse custom sections (ignored during parsing). +Parse custom Wasm module sections (ignored during parsing). ### `+magic` {#magic} @@ -1544,17 +1544,11 @@ Parse Wasm version number (currently version 1). %0xf `[%return ~] %0x1a `[%drop ~] %0x1b `[%select ~] - :: [more opcodes...] + :: ... == ``` -Maps single-byte Wasm opcodes to their corresponding [`$instruction`](./wasm-data-types.md#instruction) representations. Covers all basic Wasm instructions including: -- Control flow (`unreachable`, `nop`, `return`) -- Stack manipulation (`drop`, `select`) -- Arithmetic operations (`add`, `sub`, `mul`, `div`) -- Comparison operations (`eq`, `ne`, `lt`, `gt`, `le`, `ge`) -- Bitwise operations (`and`, `or`, `xor`, `shl`, `shr`) -- Type conversion operations (`extend`, `convert`, `reinterpret`) +Maps single-byte Wasm opcodes to their corresponding [`$instruction`](./wasm-data-types.md#instruction) representations. ## `+simd-map` {#simd-map} @@ -1570,46 +1564,8 @@ Maps single-byte Wasm opcodes to their corresponding [`$instruction`](./wasm-dat ?+ op ~ %14 `[%swizzle ~] %98 `[%popcnt ~] - :: [more SIMD opcodes...] + :: ... == ``` -Maps SIMD/vector instruction opcodes to their corresponding vector instruction representations. Includes helper functions for different categories of vector operations: - -### `+nearest`, +sqrt, +div, +pmin, +pmax {#simd-float-ops} - -Floating-point vector operations with type-specific handling. - -### `+avgr`, +ceil, +floor {#simd-rounding-ops} - -Vector rounding and averaging operations. - -### `+all-true`, +bitmask {#simd-reduction-ops} - -Vector reduction operations that produce scalar results. - -### `+narrow`, +shl, +extadd, +convert {#simd-width-ops} - -Vector operations that change lane width or perform type conversions. - -### `+mul`, +splat, +eq, +ne, +abs, +neg, +trunc {#simd-basic-ops} - -Basic vector arithmetic and comparison operations. - -### `+lt`, +gt, +le, +ge {#simd-comparison-ops} - -Vector comparison operations with signed/unsigned variants. - -### `+shr`, +min, +max {#simd-minmax-ops} - -Vector shift and min/max operations. - -### `+add`, +sub {#simd-arithmetic-ops} - -Vector addition and subtraction with optional saturation. - -### `+extend`, +extmul {#simd-extend-ops} - -Vector lane extension and extended multiplication operations. - -Each SIMD operation handler correctly maps the opcode to the appropriate lane type and operation mode (signed/unsigned, saturation, etc.). +Maps SIMD instruction opcodes to their corresponding [vector instruction](./wasm-data-types.md#instr-vec) representations. Includes helper functions for different categories of vector operations. From 67450809975aee02fc59ed9b6a2b883cc41496ed Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 11:15:43 +0100 Subject: [PATCH 30/57] Trim whitespace --- .../wasm-walkthrough/reference/lib-wasm-parser.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md index 806835ee..3e1dde5d 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -1324,7 +1324,7 @@ Parse element kind (currently only function references references supported). == ``` -Parse different element segment formats. +Parse different element segment formats. ### `+handle-elem-0` through +handle-elem-7 {#handle-elem-variants} From e36d8622ddaff8b51becc6567992fb070817fc2f Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 13:49:37 +0100 Subject: [PATCH 31/57] Draft wasm-validator docs --- .../reference/lib-wasm-validator.md | 745 +++++++++++++++++- 1 file changed, 717 insertions(+), 28 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md index 6d939a59..9260ab02 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md @@ -1,31 +1,720 @@ +# Wasm Validator -## /lib/wasm/validator +The `+validator` library validates WebAssembly modules for correctness according to the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/valid/index.html). It performs static analysis to ensure type safety, proper memory access, and correct control flow before execution. +The validator operates on parsed [`$module`](./wasm-data-types.md#module) structures from the [`+parser`](./lib-wasm-parser.md) core and provides error messages for invalid modules. + +## `+validator` {#validator} + +```hoon ++ validator - ++ output - ++ result-form - ++ result - ++ bind - ++ snug - ++ validate-module - ++ v-import-section - ++ validate-limits - ++ v-function-section - ++ v-table-section - ++ v-memory-section - ++ v-global-section - ++ v-export-section - ++ v-start-section - ++ v-elem-section - ++ v-datacnt-section - ++ v-code-section - ++ v-data-section - ++ validate-code - ++ validate-expr - ++ validate-instr - ++ get-type - ++ get-type-vec - ++ from-coin - ++ byte-width - ++ dim-lane - ++ unpack + =, wasm-sur + |% + +$ glob-type [v=valtype m=?(%con %var)] + +$ glob-types (list glob-type) + :: ... + -- +``` + +Core validator namespace. Exposes the nested `+wasm-sur` namespace and defines validator-specific types. + +## `$glob-type` {#glob-type} + +```hoon ++$ glob-type [v=valtype m=?(%con %var)] +``` + +Global variable type combining a [`$valtype`](./wasm-data-types.md#valtype) with mutability: +- `.v`: Value type of the global variable. +- `.m`: Mutability - `%con` for constant, `%var` for variable. + +## `$glob-types` {#glob-types} + +```hoon ++$ glob-types (list glob-type) +``` + +List of all global variable types. + +## `+output` {#output} + +```hoon +++ output + |% + +$ import + $: + funcs=(list func-type) :: flopped + tables=(list table) :: flopped + memo=(unit limits) + globs=glob-types :: flopped + == + -- +``` + +Validation output types. + +??? - why are they flopped? + +## `$import` {#import} + +```hoon ++$ import + $: + funcs=(list func-type) :: flopped + tables=(list table) :: flopped + memo=(unit limits) + globs=glob-types :: flopped + == +``` + +??? - why flopped? + +Aggregated import validation results: +- `.funcs`: List of imported function types. +- `.tables`: List of imported [`$table`s](./wasm-data-types.md#table). +- `.memo`: Optional imported memory [`$limits`](./wasm-data-types.md#limits). +- `.globs`: List of imported global types. + +## `$store` {#store} + +```hoon ++$ store import:output :: right order +``` + +Validation store containing all available types in the correct order for validation context. + +??? - why does order matter here? + +## `+result-form` {#result-form} + +```hoon +++ result-form + |$ [mold] + (each mold cord) +``` + +Generic result type parameterized by return type. Either a result of the given `$mold` or an error message cord. + +## `+result` {#result} + +```hoon +++ result + |* m2=mold + |% + +$ form $+(form (result-form m2)) + ++ bind + |* m1=mold + |= [a=(result-form m1) b=$-(m1 form)] + ^- form + ?: ?=(%| -.a) a + (b p.a) + -- +``` + +Monadic error handling system for validation. If the first validation fails, returns the error message; otherwise applies the continuation function. + +## `+snug` {#snug} + +```hoon +++ snug + |= where=cord + |* [a=@ b=(list)] + =/ r (result _?>(?=(^ b) i.b)) + |- ^- form:r + ?~ b |+(cat 3 'index error in ' where) + ?: =(a 0) &+i.b + $(a (dec a), b t.b) +``` + +Safe list indexing. Returns element at index `.a` in list `.b`, or an error message indicating the failure location. + +## `+validate-module` {#validate-module} + +```hoon +++ validate-module + |= m=module + =/ r (result ,~) + ^- form:r + ;< import-out=import:output bind:r (v-import-section m) + =/ n-funcs-import=@ (lent funcs.import-out) + ;< functypes=(list func-type) bind:r + (v-function-section m funcs.import-out) + ;< tables=(list table) bind:r (v-table-section m tables.import-out) + ;< memo=(unit limits) bind:r (v-memory-section m memo.import-out) + =/ n-funcs=@ (lent functypes) + =/ n-tables=@ (lent tables) + ;< =glob-types bind:r + (v-global-section m globs.import-out n-funcs) + =/ =store [functypes tables memo glob-types] + ;< ~ bind:r + %: v-export-section + m + n-funcs + n-tables + ?^(memo 1 0) + (lent glob-types) + == + ;< ~ bind:r (v-start-section m functypes) + ;< ~ bind:r (v-elem-section m n-tables functypes store) + ;< datacnt=(unit @) bind:r (v-datacnt-section m) + ;< ~ bind:r (v-code-section m n-funcs-import store) + (v-data-section m datacnt store) +:: +``` + +Main module validation function. Validates a [`$module`](./wasm-data-types.md#module) by sequentially checking all sections in dependency order. + +## `+v-import-section` {#v-import-section} + +```hoon +++ v-import-section + |= m=module + =| out=import:output + =/ num-types=@ (lent type-section.m) + =/ r (result import:output) + |- ^- form:r + ?~ import-section.m + &+out + ?- -.desc.i.import-section.m + %func + =/ idx=@ type-id.desc.i.import-section.m + ;< type=func-type bind:r ((snug 'import functype') idx type-section.m) + %= $ + import-section.m t.import-section.m + funcs.out [type funcs.out] + == + :: + %tabl + ?. (validate-limits q.t.desc.i.import-section.m) + |+'invalid limits import table' + =/ =table t.desc.i.import-section.m + $(import-section.m t.import-section.m, tables.out [table tables.out]) + :: + %memo + ?. (validate-limits l.desc.i.import-section.m) + |+'invalid limits import memo' + ?^ memo.out |+'multiple memos' + %= $ + import-section.m t.import-section.m + memo.out `l.desc.i.import-section.m + == + :: + %glob + %= $ + import-section.m t.import-section.m + globs.out [+.desc.i.import-section.m globs.out] + == + == +``` + +Validates the module's [`$import-section`](./wasm-data-types.md#import-section). Checks: +- Function imports reference valid type indices. +- Table imports have valid [`$limits`](./wasm-data-types.md#limits). +- At most one memory can be imported. +- Global imports have proper types. + +## `+validate-limits` {#validate-limits} + +```hoon +++ validate-limits + |= l=limits + ^- ? + ?- -.l + %flor & + %ceil (gte q.l p.l) + == +``` + +Validates [`$limits`](./wasm-data-types.md#limits) ensuring maximum is greater than or equal to minimum. + +## `+v-function-section` {#v-function-section} + +```hoon +++ v-function-section + |= [m=module functypes-import=(list func-type)] + =/ functypes=(list func-type) functypes-import + =/ r (result (list func-type)) + |- ^- form:r + ?~ function-section.m &+(flop functypes) + =/ idx=@ i.function-section.m + ;< type=func-type bind:r ((snug 'local functype') idx type-section.m) + %= $ + function-section.m t.function-section.m + functypes [type functypes] + == +``` + +Validates the [`$function-section`](./wasm-data-types.md#function-section) by checking that all function type indices reference valid entries in the type section. + +## `+v-table-section` {#v-table-section} + +```hoon +++ v-table-section + |= [m=module tables=(list table)] + =/ r (result (list table)) + ^- form:r + ?~ table-section.m &+(flop tables) + ?. (validate-limits q.i.table-section.m) |+'invalid limits local table' + $(table-section.m t.table-section.m, tables [i.table-section.m tables]) +``` + +Validates the [`$table-section`](./wasm-data-types.md#table-section) by checking table [`$limits`](./wasm-data-types.md#limits). + +## `+v-memory-section` {#v-memory-section} + +```hoon +++ v-memory-section + |= [m=module memo=(unit limits)] + =/ r (result (unit limits)) + ^- form:r + =/ len-memos=@ (lent memory-section.m) + ?: (gth len-memos 1) |+'multiple memos' + ?: &(?=(^ memo) (gth len-memos 0)) |+'multiple memos' + ?^ memo &+memo + ?: =(len-memos 0) &+~ + =/ lim=limits -.memory-section.m + ?. (validate-limits lim) |+'invalid limits local memory' + ?: &(?=(%ceil -.lim) (gth q.lim (bex 16))) |+'mem limit too big' + &+`-.memory-section.m +``` + +Validates the [`$memory-section`](./wasm-data-types.md#memory-section). Ensures: +- At most one memory is defined. +- Memory limits are valid. +- Maximum memory size doesn't exceed 2^16 pages (4GB). + +## `+v-global-section` {#v-global-section} + +```hoon +++ v-global-section + |= [m=module gt=glob-types n-funcs=@] + =/ n-glob-import=@ (lent gt) + =/ r (result glob-types) + |- ^- form:r + ?~ global-section.m &+(flop gt) + =/ glob i.global-section.m + ?- -.i.glob + %const + ?. =(v.glob -.p.i.glob) |+'global type mismatch' + $(global-section.m t.global-section.m, gt [[v m]:glob gt]) + :: + %vec + ?. ?=(%v128 v.glob) |+'global type mismatch' + $(global-section.m t.global-section.m, gt [[v m]:glob gt]) + :: + %ref-null + $(global-section.m t.global-section.m, gt [[v m]:glob gt]) + :: + %ref-func + ?: (gte func-id.i.glob n-funcs) |+'invalid funcref' + $(global-section.m t.global-section.m, gt [[v m]:glob gt]) + :: + %global-get + ?: (gte index.i.glob n-glob-import) + |+'non-import or nonexisting const global initializer' + $(global-section.m t.global-section.m, gt [[v m]:glob gt]) + == +``` + +Validates the [`$global-section`](./wasm-data-types.md#global-section). Checks: +- Initializer expressions match declared types. +- Function references are valid. +- Global references in initializers refer to imported constants. + +## `+v-export-section` {#v-export-section} + +```hoon +++ v-export-section + |= [m=module n-funcs=@ n-tables=@ n-memos=@ n-globs=@] + =| names=(set cord) + =/ r (result ,~) + |- ^- form:r + ?~ export-section.m &+~ + =/ exp i.export-section.m + ?: (~(has in names) name.exp) |+'name duplicate' + =; [i=@ num=@] + ?: (gte i num) |+'invalid export index' + $(export-section.m t.export-section.m, names (~(put in names) name.exp)) + ?- -.export-desc.exp + %func [i.export-desc.exp n-funcs] + %tabl [i.export-desc.exp n-tables] + %memo [i.export-desc.exp n-memos] + %glob [i.export-desc.exp n-globs] + == +``` + +Validates the [`$export-section`](./wasm-data-types.md#export-section). Checks: +- Export names are unique. +- Export indices are within bounds for their respective types. + +## `+v-start-section` {#v-start-section} + +```hoon +++ v-start-section + |= [m=module functypes=(list func-type)] + =/ r (result ,~) + ^- form:r + ?~ start-section.m &+~ + =/ func-idx=@ u.start-section.m + ;< type=func-type bind:r ((snug 'start section') func-idx functypes) + ?. ?=([~ ~] type) + |+'non-void start function' + &+~ +``` + +Validates the [`$start-section`](./wasm-data-types.md#start-section) ensuring the start function has no parameters and no return values. + +## `+v-elem-section` {#v-elem-section} + +```hoon +++ v-elem-section + :: elems are additionaly restricted by the parser: offset + :: expression is limited to a single const instruction, + :: and init expression are limited to a single %ref* instruction + :: + |= [m=module n-tables=@ functypes=(list func-type) =store] + =/ r (result ,~) + ^- form:r + ?~ elem-section.m &+~ + =/ elem i.elem-section.m + ;< ~ bind:r + =/ r (result ,~) + |- ^- form:r + ?~ i.elem &+~ + ?: ?=(%ref-null -.i.i.elem) + ?: =(t.elem t.i.i.elem) $(i.elem t.i.elem) + |+'%ref-null type mismatch in element' + ?. ?=(%func t.elem) |+'%ref-null type mismatch in element' + =/ idx=@ func-id.i.i.elem + ;< * bind:r ((snug 'elem section funcref') idx functypes) + $(i.elem t.i.elem) + ?. ?=(%acti -.m.elem) $(elem-section.m t.elem-section.m) + ?: (gte tab.m.elem n-tables) |+'element index error' + :: ?. ?=(%i32 -.p.off.m.elem) |+'type error in element offset' + ?: ?=(?(%ref-null %ref-func %vec) -.off.m.elem) + |+'type error in element offset' + ?: ?=(%const -.off.m.elem) + ?. ?=(%i32 -.p.off.m.elem) |+'type error in element offset' + $(elem-section.m t.elem-section.m) + :: %global-get + ;< glob=glob-type bind:r + ((snug 'global section') index.off.m.elem globs.store) + ?. ?=(%i32 v.glob) |+'type error in element offset' + $(elem-section.m t.elem-section.m) +``` + +Validates the [`$elem-section`](./wasm-data-types.md#elem-section). Checks: +- Element initializers match table reference types. +- Function references are valid. +- Table indices are within bounds. +- Offset expressions have correct types. + +## `+v-datacnt-section` {#v-datacnt-section} + +```hoon +++ v-datacnt-section + |= m=module + =/ r (result (unit @)) + ^- form:r + &+datacnt-section.m +``` + +Returns the data count section, no additional validation needed. + +## `+v-code-section` {#v-code-section} + +```hoon +++ v-code-section + |= $: m=module + n-funcs-import=@ + =store + == + ?. =((lent code-section.m) (lent function-section.m)) + |+'mismatching lengths of function and code sections' + =/ idx=@ n-funcs-import + =/ r (result ,~) + |- ^- form:r + ?~ code-section.m &+~ + ;< type=func-type bind:r ((snug 'code section') idx funcs.store) + ;< ~ bind:r (validate-code idx i.code-section.m type m store) + $(idx +(idx), code-section.m t.code-section.m) +``` + +Validates the [`$code-section`](./wasm-data-types.md#code-section). Checks: +- Code and function sections have matching lengths. +- Each function body validates against its declared type. + +## `+v-data-section` {#v-data-section} + +```hoon +++ v-data-section + :: data section is additionaly restrained by the parser: + :: offset expression may only be a single const instruction + :: + |= [m=module datacnt=(unit @) =store] + =/ r (result ,~) + ^- form:r + ?: &(?=(^ datacnt) !=(u.datacnt (lent data-section.m))) + |+'wrong datacnt' + |- ^- form:r + ?~ data-section.m + &+~ + =/ data i.data-section.m + ?: ?=(%pass -.data) + $(data-section.m t.data-section.m) + ?~ memo.store |+'no memory to copy data to' + ?: ?=(%const -.off.data) + ?. ?=(%i32 -.p.off.data) |+'type error in data offset' + $(data-section.m t.data-section.m) + ?: ?=(?(%ref-null %ref-func %vec) -.off.data) + |+'type error in data offset' + :: global-get + ;< glob=glob-type bind:r + ((snug 'global-section') index.off.data globs.store) + ?. ?=(%i32 v.glob) |+'type error in data offset' + $(data-section.m t.data-section.m) +``` + +Validates the [`$data-section`](./wasm-data-types.md#data-section). Checks: +- Data count matches actual data segments. +- Memory exists for active data segments. +- Offset expressions have correct types. + +## `+validate-code` {#validate-code} + +```hoon +++ validate-code + |= $: idx=@ + =code + type=func-type + =module + =store + == + =/ r (result ,~) + ^- form:r + =/ locals (weld params.type locals.code) + =/ stack=(list valtype) ~ + =/ frames=(list (list valtype)) ~[results.type] + =/ res + %: validate-expr + expression.code + module + store + locals + stack + frames + == + ?- -.res + %& res + %| |+(rap 3 'func ' (scot %ud idx) ': ' p.res ~) + == +``` + +Validates a single function's [`$code`](./wasm-data-types.md#code) against its expected [`$func-type`](./wasm-data-types.md#func-type). Sets up the validation context with parameters and local variables, then validates the function body. + +## `+validate-expr` {#validate-expr} + +```hoon +++ validate-expr + |= $: expr=expression + =module + =store + $= args + $: locals=(list valtype) + stack=(list valtype) + frames=(list (list valtype)) + == == + =/ r (result ,~) + ^- form:r + ?~ expr + ?. =(-.frames.args (flop stack.args)) + ~& [frames.args (flop stack.args)] + |+'type error in result' + &+~ + =/ instr i.expr + :: stack-polymorphic instructions (unconditional control transfer) + :: + ?: ?=(%unreachable -.instr) &+~ + ?: ?=(%br -.instr) + ;< results=(list valtype) bind:r + ((snug 'br frames') label.instr frames.args) + ?. =(results (flop (scag (lent results) stack.args))) |+'br type error' + &+~ + ?: ?=(%br-table -.instr) + =/ labels=(list @) [label-default label-vec]:instr + ?. =(%i32 -.stack.args) |+'br-table index type error' + =. stack.args +.stack.args + |- ^- form:r + ?~ labels &+~ + ;< results=(list valtype) bind:r + ((snug 'br-table frames') i.labels frames.args) + ?. =(results (flop (scag (lent results) stack.args))) + |+'br-table type error' + $(labels t.labels) + ?: ?=(%return -.instr) + ?: =(~ frames.args) |+'no frames' + =/ results=(list valtype) (rear frames.args) + ?. =(results (flop (scag (lent results) stack.args))) + |+'return type error' + &+~ + ;< [stack1=_stack.args] bind:r + (validate-instr instr module store args) + $(expr t.expr, stack.args stack1) +``` + +Validates an [`$expression`](./wasm-data-types.md#expression) (sequence of instructions) within a given context. Validates: +- Local variable types. +- Stack type state. +- Control flow frames for branch validation. + +Handles stack-polymorphic instructions (`unreachable`, `br`, `br-table`, `return`) specially as they don't return normally. + +## `+validate-instr` {#validate-instr} + +```hoon +++ validate-instr + |= $: $= instr + $~ [%nop ~] + $<(?(%unreachable %br %br-table %return) instruction) + :: + =module + =store + locals=(list valtype) + stack=(pole valtype) + frames=(list (list valtype)) + == + =/ r (result _stack) + ^- form:r + :: ... +``` + +Validates a single [`$instruction`](./wasm-data-types.md#instruction) against the current stack and context. Handles: +- Value-polymorphic instructions (`drop`, `select`). +- Block instructions (`block`, `loop`, `if`). +- Control flow instructions (`br-if`, `call`, `call-indirect`). +- Reference instructions (`ref-is-null`). + +For most instructions, delegates to [`+get-type`](#get-type) to determine the instruction's type signature. + +## `+get-type` {#get-type} + +```hoon +++ get-type + |= $: $= instr + $~ [%nop ~] + $< $? %unreachable + %br + %br-table + %return + %drop + %select + %block + %loop + %if + %br-if + %call + %call-indirect + %ref-is-null + == + instruction + :: + =module + =store + locals=(list valtype) + == + ~+ + =/ r (result func-type) + ^- form:r + ?- -.instr + :: ... + == +``` + +Returns the type signature of an [`$instruction`](./wasm-data-types.md#instruction) as a [`$func-type`](./wasm-data-types.md#func-type) (parameter types and result types). Handles: +- Constant instructions (`const`). +- Unary numeric operations (`eqz`, `clz`, `ctz`, `popcnt`, `abs`, `neg`, etc.). +- Binary numeric operations (`add`, `sub`, `mul`, `div`, `rem`, etc.). +- Comparison operations (`eq`, `ne`, `lt`, `gt`, `le`, `ge`). +- Reference operations (`ref-null`, `ref-func`). +- Variable operations (`local-get`, `local-set`, `local-tee`, `global-get`, `global-set`). +- Table operations (`table-get`, `table-set`, `table-init`, etc.). +- Memory operations (`load`, `store`, `memory-size`, `memory-grow`, etc.). +- Vector instructions (delegated to [`+get-type-vec`](#get-type-vec)). + +## `+get-type-vec` {#get-type-vec} + +```hoon +++ get-type-vec + |= [instr=instr-vec =module =store] + =/ r (result func-type) + ^- form:r + ?- -.instr + :: ... + == +``` + +Returns the type signature for SIMD vector instructions. Handles: +- Vector memory operations (`load`, `store`, `load-lane`, `store-lane`). +- Vector constants and manipulation (`const`, `shuffle`, `extract`, `replace`). +- Vector logical operations (`swizzle`, `splat`). +- Vector comparison and arithmetic operations. +- Vector conversion operations. + +## `+from-coin` {#from-coin} + +```hoon +++ from-coin + |= coin=coin-wasm + ^- valtype + ?- -.coin + valtype -.coin + %ref +<.coin + == +``` + +Extracts the [`$valtype`](./wasm-data-types.md#valtype) from a [`$coin-wasm`](./wasm-data-types.md#coin-wasm). + +## `+byte-width` {#byte-width} + +```hoon +++ byte-width + |= v=?(num-type vec-type) + ^- @ + ?- v + ?(%i32 %f32) 4 + ?(%i64 %f64) 8 + %v128 16 + == +``` + +Returns the byte width of a numeric or vector type. + +## `+dim-lane` {#dim-lane} + +```hoon +++ dim-lane + |= l=lane-type + ^- @ + ?- l + %i8 16 + %i16 8 + ?(%i32 %f32) 4 + ?(%i64 %f64) 2 + == +``` + +Returns the number of lanes in a 128-bit vector for the given [`$lane-type`](./wasm-data-types.md#lane-type). + +## `+unpack` {#unpack} + +```hoon +++ unpack + |= l=lane-type + ^- num-type + ?- l + num-type l + ?(%i8 %i16) %i32 + == +``` + +Converts a [`$lane-type`](./wasm-data-types.md#lane-type) to its corresponding [`$num-type`](./wasm-data-types.md#num-type), promoting `%i8` and `%i16` to `%i32`. From 930bcb22b592c25dadb73915bca60168292074bd Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 15:15:29 +0100 Subject: [PATCH 32/57] Draft op-def docs --- .../reference/lib-wasm-runner-op-def.md | 793 +++++++++++++++--- 1 file changed, 670 insertions(+), 123 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md index 2687c631..cd514899 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md @@ -1,126 +1,673 @@ +# Wasm Runner Op-Def -## /lib/wasm/runner/op-def +The `/lib/wasm/runner/op-def` library implements WebAssembly instruction definitions as functions that transform the [`$local-state`](./wasm-interpreter-data-types.md#local-state) of the UrWasm interpreter. This library serves as the operational semantics for WebAssembly instructions, defining how each instruction modifies the interpreter's execution state. +## `+op-def` {#op-def} + +```hoon ++ op-def - ++ mayb - ++ sure - ++ torn - ++ lane-size - ++ fuse :: from \~paldev - ++ chap - ++ page-size ^\~((bex 16)) - ++ place - ++ lim-min - ++ lim-max - ++ lte-lim - ++ change - ++ to-si - ++ en-si - ++ sat - ++ coin-to-val - ++ val-to-coin - ++ snug - ++ shot - ++ buy - ++ grab - ++ func - ++ table - ++ memo - ++ glob - ++ mem-store - ++ mem-load - ++ kind - ++ fetch-gate - ++ fetch - ++ dbug - ++ print-tee - ++ select - ++ null - ++ unreachable - ++ nop |=(local-state +<) - ++ return - ++ drop - ++ ref - ++ ref-null - ++ ref-is-null - ++ ref-func - ++ load - ++ store - ++ const - ++ get - ++ set - ++ branch - ++ table - ++ table-get - ++ table-set - ++ table-init - ++ elem-drop - ++ table-copy - ++ table-grow - ++ table-size - ++ table-fill - ++ memo - ++ memory-size - ++ memory-grow - ++ memory-init - ++ data-drop - ++ memory-copy - ++ memory-fill - ++ unar - ++ clz - ++ ctz - ++ popcnt - ++ abs - ++ neg - ++ sqrt - ++ ceil - ++ floor - ++ trunc - ++ nearest - ++ eqz - ++ wrap - ++ extend - ++ convert - ++ demote - ++ promote - ++ reinterpret - ++ bina - ++ add - ++ sub - ++ mul - ++ div - ++ rem - ++ and - ++ or - ++ xor - ++ shl - ++ shr - ++ rotl - ++ rotr - ++ min - ++ max - ++ copysign - ++ eq - ++ ne - ++ lt - ++ gt - ++ le - ++ ge - ++ simd - ++ rope - ++ fetch-vec - ++ load - ++ load-lane - ++ store - ++ store-lane - ++ const - ++ shuffle - ++ extract - ++ replace - ++ plain - ++ kind - ++ vec-unar - ++ vec-bina - ++ get-op-unar - ++ get-op-bina - ++ get-size + =, engine-sur + |% + :: ... + -- +``` + +Core instruction definitions namespace. Implements WebAssembly instructions as gates that transform [`$local-state`](./wasm-interpreter-data-types.md#local-state) to [`$local-state`](./wasm-interpreter-data-types.md#local-state). Uses round-to-nearest ties-to-even semantics for floating-point operations except where otherwise specified. + +## `+mayb` {#mayb} + +```hoon +++ mayb + |* gat=$-(* *) + |: a=+6.gat + ^- (unit _$:gat) + `(gat a) +``` + +Wrap output of a gate in a unit. + +## `+sure` {#sure} + +```hoon +++ sure + |* gat=$-(* (unit)) + |* a=_+6.gat + (need (gat a)) +``` + +Unwrap output of gate, crashing if unit is empty. + +## `+torn` {#torn} + +```hoon +++ torn + |* [a=(list) b=$-(* (unit))] + =| l=(list _(need $:b)) + |- ^- (unit (list _(need $:b))) + ?~ a `(flop l) + =+ c=(b i.a) + ?~ c ~ + $(a t.a, l [u.c l]) +``` + +Map a list with a gate, collapsing units. Returns `~` if any application produces `~`. + +## `+lane-size` {#lane-size} + +```hoon +++ lane-size + |= lt=lane-type + ^- @ + (slav %ud (rsh 3 lt)) +``` + +Extract the bit size from a [`$lane-type`](./wasm-data-types.md#lane-type). + +## `+fuse` {#fuse} + +```hoon +++ fuse + |* [a=(list) b=(list)] + ^- (list [_?>(?=(^ a) i.a) _?>(?=(^ b) i.b)]) + ?~ a ~ + ?~ b ~ + :- [i.a i.b] + $(a t.a, b t.b) +``` + +Zip two lists together, stopping when either list is exhausted. + +## `+chap` {#chap} + +```hoon +++ chap + |= [l=local-state instr=$-(local-state local-state)] + ^- local-state + ?^ br.stack.l l + (instr l) +``` + +Check branching signal and conditionally apply instruction. If there's a branch signal in the local state, return unchanged; otherwise apply the instruction. + +## `+page-size` {#page-size} + +```hoon +++ page-size ^~((bex 16)) +``` + +WebAssembly memory page size (65,536 bytes). + +## `+place` {#place} + +```hoon +++ place + |* [a=(list) off=@ b=(list)] + |- ^+ b + ?~ b a + ?> (lth off (lent a)) + $(a (shot a off i.b), b t.b, off +(off)) +``` + +Place list `.b` into list `.a` starting at offset `.off`, overwriting contents of `.a`. + +## `+lim-min` {#lim-min} + +```hoon +++ lim-min + |= l=limits + ^- @ + ?: ?=(%flor -.l) + p.l + p.l +``` + +Extract minimum value from [`$limits`](./wasm-data-types.md#limits). + +## `+lim-max` {#lim-max} + +```hoon +++ lim-max + |= l=limits + ^- (unit @) + ?: ?=(%flor -.l) + ~ + `q.l +``` + +Extract maximum value from [`$limits`](./wasm-data-types.md#limits). Returns `~` if no maximum is specified. + +## `+lte-lim` {#lte-lim} + +```hoon +++ lte-lim + |= [a=@ l=limits] + ^- ? + ?: ?=(%flor -.l) + & + (lte a q.l) +``` + +Test if value `.a` is within the specified [`$limits`](./wasm-data-types.md#limits). + +## `+change` {#change} + +```hoon +++ change + |= [a=(list valtype) b=(list val)] + ^- (list coin-wasm) + ?. &(?=(^ a) ?=(^ b)) + ?> &(?=(~ a) ?=(~ b)) + ~ + :_ $(a t.a, b t.b) + ;; coin-wasm + ?- i.a + ?(num-type vec-type) + [i.a ?>(?=(@ i.b) i.b)] + :: + %extn + ?>(?=([%ref %extn ~] i.b) i.b) + :: + %func + ?>(?=([%ref %func *] i.b) i.b) + == +``` + +Convert stack values to a list of [`$coin-wasm`](./wasm-data-types.md#coin-wasm) for type checking. + +## `+to-si` {#to-si} + +```hoon +++ to-si + |= [base=@ n=@] + ^- @s + =. n (mod n (bex base)) + =/ sign=? (lth n (bex (dec base))) + %+ new:si sign + ?: sign n + (sub (bex base) n) +``` + +Convert unsigned integer to signed integer with specified bit width. + +## `+en-si` {#en-si} + +```hoon +++ en-si + |= [base=@ s=@s] + ^- @ + ?: (syn:si s) + +:(old:si s) + (sub (bex base) +:(old:si s)) +``` + +Convert signed integer to unsigned integer with specified bit width. + +## `+sat` {#sat} + +```hoon +++ sat + |= [size=@ s=@s mode=?(%u %s)] + ^- @ + =, si + =; sat-s=@s + (en-si size sat-s) + ?: =(%u mode) + ?: =(--1 (cmp s (sum (new & (bex size)) -1))) + (sum (new & (bex size)) -1) + ?: =(-1 (cmp s --0)) + --0 + s + ?: =(--1 (cmp s (sum (new & (bex (dec size))) -1))) + (sum (new & (bex (dec size))) -1) + ?: =(-1 (cmp s (new | (bex (dec size))))) + (new | (bex (dec size))) + s +``` + +Saturating conversion from signed integer with specified size and mode (`%u` for unsigned, `%s` for signed). + +## `+coin-to-val` {#coin-to-val} + +```hoon +++ coin-to-val + |= c=coin-wasm + ^- val + ?: ?=(%ref -.c) + c + ?- -.c + ?(%i32 %f32) (mod +.c ^~((bex 32))) + ?(%i64 %f64) (mod +.c ^~((bex 64))) + %v128 (mod +.c ^~((bex 128))) + == +``` + +Convert [`$coin-wasm`](./wasm-data-types.md#coin-wasm) to interpreter [`$val`](./wasm-interpreter-data-types.md#val). + +## `+val-to-coin` {#val-to-coin} + +```hoon +++ val-to-coin + |= [v=val ex=coin-wasm] + ^- coin-wasm + ?@ v + ?< ?=(%ref -.ex) + ;; coin-wasm + [-.ex v] + ?> ?=(%ref -.ex) + ?> =(+<.v +<.ex) :: assert: same reftypes + v +``` + +Convert interpreter [`$val`](./wasm-interpreter-data-types.md#val) to [`$coin-wasm`](./wasm-data-types.md#coin-wasm) using expected type. + +## `+snug` {#snug} + +```hoon +++ snug + |* [a=@ b=(list)] + |- ^- (unit _?>(?=(^ b) i.b)) + ?~ b ~ + ?: =(0 a) `i.b + $(b t.b, a (dec a)) +``` + +Unitized list indexing. Returns element at index `.a` or `~` if index is out of bounds. + +## `+shot` {#shot} + +```hoon +++ shot + |* [a=(list) b=@ c=*] + ^+ a + ?> (lth b (lent a)) + (snap a b c) +``` + +Replace existing item in a list at index `.b` with value `.c`. + +## `+buy` {#buy} + +```hoon +++ buy + |= [l=local-state req=[[mod=cord name=cord] =request] type=(list valtype)] + ^- local-state + ?~ shop.store.l + =, store.l + l(br.stack [%bloq req module mem tables globals]) + =/ valid-types=? + =/ res=(list coin-wasm) p.i.shop.store.l + |- ^- ? + ?: &(?=(~ res) ?=(~ type)) & + ?> &(?=(^ res) ?=(^ type)) + ?& =(-.i.res i.type) + $(res t.res, type t.type) + == + ?> valid-types + %= l + va.stack + %+ weld + %- flop + (turn p.i.shop.store.l coin-to-val) + va.stack.l + :: + store + =, store.l + [t.shop q.i.shop] + == +``` + +Resolve import. If no values are available in the `.shop`, creates a request and blocks execution. Otherwise, validates types and pushes values onto the stack. + +## `+grab` {#grab} + +```hoon +++ grab + |% + ++ func + |= [id=@ st=store] + ^- (each function [[mod=cord name=cord] type-id=@]) + =, import-section.module.st + =+ imp=(snug id funcs) + ?^ imp [%| u.imp] + :- %& + (snag (sub id (lent funcs)) function-section.module.st) + :: + ++ table + |= [id=@ st=store] + ^- %+ each (pair @ (list $>(%ref coin-wasm))) + [[mod=cord name=cord] t=^table] + =, import-section.module.st + =+ imp=(snug id tables) + ?^ imp [%| u.imp] + :- %& + =+ idx=(sub id (lent tables)) + :- idx + (snag idx tables.st) + :: + ++ memo + |= [id=@ st=store] + ^- %+ each [buffer=@ n-pages=@] + [[mod=cord name=cord] l=limits] + =, import-section.module.st + =+ imp=(snug id memos) + ?^ imp [%| u.imp] + [%& (need mem.st)] + :: + ++ glob + |= [id=@ st=store] + ^- %+ each (pair @ coin-wasm) + [[mod=cord name=cord] v=valtype m=?(%con %var)] + =, import-section.module.st + =+ imp=(snug id globs) + ?^ imp [%| u.imp] + :- %& + =+ idx=(sub id (lent globs)) + :- idx + (snag idx globals.st) + :: + -- +``` + +Import resolution utilities. Each arm returns either a local instance of an object or its external reference. +- `+func`: Resolve function by index. +- `+table`: Resolve table by index. Returns either a local table with its contents or an external reference. +- `+memo`: Resolve memory by index. Returns either local memory instance or an external reference. +- `+glob`: Resolve global variable by index. Returns either local global value or an external reference. + +## `+mem-store` {#mem-store} + +```hoon +++ mem-store + |= [index=@ size=@ content=@ buffer=@ n-pages=@] + ^- (unit [buffer=@ n-pages=@]) + ?. (lte (add index size) (mul n-pages page-size)) + ~ + `[(sew 3 [index size content] buffer) n-pages] +``` + +Store data in linear memory at the specified index. Returns updated memory or `~` if out of bounds. + +## `+mem-load` {#mem-load} + +```hoon +++ mem-load + |= [index=@ size=@ buffer=@ n-pages=@] + ^- (unit @) + ?. (lte (add index size) (mul n-pages page-size)) + ~ + `(cut 3 [index size] buffer) +``` + +Load data from linear memory at the specified index. Returns data or `~` if out of bounds. + +## `+kind` {#kind} + +```hoon +++ kind + |% + +$ nullary $? %unreachable %nop %return %drop == + +$ ref ?(%ref-null %ref-is-null %ref-func) + +$ get ?(%global-get %local-get) + +$ set ?(%global-set %local-set %local-tee) + +$ branch ?(%br %br-if %br-table) + +$ table $? %table-get %table-set %table-init %elem-drop + %table-copy %table-grow %table-size %table-fill == + +$ memo $? %memory-size %memory-grow %memory-init %data-drop + %memory-copy %memory-fill == + +$ unary-num $? %clz %ctz %popcnt %abs %neg %sqrt %ceil %floor + %trunc %nearest %eqz %wrap %extend %convert + %demote %promote %reinterpret == + +$ binary-num $? %add %sub %mul %div %rem %and %or %xor %shl %shr + %rotl %rotr %min %max %copysign %eq %ne %lt %gt + %le %ge == + -- +``` + +Instruction category types for organizing instruction implementations. + +## `+fetch-gate` {#fetch-gate} + +```hoon +++ fetch-gate + |= i=$<(?(%call %loop %call-indirect %block %if) instruction) + ^- $-(local-state local-state) + ?- -.i + %vec (simd +.i) + nullary:kind (null:fetch i) + ref:kind (ref:fetch i) + %load (load:fetch i) + %store (store:fetch i) + %const (const:fetch i) + get:kind (get:fetch i) + set:kind (set:fetch i) + branch:kind (branch:fetch i) + table:kind (table:fetch i) + memo:kind (memo:fetch i) + %select select:fetch + %dbug (dbug:fetch i) + :: + unary-num:kind + |= l=local-state + ^- local-state + ?> ?=([a=@ rest=*] va.stack.l) + =, va.stack.l + =+ val=((unar:fetch i) a) + ?~ val l(br.stack [%trap ~]) + l(va.stack [u.val rest]) + :: + binary-num:kind + |= l=local-state + ^- local-state + ?> ?=([b=@ a=@ rest=*] va.stack.l) + =, va.stack.l + =+ val=((bina:fetch i) a b) + ?~ val l(br.stack [%trap ~]) + l(va.stack [u.val rest]) + :: + == +``` + +Convert [`$instruction`](./wasm-data-types.md#instruction) to a gate that transforms local state. Handles different instruction categories appropriately. + +## `+fetch` {#fetch} + +```hoon +++ fetch + |% + ++ dbug :: Debug instructions + ++ select :: Parametric instructions + ++ null :: Control instructions with no operands + ++ ref :: Reference instructions + ++ load :: Memory load instructions + ++ store :: Memory store instructions + ++ const :: Constant instructions + ++ get :: Variable get instructions + ++ set :: Variable set instructions + ++ branch :: Branch instructions + ++ table :: Table instructions + ++ memo :: Memory instructions + ++ unar :: Unary numeric instructions + ++ bina :: Binary numeric instructions + -- +``` + +Core with instruction implementation definitions. Each arm contains implementations for specific categories of WebAssembly instructions. + +### `+dbug:fetch` {#dbug-fetch} + +```hoon +++ dbug + =- |= i=instruction + ((~(got by m) ;;(@tas +<.i)) i) + ^~ + ^= m + ^- (map @tas $-(instruction $-(local-state local-state))) + |^ + %- my + :~ print-tee+print-tee == + ++ print-tee + |= i=instruction + ?> ?=([%dbug %print-tee a=term] i) + |= l=local-state + ^- local-state + ~& [a.i ;;(@ux -.va.stack.l)] + l + -- +``` + +Debug instruction implementations. Currently supports `%print-tee` which prints the top stack value with a label. + +### `+select:fetch` {#select-fetch} + +```hoon +++ select + |= l=local-state + ^- local-state + ?> ?=([which=@ val2=* val1=* rest=*] va.stack.l) + =, va.stack.l + %= l + va.stack + [?.(=(0 which) val1 val2) rest] + == +``` + +Select instruction. Pops condition and two values, pushes the chosen value based on the condition. + +### `+null:fetch` {#null-fetch} + +```hoon +++ null + =- |= i=instruction + (~(got by m) ;;(@tas -.i)) + ^~ + ^= m + ^- (map @tas $-(local-state local-state)) + |^ + %- my + :~ + unreachable+unreachable + nop+nop + return+return + drop+drop + == + ++ unreachable + |= l=local-state + ^- local-state + l(br.stack [%trap ~]) + ++ nop |=(local-state +<) + ++ return + |= l=local-state + ^- local-state + l(br.stack [%retr ~]) + ++ drop + |= l=local-state + ^- local-state + l(va.stack +.va.stack.l) + -- +``` + +Control instructions with no operands: +- `unreachable`: Unconditionally trap. +- `nop`: No operation. +- `return`: Return from function. +- `drop`: Drop top value from stack. + +### `+ref:fetch` {#ref-fetch} + +```hoon +++ ref + =- |= i=instruction + ?> ?=(ref:kind -.i) + ^- $-(local-state local-state) + ((~(got by m) ;;(@tas -.i)) i) + ^~ + ^= m + ^- (map @tas $-(instruction $-(local-state local-state))) + |^ + %- my + :~ + ref-null+ref-null + ref-is-null+ref-is-null + ref-func+ref-func + == + ++ ref-null + |= i=instruction + ?> ?=(%ref-null -.i) + |= l=local-state + ^- local-state + %= l + va.stack + :_ va.stack.l + :- %ref + ?- t.i + %extn [%extn ~] + %func [%func ~] + == + == + ++ ref-is-null + |= * + |= l=local-state + ^- local-state + ?> ?=([ref=[%ref *] rest=*] va.stack.l) + =, va.stack.l + =/ out=@ + ?@(+>.ref 1 0) + l(va.stack [out rest]) + ++ ref-func + |= i=instruction + ?> ?=(%ref-func -.i) + |= l=local-state + ^- local-state + l(va.stack [[%ref %func ~ func-id.i] va.stack.l]) + -- +``` + +Reference instruction implementations: +- `ref-null`: Push null reference of specified type. +- `ref-is-null`: Test if reference is null. +- `ref-func`: Push function reference. + +## `+simd` {#simd} + +```hoon +++ simd + |= iv=instr-vec + ^- $-(local-state local-state) + :: Implementation details for SIMD vector instructions +``` + +SIMD vector instruction implementations for 128-bit vectors. Handles vector load/store operations, lane manipulation, and parallel arithmetic operations on packed data. + +The SIMD implementation includes: + +### `+rope` {#rope} + +Helper functions for vector operation utilities. + +### `+fetch-vec` {#fetch-vec} + +Vector instruction dispatcher that routes to specific vector operation implementations. + +### Vector Memory Operations + +- `load`: Load vector from memory with optional splat/zero-extend/sign-extend +- `load-lane`: Load single value into specific lane +- `store`: Store vector to memory +- `store-lane`: Store single lane to memory + +### Vector Manipulation + +- `const`: Vector constant values +- `shuffle`: Rearrange lanes by index list +- `extract`: Get value from specific lane +- `replace`: Set value in specific lane + +### Vector Arithmetic + +- `plain`: Plain vector operations including: + - `kind`: Categorize vector operation types + - `vec-unar`: Unary vector operations + - `vec-bina`: Binary vector operations + - `get-op-unar`: Resolve unary operation implementations + - `get-op-bina`: Resolve binary operation implementations + - `get-size`: Extract size information from vector types From cccd2d8a74d91416ad0c372580bdbb1cab51356f Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 15:30:08 +0100 Subject: [PATCH 33/57] Draft op-def docs --- .../reference/lib-wasm-runner-op-def.md | 471 +++++++++++++++++- 1 file changed, 446 insertions(+), 25 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md index cd514899..3c7b6c03 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md @@ -631,43 +631,464 @@ Reference instruction implementations: ```hoon ++ simd - |= iv=instr-vec - ^- $-(local-state local-state) - :: Implementation details for SIMD vector instructions + =< fetch-vec + |% + :: ++rope: ++rip but with leading zeros. + :: Takes bloq size, number of blocks and + :: an atom to dissasemble + :: + :: ... + -- ``` -SIMD vector instruction implementations for 128-bit vectors. Handles vector load/store operations, lane manipulation, and parallel arithmetic operations on packed data. +{TODO include comments with +foo, +bar arms in code sample above? did that in another file and i quite like that convention; you get a low-res picture of the whole thing at once to fill in as you read, easier to navigate} -The SIMD implementation includes: +SIMD vector instruction implementations for 128-bit vectors. Handles vector load/store operations, lane manipulation, and parallel arithmetic operations on packed data. ### `+rope` {#rope} -Helper functions for vector operation utilities. +```hoon +++ rope + |= [b=bloq s=step a=@] + ^- (list @) + ?: =(s 0) ~ + :- (end b a) + $(a (rsh b a), s (dec s)) +``` + +Helper for dissembling atoms with leading zeros. Similar to `+rip` but takes a specific number of blocks to extract. ### `+fetch-vec` {#fetch-vec} -Vector instruction dispatcher that routes to specific vector operation implementations. +```hoon +++ fetch-vec + |= i=instr-vec + ^- $-(local-state local-state) + ?+ -.i (plain i) + %load (load i) + %load-lane (load-lane i) + %store (store i) + %store-lane (store-lane i) + :: + %const (const i) + %shuffle (shuffle i) + %extract (extract i) + %replace (replace i) + :: + == +``` + +Vector instruction dispatcher that routes [`$instr-vec`](./wasm-data-types.md#instr-vec) to specific vector operation implementations. + +### `+load` {#load} + +```hoon +++ load + |= i=instr-vec + ?> ?=(%load -.i) + |= l=local-state + ^- local-state + ?> ?=([addr=@ rest=*] va.stack.l) + =, va.stack.l + =/ index=@ (add addr offset.m.i) + =+ mem=(memo:grab 0 store.l) + ?: ?=(%| -.mem) + %^ buy l(va.stack rest) + :* -.p.mem + %memo + (change ~[%i32] ~[addr]) + [%vec i] + == + ~[%v128] + ?~ kind.i + =+ loaded=(mem-load index 16 p.mem) + ?~ loaded l(br.stack [%trap ~]) + l(va.stack [u.loaded rest]) + ?- q.u.kind.i + [%extend p=?(%s %u)] + =; loaded=(unit @) + ?~ loaded l(br.stack [%trap ~]) + l(va.stack [u.loaded rest]) + =+ bloq=(xeb (dec p.u.kind.i)) + =+ get=(mem-load index 8 p.mem) + ?~ get ~ + =/ lanes=(list @) + (rope bloq (div 64 p.u.kind.i) u.get) + :- ~ + %+ rep +(bloq) + ?: ?=(%u p.q.u.kind.i) + lanes + %+ turn lanes + %+ cork (cury to-si p.u.kind.i) + (cury en-si (mul 2 p.u.kind.i)) + :: + %zero + =+ get=(mem-load index (div p.u.kind.i 8) p.mem) + ?~ get l(br.stack [%trap ~]) + l(va.stack [u.get rest]) + :: + %splat + =; loaded=(unit @) + ?~ loaded l(br.stack [%trap ~]) + l(va.stack [u.loaded rest]) + =+ lane=(mem-load index (div p.u.kind.i 8) p.mem) + ?~ lane ~ + `(fil (xeb (dec p.u.kind.i)) (div 128 p.u.kind.i) u.lane) + :: + == +``` + +Load vector from memory with optional operations like splat (broadcast), zero-extend, or sign-extend. + +### `+load-lane` {#load-lane} + +```hoon +++ load-lane + |= i=instr-vec + ?> ?=(%load-lane -.i) + |= l=local-state + ^- local-state + ?> ?=([vec=@ addr=@ rest=*] va.stack.l) + =, va.stack.l + =/ index=@ (add addr offset.m.i) + =+ mem=(memo:grab 0 store.l) + ?: ?=(%| -.mem) + %^ buy l(va.stack rest) + :* -.p.mem + %memo + (change ~[%i32 %v128] ~[addr vec]) + [%vec i] + == + ~[%v128] + =+ lane=(mem-load index (div p.i 8) p.mem) + ?~ lane l(br.stack [%trap ~]) + %= l + va.stack + [(sew (xeb (dec p.i)) [l.i 1 u.lane] vec) rest] + == +``` + +Load single value from memory into a specific lane of an existing vector. + +### `+store` {#store} + +```hoon +++ store + |= i=instr-vec + ?> ?=(%store -.i) + |= l=local-state + ^- local-state + ?> ?=([vec=@ addr=@ rest=*] va.stack.l) + =, va.stack.l + =+ memo=(memo:grab 0 store.l) + ?: ?=(%| -.memo) + %^ buy l(va.stack rest) + :* -.p.memo + %memo + (change ~[%i32 %v128] ~[addr vec]) + [%vec i] + == + ~ + =/ index=@ (add addr offset.m.i) + =+ mem-stored=(mem-store index 16 vec p.memo) + ?~ mem-stored l(br.stack [%trap ~]) + %= l + va.stack rest + :: + mem.store + `u.mem-stored + == +``` + +Store 128-bit vector to memory at the specified address. + +### `+store-lane` {#store-lane} + +```hoon +++ store-lane + |= i=instr-vec + ?> ?=(%store-lane -.i) + |= l=local-state + ^- local-state + ?> ?=([vec=@ addr=@ rest=*] va.stack.l) + =, va.stack.l + =+ memo=(memo:grab 0 store.l) + ?: ?=(%| -.memo) + %^ buy l(va.stack rest) + :* -.p.memo + %memo + (change ~[%i32 %v128] ~[addr vec]) + [%vec i] + == + ~ + =/ index=@ (add addr offset.m.i) + =+ lane=(cut (xeb (dec p.i)) [l.i 1] vec) + =+ mem-stored=(mem-store index (div p.i 8) lane p.memo) + ?~ mem-stored l(br.stack [%trap ~]) + %= l + va.stack rest + :: + mem.store + `u.mem-stored + == +``` + +Store single lane from vector to memory at the specified address. + +### `+const` {#const} + +```hoon +++ const + |= i=instr-vec + ?> ?=(%const -.i) + |= l=local-state + ^- local-state + l(va.stack [(coin-to-val p.i) va.stack.l]) +``` + +Push vector constant value onto the stack. + +### `+shuffle` {#shuffle} + +```hoon +++ shuffle + |= i=instr-vec + ?> ?=(%shuffle -.i) + |= l=local-state + ^- local-state + ?> ?=([c2=@ c1=@ rest=*] va.stack.l) + =, va.stack.l + =/ seq=(list @) + (weld (rope 3 16 c1) (rope 3 16 c2)) + %= l + va.stack + :_ rest + %+ rep 3 + %+ turn lane-ids.i + (curr snag seq) + == +``` + +Shuffle lanes between two vectors according to the lane indices specified in the instruction. + +### `+extract` {#extract} + +```hoon +++ extract + |= i=instr-vec + ?> ?=(%extract -.i) + |= l=local-state + ^- local-state + ?> ?=([vec=@ rest=*] va.stack.l) + =, va.stack.l + =+ size=(lane-size p.i) + =+ lane=(cut (xeb (dec size)) [l.i 1] vec) + =; to-put=@ + l(va.stack [to-put rest]) + ?: ?=(%u mode.i) lane + (en-si 32 (to-si size lane)) +``` + +Extract value from a specific lane of a vector, with optional sign extension. + +### `+replace` {#replace} + +```hoon +++ replace + |= i=instr-vec + ?> ?=(%replace -.i) + |= l=local-state + ^- local-state + ?> ?=([lane=@ vec=@ rest=*] va.stack.l) + =, va.stack.l + %= l + va.stack + :_ rest + (sew (xeb (dec (lane-size p.i))) [l.i 1 lane] vec) + == +``` + +Replace a specific lane in a vector with a new value. -### Vector Memory Operations +### `+plain` {#plain} -- `load`: Load vector from memory with optional splat/zero-extend/sign-extend -- `load-lane`: Load single value into specific lane -- `store`: Store vector to memory -- `store-lane`: Store single lane to memory +```hoon +++ plain + |= i=instr-vec + ^- $-(local-state local-state) + ~+ + |^ + ?+ -.i !! + vec-unary:kind + |= l=local-state + ^- local-state + ?> ?=([a=@ rest=*] va.stack.l) + =, va.stack.l + =+ val=((vec-unar i) a) + ?~ val l(br.stack [%trap ~]) + l(va.stack [val rest]) + :: + vec-binary:kind + |= l=local-state + ^- local-state + ?> ?=([b=@ a=@ rest=*] va.stack.l) + =, va.stack.l + =+ val=((vec-bina i) a b) + ?~ val l(br.stack [%trap ~]) + l(va.stack [val rest]) + :: + lane-wise-unary:kind + =/ op=$-(@ (unit @)) (get-op-unar i) + =/ size=@ (get-size i) + |= l=local-state + ^- local-state + ?> ?=([vec=@ rest=*] va.stack.l) + =, va.stack.l + =; val=(unit @) + ?~ val l(br.stack [%trap ~]) + l(va.stack [u.val rest]) + ;< =(list @) _biff + (torn (rope (xeb (dec size)) (div 128 size) vec) op) + `(rep (xeb (dec size)) list) + :: + lane-wise-binary:kind + =/ op=$-([@ @] (unit @)) (get-op-bina i) + =/ size=@ (get-size i) + |= l=local-state + ^- local-state + ?> ?=([vec2=@ vec1=@ rest=*] va.stack.l) + =, va.stack.l + =; val=(unit @) + ?~ val l(br.stack [%trap ~]) + l(va.stack [u.val rest]) + ;< =(list @) _biff + %- torn :_ op + %+ fuse (rope (xeb (dec size)) (div 128 size) vec1) + (rope (xeb (dec size)) (div 128 size) vec2) + `(rep (xeb (dec size)) list) + :: + %bitselect + |= l=local-state + ^- local-state + ?> ?=([vec3=@ vec2=@ vec1=@ rest=*] va.stack.l) + =, va.stack.l + %= l + va.stack + :_ rest + :: ++con is ior, ++dis is iand + :: + (con (dis vec1 vec3) (dis vec2 (not 7 1 vec3))) + == + == +``` -### Vector Manipulation +Plain vector operations dispatcher that handles different categories of SIMD instructions. -- `const`: Vector constant values -- `shuffle`: Rearrange lanes by index list -- `extract`: Get value from specific lane -- `replace`: Set value in specific lane +#### `+kind:plain` {#kind-plain} -### Vector Arithmetic +```hoon +++ kind + |% + +$ vec-unary + $? %splat %not %any-true %all-true + %bitmask %extadd %extend %convert + %demote %promote + == + :: + +$ vec-binary + $? %swizzle %and %andnot %or %xor + %narrow %shl %shr %extmul %dot + == + :: + +$ lane-wise-unary + $? + %abs %neg %popcnt %ceil %floor %trunc + %nearest %sqrt + == + :: + +$ lane-wise-binary + $? %eq %ne %lt %gt %le %ge %add %sub + %min %max %avgr %q15mul-r-sat %mul %div + %pmin %pmax + == + -- +``` + +SIMD instruction type categories for organizing vector operations. + +#### `+vec-unar:plain` {#vec-unar-plain} + +```hoon +++ vec-unar + |: i=`$>(vec-unary:kind instr-vec)`[%not ~] + ^- $-(@ @) + ?- -.i + :: ... + == +``` + +{TODO - comment with %foo, %bar branches analogous to core with commented out +foo, +bar etc.} + +Unary vector operations including splat, bitwise not, truth testing, type conversions, and lane extensions. + +#### `+vec-bina:plain` {#vec-bina-plain} + +```hoon +++ vec-bina + |: i=`$>(vec-binary:kind instr-vec)`[%and ~] + ^- $-([@ @] @) + ?- -.i + :: ... + == +``` + +Binary vector operations including logical operations, lane narrowing, shifts, and multiplication. + +#### `+get-op-unar:plain` {#get-op-unar-plain} + +```hoon +++ get-op-unar + |: i=`$>(lane-wise-unary:kind instr-vec)`[%popcnt ~] + ^- $-(@ (unit @)) + ?- -.i + :: ... + == +``` + +Resolve unary operation implementations for lane-wise vector operations. + +#### `+get-op-bina:plain` {#get-op-bina-plain} + +```hoon +++ get-op-bina + |: i=`$>(lane-wise-binary:kind instr-vec)`[%q15mul-r-sat ~] + ^- $-([@ @] (unit @)) + ?- -.i + :: ... + == +``` + +Resolve binary operation implementations for lane-wise vector operations. + +#### `+get-size:plain` {#get-size-plain} + +```hoon +++ get-size + |= i=^ + ^- @ + ?+ +.i !! + ~ + ?+ -.i !! + %q15mul-r-sat 16 + %popcnt 8 + == + :: + lane-type + (lane-size +.i) + :: + [p=lane-type *] + (lane-size p.i) + == +``` -- `plain`: Plain vector operations including: - - `kind`: Categorize vector operation types - - `vec-unar`: Unary vector operations - - `vec-bina`: Binary vector operations - - `get-op-unar`: Resolve unary operation implementations - - `get-op-bina`: Resolve binary operation implementations - - `get-size`: Extract size information from vector types +Extract size information from lane-wise SIMD instruction types. From edd1d0e8734964b5ccb27712b0f183de278c38bb Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 15:37:09 +0100 Subject: [PATCH 34/57] Add jets to README index --- content/build-on-urbit/wasm-walkthrough/reference/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm-walkthrough/reference/README.md index 28ef154f..d1c58b50 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/README.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/README.md @@ -26,3 +26,6 @@ This reference section documents UrWasm's data types and library functionality. - Wasm operator - Wasm interpreter - Lia interpreter + +## Jets +- foobar From 08b134488ef5408dc243c96f85d84900d38a56e2 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 15:50:12 +0100 Subject: [PATCH 35/57] Draft lib-wasm-lia docs --- .../reference/lib-wasm-lia.md | 298 ++++++++++++++++-- 1 file changed, 279 insertions(+), 19 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md index 92344e2b..236d81b3 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md @@ -1,31 +1,291 @@ +## Lia Interpreter -## /lib/wasm/lia +The `/lib/wasm/lia.hoon` library implements Lia (Language for Invocation of webAssembly), a high-level scripting interface for executing WebAssembly modules within Urbit. Lia provides deterministic execution of Wasm code while maintaining performance through caching and efficient state management. +Lia handles: +- Deterministic execution of Wasm modules. +- Memory read/write operations. +- Function invocation with automatic type conversion. +- Global variable access. +- Import function handling for external calls. + +## `$run-input` {#run-input} + +```hoon ++$ run-input + (each (script-raw-form (list lia-value) *) (list lia-value)) +``` + +Input type for [`+run`](#run). Either a new script to execute or cached values from previous execution. + +## `+run-once` {#run-once} + +```hoon ++ run-once - ++ init + |* [type-yield=mold type-acc=mold] + |= [[binary=octs imp=(import type-acc)] hint=term script-in=form:m] + ^- [yield:m type-acc] + :: ... +``` + +Build a stateless execution arm for a Wasm module. Takes: +- `.type-yield`: Mold for the yield type. +- `.type-acc`: Mold for the accumulator type. +- `.binary`: WebAssembly module as [`$octs`](./wasm-data-types.md#octs). +- `.imp`: Import function map. +- `.hint`: Execution hint. +- `.script-in`: Lia script to execute. + +Returns the script yield and final accumulator state. + +### `+init:run-once` {#init-run-once} + +```hoon +++ init + =/ m (script ,~ type-acc) + ^- form:m + |= sat=(lia-state type-acc) + ^- output:m + :: ... +``` + +Initializes the Wasm module within [`+run-once`](#run-once). Handles module instantiation and processes any required imports by calling external functions. + +## `+run` {#run} + +```hoon ++ run - ++ init + |= [input=run-input =seed hint=term] + ^- [yield:m * _seed] + :: ... +``` + +Stateful execution of a Wasm module. Can be used to run a new script or resume computation with the provided `$seed` state. + +### `+init` {#init-run} + +```hoon +++ init + =/ m (script ,~ *) + ^- form:m + |= sat=(lia-state) + ^- output:m +``` +Initializes the Wasm module within [`+run`](#run). Similar to [`+init`](#init-run-once) in `+run-once` but operates on the monomorphic [`$lia-state`](./lia-data-types.md#lia-state). + +## `+arrows` {#arrows} + +```hoon ++ arrows -* [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - ++ m-sat (lia-state m-acc) - ++ call - ++ call-1 - ++ memread - ++ memwrite - ++ call-ext - ++ global-set - ++ global-get - ++ memory-size - ++ memory-grow :: returns old size in pages - ++ get-acc - ++ set-acc - ++ get-all-local-globals - ++ set-all-local-globals + |* m-acc=mold + ^? |% + :: ... +``` + +Core containing Kleisli arrows (monadic operations) for Lia script operations. Type-polymorphic over the accumulator type `.m-acc`. + +### `$m-sat` {#m-sat} + +```hoon ++$ m-sat (lia-state m-acc) +``` + +Type alias for the polymorphic [`$lia-state`](./lia-data-types.md#lia-state) with accumulator type `.m-acc`. + +### `+call` {#call} + +```hoon +++ call + |= [name=cord args=(list @)] + =/ m (script (list @) m-acc) + ^- form:m +``` + +Invokes a WebAssembly function by name with the given arguments. Performs type conversion from Hoon atoms to [`$coin-wasm`](./wasm-data-types.md#coin-wasm) values and back. Handles import function resolution if the called function is not locally defined. + +### `+call-1` {#call-1} + +```hoon +++ call-1 + |= [name=cord args=(list @)] + =/ m (script @ m-acc) + ^- form:m +``` + +Convenience function for calling WebAssembly functions that return exactly one value. Wraps [`+call`](#call) and extracts the single return value. + +### `+memread` {#memread} + +```hoon +++ memread + |= [ptr=@ len=@] + =/ m (script octs m-acc) + ^- form:m +``` + +Reads `.len` bytes from WebAssembly linear memory starting at address `.ptr`. Returns the data as [`$octs`](./wasm-data-types.md#octs). Performs bounds checking against the current memory size. + +### `+memwrite` {#memwrite} + +```hoon +++ memwrite + |= [ptr=@ len=@ src=@] + =/ m (script ,~ m-acc) + ^- form:m +``` + +Writes `.len` bytes from atom `.src` to WebAssembly linear memory starting at address `.ptr`. Performs bounds checking and fails if the write would exceed memory bounds. + +### `+call-ext` {#call-ext} + +```hoon +++ call-ext + |= [name=term args=(list lia-value)] + =/ m (script (list lia-value) m-acc) + ^- form:m +``` + +Calls an external (import) function. If no cached result is available, yields the function call request to the host environment. Otherwise returns the cached result. + +### `+global-set` {#global-set} + +```hoon +++ global-set + |= [name=cord value=@] + =/ m (script ,~ m-acc) + ^- form:m +``` + +Sets the value of an exported global variable by name. Verifies the global is mutable and performs type conversion from atom to the appropriate [`$coin-wasm`](./wasm-data-types.md#coin-wasm) type. +### `+global-get` {#global-get} + +```hoon +++ global-get + |= name=cord + =/ m (script @ m-acc) + ^- form:m +``` + +Gets the value of an exported global variable by name. Returns the value as an atom, performing type conversion from [`$coin-wasm`](./wasm-data-types.md#coin-wasm). + +### `+memory-size` {#memory-size} + +```hoon +++ memory-size + =/ m (script @ m-acc) + ^- form:m +``` + +Returns the current size of WebAssembly linear memory in pages. Each page is [`+page-size`](#page-size) bytes (65,536 bytes). + +### `+memory-grow` {#memory-grow} + +```hoon +++ memory-grow + |= delta=@ + =/ m (script @ m-acc) + ^- form:m +``` + +Grows WebAssembly linear memory by `.delta` pages. Returns the previous memory size in pages. Growing memory preserves existing data and zero-initializes the new pages. + +### `+get-acc` {#get-acc} + +```hoon +++ get-acc + =/ m (script m-acc m-acc) + ^- form:m +``` + +Returns the current accumulator value from the Lia state. + +### `+set-acc` {#set-acc} + +```hoon +++ set-acc + |= acc=m-acc + =/ m (script ,~ m-acc) + ^- form:m +``` + +Sets the accumulator value in the Lia state. + +### `+get-all-local-globals` {#get-all-local-globals} + +```hoon +++ get-all-local-globals + =/ m (script (list @) m-acc) + ^- form:m +``` + +Returns all local (non-import) global variable values as a list of atoms. + +### `+set-all-local-globals` {#set-all-local-globals} + +```hoon +++ set-all-local-globals + |= vals=(list @) + =/ m (script ,~ m-acc) + ^- form:m +``` + +Sets all local global variables from a list of atoms. Performs type conversion to the appropriate [`$coin-wasm`](./wasm-data-types.md#coin-wasm) types. + +## `+runnable` {#runnable} + +```hoon ++ runnable (script (list lia-value) *) +``` + +Type alias for the monomorphic script type used by [`+run`](#run). + +## `+cw-to-atom` {#cw-to-atom} + +```hoon ++ cw-to-atom + |= cw=coin-wasm:wasm-sur + ^- @ +``` + +Converts a [`$coin-wasm`](./wasm-data-types.md#coin-wasm) value to an atom. Fails if the coin represents a reference type. + +## `+types-atoms-to-coins` {#types-atoms-to-coins} + +```hoon ++ types-atoms-to-coins + |= [a=(list valtype:wasm-sur) b=(list @)] + ^- (list coin-wasm:wasm-sur) +``` + +Converts parallel lists of [`$valtype`s](./wasm-data-types.md#valtype) and atoms into a list of [`$coin-wasm`](./wasm-data-types.md#coin-wasm) values. Used for function argument conversion. + +## `+valtype-from-coin` {#valtype-from-coin} + +```hoon ++ valtype-from-coin -++ page-size ^\~((bex 16)) + |= =cw + ^- valtype:wasm-sur +``` + +Extracts the [`$valtype`](./wasm-data-types.md#valtype) from a [`$coin-wasm`](./wasm-data-types.md#coin-wasm) value. + +## `+page-size` {#page-size} + +```hoon +++ page-size ^~((bex 16)) +``` + +WebAssembly page size constant: 65,536 bytes. + +## `+yield-need` {#yield-need} + +```hoon ++ yield-need + |* a=(script-yield *) + ?> ?=(%0 -.a) + p.a +``` + +Extracts the payload from a successful script yield, crashing if the yield indicates failure or blocking. From ff345b375b90fca6a9be49692a15a090f80d6dbd Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 15 Aug 2025 18:52:49 +0100 Subject: [PATCH 36/57] Draft Wasm engine docs --- .../reference/lib-wasm-runner-engine.md | 700 +++++++++++++++++- 1 file changed, 677 insertions(+), 23 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md index b3c4391e..27de726d 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md @@ -1,26 +1,680 @@ +# Wasm Runner Engine -## /lib/wasm/runner/engine +The `+engine` core implements the core WebAssembly interpreter engine. This runs module instantiation, function invocation, and the main evaluation loop for WebAssembly instructions. +## `+engine` {#engine} + +```hoon ++ engine - ++ get-types - ++ mint - ++ make-export-map - ++ find-func-id - ++ conv - ++ import-upd - ++ prep - ++ instantiate - ++ init-globals - ++ init-table - ++ init-elems - ++ init-mem - ++ init-data - ++ start - ++ wasm-need - ++ wasm-bind - ++ invoke - ++ invoke-id - ++ call - ++ eval - ++ dec-br - ++ apply + =, engine-sur + =, op-def + |% + :: ... + -- +``` + +Exposes the `+engine-sur` and `+op-def` namespaces containing interpreter data types and instruction definitions. + +## `+get-types` {#get-types} + +```hoon +++ get-types + |= a=(list coin-wasm) + ^- (list valtype) + %+ turn a + |= c=coin-wasm + ^- valtype + ?. ?=([%ref r=*] c) + -.c + -.r.c +``` + +Extract [`$valtype`s](./wasm-data-types.md#valtype) from a list of [`$coin-wasm`](./wasm-data-types.md#coin-wasm) values. Used primarily for function parameter type checking. + +## `+mint` {#mint} + +```hoon +++ mint + |= a=(list valtype) + ^- (list val) + ?~ a ~ + :_ $(a t.a) + ^- val + ?- i.a + ?(num-type vec-type) *@ + ref-type :- %ref + ?- i.a + %extn [%extn ~] + %func [%func ~] + == == +``` + +Generate initial values for local variables. Creates default zero values for numeric and vector types, and null references for reference types. + +## `+make-export-map` {#make-export-map} + +```hoon +++ make-export-map + |= =export-section + =| out=(map cord export-desc) + |- ^+ out + ?~ export-section out + =, i.export-section + %= $ + out (~(put by out) name export-desc) + export-section t.export-section + == +``` + +Convert an [`$export-section`](./wasm-data-types.md#export-section) into a map from export names to their [`$export-desc`](./wasm-data-types.md#export-desc) for efficient lookup. + +## `+find-func-id` {#find-func-id} + +```hoon +++ find-func-id + |= [name=cord =module] + ^- @ + =, module + =/ =export-desc + (~(got by (make-export-map export-section)) name) + ?> ?=(%func -.export-desc) + i.export-desc +``` + +Find function index by export name. Looks up the function in the module's exports and returns its internal function index. + +## `+conv` {#conv} + +```hoon +++ conv + |= [m=^module sh=shop] + ^- store + =| st=store + =. shop.st sh + |^ + =. module.st + =, m + :* + type-section + (import-upd import-section) + (fuse function-section code-section) + table-section + memory-section + global-section + export-section + start-section + elem-section + data-section + == + st +``` + +Convert a parsed [`$module`](./wasm-data-types.md#module) into a [`$store`](./wasm-interpreter-data-types.md#store) suitable for execution. Restructures the module by: +- Reorganizing imports with [`+import-upd`](#import-upd). +- Fusing function signatures with their code implementations. +- Setting up the execution environment. + +### `+import-upd` {#import-upd} + +```hoon +++ import-upd + |= i=^import-section + =| out=import-section + |- ^- import-section + ?~ i + =, out + %_ out + funcs (flop funcs) + tables (flop tables) + memos (flop memos) + globs (flop globs) + == + =. out + =, i.i + =, out + ?- -.desc.i.i + %func out(funcs [[[mod name] type-id.desc] funcs]) + %tabl out(tables [[[mod name] t.desc] tables]) + %memo out(memos [[[mod name] l.desc] memos]) + %glob out(globs [[[mod name] +.desc] globs]) + == + $(i t.i) +``` + +Reorganize imports from the flat list structure in parsed modules to the categorized structure needed by the engine's [`$import-section`](./wasm-interpreter-data-types.md#import-section). + +## `+prep` {#prep} + +```hoon +++ prep + |= [m=^module sh=shop] + ^- result + (instantiate (conv m sh)) +``` + +Prepare a parsed [`$module`](./wasm-data-types.md#module) for execution. First converts it to the engine's internal representation, then instantiates it through the full WebAssembly instantiation process. + +## `+instantiate` {#instantiate} + +```hoon +++ instantiate + |= st=store + ^- result + |^ + ;< [* st=store] _wasm-bind (init-globals st) => +(st st) + ;< [* st=store] _wasm-bind (init-table st) => +(st st) + ;< [* st=store] _wasm-bind (init-elems st) => +(st st) + ;< [* st=store] _wasm-bind (init-mem st) => +(st st) + ;< [* st=store] _wasm-bind (init-data st) => +(st st) + ;< [* st=store] _wasm-bind (start st) => +(st st) + [%0 ~ st] +``` + +Main WebAssembly module instantiation process following the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/modules.html#instantiation). Executes the instantiation steps in order: +1. Initialize global variables. +2. Initialize tables with null references. +3. Initialize table elements from element segments. +4. Initialize memory if present. +5. Initialize memory from data segments. +6. Execute the start function if present. + +Uses [`+wasm-bind`](#wasm-bind) to handle potential import blocking during initialization. + +### `+init-globals` {#init-globals} + +```hoon +++ init-globals + |= st=store + =/ m=module module.st + |- ^- result + ?~ global-section.m + [%0 ~ st(globals (flop globals.st))] + =* glob i.global-section.m + :: Const globals + :: + ?: ?=([%const p=$<(?(%v128 %ref) coin-wasm)] i.glob) + %= $ + global-section.m t.global-section.m + globals.st [p.i.glob globals.st] + == + ?: ?=([%vec %const p=$>(%v128 coin-wasm)] i.glob) + %= $ + global-section.m t.global-section.m + globals.st [p.i.glob globals.st] + == + ?: ?=([%ref-null t=ref-type] i.glob) + =/ null-ref=coin-wasm + ?: ?=(%func t.i.glob) [%ref %func ~] + [%ref %extn ~] + %= $ + global-section.m t.global-section.m + globals.st [null-ref globals.st] + == + ?: ?=([%ref-func func-id=@] i.glob) + %= $ + global-section.m t.global-section.m + globals.st [[%ref %func `func-id.i.glob] globals.st] + == + :: Imported globals. We assume here that %global-get + :: would not affect module store + :: + ?^ shop.st + %= $ + global-section.m t.global-section.m + globals.st [-.p.i.shop.st globals.st] + shop.st t.shop.st + == + :+ %1 + :- -:(snag index.i.glob globs.import-section.module.st) + [%glob ~ i.glob] + [*module ~ ~ ~] +``` + +Initialize global variables according to their constant initializer expressions. Handles various constant types and imported globals, potentially blocking on unresolved imports. + +### `+init-table` {#init-table} + +```hoon +++ init-table + |= st=store + =/ m=module module.st + |- ^- result + :+ %0 ~ + |- ^- store + ?~ table-section.m + st(tables (flop tables.st)) + =* tab i.table-section.m + %= $ + table-section.m t.table-section.m + :: + tables.st + :_ tables.st + (reap (lim-min q.tab) [%ref %func ~]) + == +``` + +Initialize tables by creating arrays filled with null function references according to each table's minimum size [`$limits`](./wasm-data-types.md#limits). + +### `+init-elems` {#init-elems} + +```hoon +++ init-elems + |= st=store + =/ m=module module.st + |- ^- result + :+ %0 ~ + |- ^- store + ?~ elem-section.m st + =* elem i.elem-section.m + ?. ?=(%acti -.m.elem) + $(elem-section.m t.elem-section.m) + :: Assert: only %func ref tables can be + :: initialized with an element segment + :: + ?> ?=(%func t.elem) + :: Assert: i32 value in the offset + :: (it theoretically can be a %global-get of import, revisit later?) + :: + =/ offset=(unit @) + ?: ?=([%const %i32 n=@] off.m.elem) `n.p.off.m.elem + ?. ?=(%global-get -.off.m.elem) ~ + =+ glob=(glob:grab index.off.m.elem st) + ?: ?=(%| -.glob) ~ + =/ coin=coin-wasm q.p.glob + ?: ?=(%i32 -.coin) `+.coin + ~ + ?> ?=(^ offset) + =/ tab-loc-id=@ + %+ sub tab.m.elem :: Assert: elems are instantiated locally + (lent tables.import-section.module.st) :: (to revisit?) + %= $ + elem-section.m t.elem-section.m + :: + tables.st + %^ shot tables.st tab-loc-id + %^ place (snag tab-loc-id tables.st) :: table to change + u.offset :: offset + %+ turn i.elem + |= in=instruction + ^- $>(%ref coin-wasm) + ?> ?=([%ref-func @] in) :: Assert: %func refs only + [%ref %func `func-id.in] + :: + == +``` + +Initialize active element segments by copying their contents into tables at the specified offsets. Only processes active segments; passive segments are handled by explicit instructions during execution. + +### `+init-mem` {#init-mem} + +```hoon +++ init-mem + |= st=store + =/ m=module module.st + |- ^- result + :+ %0 ~ + ?~ memory-section.m st + ?> ?=(@ t.memory-section.m) :: Assert: single memory + =* mem i.memory-section.m + st(mem `[0 (lim-min mem)]) +``` + +Initialize linear memory with the minimum number of pages specified in the memory section. WebAssembly currently supports only one memory per module. + +### `+init-data` {#init-data} + +```hoon +++ init-data + |= st=store + =/ m=module module.st + =+ id=`@`0 + |- ^- result + ?~ data-section.m [%0 ~ st] + =* data i.data-section.m + ?. ?=(%acti -.data) + $(data-section.m t.data-section.m, id +(id)) + :: Assert: const i32 value as offset + :: (it theoretically can be a %global-get of import, revisit later?) + :: + =/ offset=(unit @) + ?: ?=([%const %i32 n=@] off.data) `n.p.off.data + ?. ?=(%global-get -.off.data) ~ + =+ glob=(glob:grab index.off.data st) + ?: ?=(%| -.glob) ~ + =/ coin=coin-wasm q.p.glob + ?: ?=(%i32 -.coin) `+.coin + ~ + ?> ?=(^ offset) + =/ l=local-state + [[~ ~[-.b.data 0 u.offset]] ~ st] + =. l ((fetch-gate [%memory-init id %0]) l) + ?^ br.stack.l + ?+ br.stack.l !! + [%bloq p=*] [%1 p.br.stack.l] + [%trap ~] [%2 store.l] + == + %= $ + id +(id) + data-section.m t.data-section.m + st store.l + == +:: +``` + +Initialize active data segments by copying their contents into linear memory at specified offsets. Uses the `memory.init` instruction implementation for the actual memory copying. + +### `+start` {#start} + +```hoon +++ start + |= st=store + ^- result + =/ m=module module.st + ?~ start-section.m [%0 ~ st] + =/ [=stack * st-out=store] + (call u.start-section.m [[~ ~] ~ st]) + ?+ br.stack !! + ~ [%0 ~ st-out] + [%bloq p=*] [%1 p.br.stack] + [%trap ~] [%2 st-out] + == +``` + +Execute the start function if one is defined. The start function must take no parameters and return no values. + +## `+wasm-need` {#wasm-need} + +```hoon +++ wasm-need + |= a=result + ^- (quip coin-wasm store) + ?> ?=(%0 -.a) + +.a +``` + +Extract successful result from a [`$result`](./wasm-interpreter-data-types.md#result). Crashes if the result indicates an error or blocking state. + +## `+wasm-bind` {#wasm-bind} + +```hoon +++ wasm-bind + |= [a=result b=$-((quip coin-wasm store) result)] + ^- result + ?. ?=(%0 -.a) a + (b +.a) +``` + +Monadic bind operator for chaining [`$result`](./wasm-interpreter-data-types.md#result) computations. If the first result is successful, applies the continuation function; otherwise propagates the error or blocking state. + +## `+invoke` {#invoke} + +```hoon +++ invoke + |= [name=cord in=(list coin-wasm) st=store] + ^- result + =/ id=@ (find-func-id name module.st) + (invoke-id id in st) +``` + +Invoke an exported function by name with the given arguments. Looks up the function by name in the exports table, then delegates to [`+invoke-id`](#invoke-id). + +## `+invoke-id` {#invoke-id} + +```hoon +++ invoke-id + |= [id=@ in=(list coin-wasm) st=store] + ^- result + =/ id-local=@ + (sub id (lent funcs.import-section.module.st)) + :: Type check for the input values + :: + =, module.st + =/ =func-type + =/ func (func:grab id st) + ?: ?=(%& -.func) (snag type-id.p.func type-section) + (snag type-id.p.func type-section) + ?> =(params.func-type (get-types in)) + =/ [stack-out=stack * st-out=store] + %+ call id + ^- local-state + :+ stack=[~ (turn (flop in) coin-to-val)] + locals=~ + store=st + ?+ br.stack-out !! + ~ :+ %0 + (change results.func-type (flop va.stack-out)) + st-out + [%bloq p=*] [%1 p.br.stack-out] + [%trap ~] [%2 st-out] + == +``` + +Invoke a function by its index with type checking. Converts the input [`$coin-wasm`](./wasm-data-types.md#coin-wasm) values to stack values, calls the function, and converts the results back to typed values. + +## `+call` {#call} + +```hoon +++ call + |= [id=@ l=local-state] + ^- local-state + =, module.store.l + =+ f=(func:grab id store.l) :: (each function [[mod=cord name=cord] type-id=@]) + =/ type-id=@ =>(f ?:(?=(%& -) type-id.p type-id.p)) + =/ =func-type (snag type-id type-section) + :: import case + :: + ?: ?=(%| -.f) + %^ buy l(va.stack (slag (lent params.func-type) va.stack.l)) + :+ -.p.f %func + %+ change params.func-type + %- flop + (scag (lent params.func-type) va.stack.l) + results.func-type + :: local case + :: take input values + :: + =/ input-values=(pole val) + %- flop + (scag (lent params.func-type) va.stack.l) + :: save the rest of the stack and our locals + :: + =/ rest-vals=(pole val) + (slag (lent params.func-type) va.stack.l) + =/ our-locs=(list val) locals.l + :: update local state + :: + =. l + %+ eval expression.p.f + ^- local-state + :+ stack=[~ ~] + locals=(weld input-values (mint locals.p.f)) + store=store.l + :: If trap or bloq: forward + :: + ?: ?=([?(%trap %bloq) *] br.stack.l) l + :: Assert: no branch or branch with label 0 or return + :: + ?> ?| ?=(~ br.stack.l) + ?=([%retr ~] br.stack.l) + ?=([%targ %0] br.stack.l) + == + :: If return or targeted, take appropriate amount of vals from the stack + :: + =? va.stack.l ?| ?=([%retr ~] br.stack.l) + ?=([%targ %0] br.stack.l) + == + (scag (lent results.func-type) va.stack.l) + :: Push returned values on stack, bring back locals, empty out br + :: + %= l + va.stack (weld va.stack.l rest-vals) + locals our-locs + br.stack ~ + == +``` + +Call a function by ID within the interpreter. Handles both imported functions (which create import requests) and local functions (which are executed directly). + +For local functions: +1. Extracts parameters from the stack. +2. Sets up local variables (parameters + declared locals). +3. Evaluates the function body. +4. Handles return values and control flow. + +## `+eval` {#eval} + +```hoon +++ eval + |= [e=expression l=local-state] + ^- local-state + ?: |(=(~ e) !=(~ br.stack.l)) :: if navigating branch + l :: jump to the end of expression + $(l (apply -.e l), e +.e) +``` + +Evaluate a WebAssembly [`$expression`](./wasm-data-types.md#expression) (sequence of instructions) by applying each instruction in turn to the [`$local-state`](./wasm-interpreter-data-types.md#local-state). + +Short-circuits evaluation when: +- The expression is empty. +- There's an active branch signal (from `br`, `return`, etc.) + +## `+dec-br` {#dec-br} + +```hoon +++ dec-br + |= br=branch + ^- branch + ?+ br br + [%targ %0] ~ + [%targ i=@] [%targ (dec i.br)] + == +``` + +Decrement branch target labels when exiting nested control structures. Preserves absolute branching coordinates (`trap`, `return`, `block`) and safely decrements relative target indices. Used for control flow navigation when exiting blocks and loops. + +## `+apply` {#apply} + +```hoon +++ apply + |= [i=instruction l=local-state] + ^- local-state + !. + ?+ i ((fetch-gate i) l) + [%call func-id=@] + (call func-id.i l) + :: + [%block *] :: [%block type=block-type body=expression] + =/ n-params=@ + %- lent + ?^ type.i params.type.i + params:(snag type.i type-section.module.store.l) + :: save the current frame + :: + =/ rest-vals=(pole val) (slag n-params va.stack.l) + :: execute the block + :: + =. l (eval body.i l(va.stack (scag n-params va.stack.l))) + :: If the block was targeted, pop appropriate amount of vals + :: + =? va.stack.l ?=([%targ %0] br.stack.l) + =; n-results=@ + (scag n-results va.stack.l) + %- lent + ?^ type.i results.type.i + results:(snag type.i type-section.module.store.l) + :: Exit the block, navigate branch + :: + l(va.stack (weld va.stack.l rest-vals), br.stack (dec-br br.stack.l)) + :: + [%loop *] :: [%loop type=block-type body=expression] + |- ^- local-state :: not strictly necessary, but prevents from matching `i` again + =/ n-params=@ + %- lent + ?^ type.i params.type.i + params:(snag type.i type-section.module.store.l) + :: save the current frame + :: + =/ rest-vals=(pole val) (slag n-params va.stack.l) + :: execute the block + :: + =. l (eval body.i l(va.stack (scag n-params va.stack.l))) + :: If the loop was targeted, pop appropriate amount of vals, + :: push them on the stack, clear branching signal and jump to start + :: + ?: ?=([%targ %0] br.stack.l) + %= $ + va.stack.l (weld (scag n-params va.stack.l) rest-vals) + br.stack.l ~ + == + :: Exit the block, navigate branch + :: + l(va.stack (weld va.stack.l rest-vals), br.stack (dec-br br.stack.l)) + :: + [%call-indirect type-id=@ table-id=@] + =, module.store.l + ?> ?=([ref-id=@ rest=*] va.stack.l) + =, va.stack.l + =+ tab=(table:grab table-id.i store.l) :: (each (list $>(%ref coin-wasm)) [[mod=cord name=cord] t=table]) + :: import table + :: + ?: ?=(%| -.tab) + =/ =func-type (snag type-id.i type-section) + =/ input=(list coin-wasm) + %+ change params.func-type + (flop (scag (lent params.func-type) rest)) + %^ buy l(va.stack (slag (lent params.func-type) rest)) + [-.p.tab %tabl (weld input (change ~[%i32] ~[ref-id])) i] + results.func-type + :: local table + :: + :: Type check of reference + :: + =/ type-in-instr=func-type (snag type-id.i type-section) + =+ ref=(snag ref-id q.p.tab) + =/ type-of-ref=(unit func-type) + ?+ ref ~ + [%ref %func p=[~ @]] + =; =func-type + `func-type + =/ func (func:grab u.p.ref store.l) + ?: ?=(%& -.func) (snag type-id.p.func type-section) + (snag type-id.p.func type-section) + :: + [%ref %extn p=^] + `type.u.p.ref + == + ?~ type-of-ref l(br.stack [%trap ~]) + ?. =(type-in-instr u.type-of-ref) + l(br.stack [%trap ~]) + :: local func reference + :: + ?: ?=([%ref %func p=[~ @]] ref) + (call u.p.ref l(va.stack rest)) + :: external func reference + :: + ?. ?=([%ref %extn p=^] ref) + l(br.stack [%trap ~]) + %^ buy l(va.stack (slag (lent params.type.u.p.ref) rest)) + :- -.u.p.ref + =* params params.type.u.p.ref + [%func (change params (flop (scag (lent params) rest)))] + results.type.u.p.ref + :: + [%if *] :: [%if type=block-type branch-true=expression branch-false=expression] + ?> ?=([f=@ rest=*] va.stack.l) + =, va.stack.l + ?. =(0 f) + $(i [%block type branch-true]:i, va.stack.l rest) + $(i [%block type branch-false]:i, va.stack.l rest) + :: + == +``` + +Apply a single [`$instruction`](./wasm-data-types.md#instruction) to the [`$local-state`](./wasm-interpreter-data-types.md#local-state). Most instructions delegate to [`+fetch-gate:op-def`](./lib-wasm-runner-op-def.md#fetch-gate), but complex control flow instructions are implemented directly: + +- `%call`: Direct function calls. +- `%block`: Labeled blocks with proper value stack management. +- `%loop`: Loops with branch-back semantics. +- `%call-indirect`: Indirect calls through function tables with type checking. +- `%if`: Conditional execution choosing between true/false branches. + From 792d12d013234f159f2943fbe56492ddc6fcea03 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 10:10:04 +0100 Subject: [PATCH 37/57] Restructure --- content/build-on-urbit/wasm-walkthrough/README.md | 4 ++-- .../build-on-urbit/wasm-walkthrough/examples/README.md | 6 ------ content/build-on-urbit/wasm-walkthrough/examples/agent.md | 7 ------- .../build-on-urbit/wasm-walkthrough/examples/thread.md | 8 -------- .../wasm-walkthrough/{examples => }/generator.md | 0 content/build-on-urbit/wasm-walkthrough/overview.md | 2 +- 6 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 content/build-on-urbit/wasm-walkthrough/examples/README.md delete mode 100644 content/build-on-urbit/wasm-walkthrough/examples/agent.md delete mode 100644 content/build-on-urbit/wasm-walkthrough/examples/thread.md rename content/build-on-urbit/wasm-walkthrough/{examples => }/generator.md (100%) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md index dd6e91fe..30b3e315 100644 --- a/content/build-on-urbit/wasm-walkthrough/README.md +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -15,10 +15,10 @@ layout: # Wasm Walkthrough -Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any Wasm-compatible language like Rust, Python, and Go. Using QuickJS as a Wasm module, they can also run Javascript on the Urbit ship. +Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any Wasm-compatible language like Rust, Python, and Go. These docs cover: - UrWasm overview -- UrWasm examples +- UrWasm example usage - UrWasm types and API diff --git a/content/build-on-urbit/wasm-walkthrough/examples/README.md b/content/build-on-urbit/wasm-walkthrough/examples/README.md deleted file mode 100644 index 28c591c0..00000000 --- a/content/build-on-urbit/wasm-walkthrough/examples/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# UrWasm Examples - -What usage patterns are possible with Wasm on Urbit? In this section we'll demonstrate several: -- Wasm in a [generator](../../../hoon/generators.md). -- Wasm in [threads](../../../urbit-os/base/threads/README.md). -- Wasm in [Gall agents](../../app-school/README.md). diff --git a/content/build-on-urbit/wasm-walkthrough/examples/agent.md b/content/build-on-urbit/wasm-walkthrough/examples/agent.md deleted file mode 100644 index 1bbf0ff7..00000000 --- a/content/build-on-urbit/wasm-walkthrough/examples/agent.md +++ /dev/null @@ -1,7 +0,0 @@ -# UrWasm Gall Agent Example - -foobar - -* In Gall agents - * You could do a Gall agent that tracks its state in the agent but delegates functionality to a JS library - diff --git a/content/build-on-urbit/wasm-walkthrough/examples/thread.md b/content/build-on-urbit/wasm-walkthrough/examples/thread.md deleted file mode 100644 index aed205ad..00000000 --- a/content/build-on-urbit/wasm-walkthrough/examples/thread.md +++ /dev/null @@ -1,8 +0,0 @@ -# UrWasm Thread Example - -foo - -* [cookbook.md](https://gist.github.com/Quodss/a7dca761f6bcd887241bdc04db2c026a) - * Stateful UrWasm: `+run` - * Example: running Wasm in a thread - diff --git a/content/build-on-urbit/wasm-walkthrough/examples/generator.md b/content/build-on-urbit/wasm-walkthrough/generator.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/examples/generator.md rename to content/build-on-urbit/wasm-walkthrough/generator.md diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index db3eb53d..085f4f36 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -2,7 +2,7 @@ Onboarding new developers onto Urbit necessarily involves teaching them [Hoon](../../hoon/why-hoon.md). Whatever Hoon's merits as a systems programming language, the time commitment to understanding the language enough to be productive is an obvious barrier to entry. -Urbit allows developers to run server-side code in languages like Rust and Python by compiling that code to [WebAssembly](https://webassembly.org/) (Wasm). They can run Javascript on the Urbit ship with a JS interpreter like QuickJS. Today this still involves some knowledge of Hoon, but the developer can mostly use the examples here as boilerplate. +Urbit allows developers to run server-side code in languages like Rust and Python by compiling that code to [WebAssembly](https://webassembly.org/) (Wasm). Today this still involves some knowledge of Hoon, but the developer can mostly use the examples here as boilerplate. Trivially, Urbit's Wasm affordances (collectively "UrWasm") enable Hoon developers to leverage pre-existing libraries for functionality that doesn't already exist in Hoon, or would be prohibitively slow without writing a C [runtime jet](../runtime/jetting.md). But one can imagine more ambitious use-cases like running complete Next.js or Rust apps on the Urbit ship. From 7e996faa643b07f091979e9ea040aed9243ff065 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 10:13:28 +0100 Subject: [PATCH 38/57] Draft new README --- content/build-on-urbit/wasm-walkthrough/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm-walkthrough/README.md index 30b3e315..eda4e1d6 100644 --- a/content/build-on-urbit/wasm-walkthrough/README.md +++ b/content/build-on-urbit/wasm-walkthrough/README.md @@ -18,7 +18,7 @@ layout: Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any Wasm-compatible language like Rust, Python, and Go. These docs cover: -- UrWasm overview -- UrWasm example usage -- UrWasm types and API +- An [overview](./overview.md) of Wasm and how it interacts with Urbit. +- [Example usage](./generator.md) of a Wasm module sort a large list. +- UrWasm data types and library [reference](./reference). From 06c4409dac9515135184edadfc5c3a6d56756857 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 11:15:26 +0100 Subject: [PATCH 39/57] Generator TODOs --- .../wasm-walkthrough/generator.md | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/generator.md b/content/build-on-urbit/wasm-walkthrough/generator.md index fb6186dd..cc2ab5b6 100644 --- a/content/build-on-urbit/wasm-walkthrough/generator.md +++ b/content/build-on-urbit/wasm-walkthrough/generator.md @@ -13,8 +13,6 @@ In pure Hoon, we would write something like this: (sort lit lth) ``` -{TODO: check the above compiles and runs} - Let's run this and see how long it takes. (`__~` in the Dojo discards the product of the given expression and returns `~`). ``` @@ -101,8 +99,6 @@ What's going on in this `sortu64()` wrapper function? We see that it does the fo 5. Frees the returned array from Wasm memory with `__wbindgen_free`. 6. Returns the sorted array. -{TODO: better setup for yil-mold and acc-mold here.} - We don't need to reimplement step 5, since the whole Wasm VM will be freed when we're done. Our generator with Hoon "bindings" will look like this in full. We'll examine each part in detail below. @@ -172,9 +168,11 @@ We use the `%bout` runtime hint to time the computation that follows. ~> %bout ``` -Now we'll define the types for our yield of the main script and the accumulator noun. We don't need the accumulator for this example but it's required for `+run-once`, so we'll just call it a noun `*`. +Now we'll define the types for our yield of the main script, and the accumulator noun: +- The `$yil-mold` is the type of our yield, the result of the script. +- The `$acc-mold` is the type of the accumulator, which holds some arbitrary state we can read and write to during script execution. -{TODO: better intro to the yield concept} +We don't need the accumulator for this example but it's required for `+run-once`, so we'll just call it a noun `*`. ```hoon => |% @@ -183,13 +181,9 @@ Now we'll define the types for our yield of the main script and the accumulator -- ``` -Since Lia's `+run-once` returns a pair of \[yield accumulator], we grab the yield with [`=<`](../../../hoon/rune/tis.md#tisgal) to get the head (`-`) of the result. `+yield-need` is a Lia function that asserts that a yield is successful and returns the unwrapped result. The `%$` is where we'd specify a runtime hint like `%bout`, but we stub it out here as we don't need one. - -Below, we build Lia's `+run-once` gate and run it on our imported `.wasm-bin` module, which we give the empty initial state `[~ ~]`. (That is, a pair of the initial accumulator state and {foobar}). - -{TODO: not sure about this Lia `+run-once` verbiage above} +Since Lia's `+run-once` returns a pair of \[yield accumulator], we grab the yield with [`=<`](../../../hoon/rune/tis.md#tisgal) to get the head (`-`) of the result. `+yield-need` is a Lia function that asserts that a yield is successful and returns the unwrapped result. -{TODO: get clarity on (list coin-wasm) arg in wasm state} +Below, we build Lia's `+run-once` core and run it on our imported `.wasm-bin` module, which we give the empty argument `[~ ~]`. (That is, a pair of the initial accumulator state and a map of imports.) The `%$` is where we'd specify a runtime hint like `%bout`, but we stub it out here as we don't need it. ```hoon :: run +yield-need on the head of the result @@ -201,9 +195,7 @@ Below, we build Lia's `+run-once` gate and run it on our imported `.wasm-bin` mo %^ (run-once yil-mold acc-mold) [wasm-bin [~ ~]] %$ ``` -Some more boilerplate. Hoon developers will recognize `.m` by analogy to the `.m` from the boilerplate often seen in [threads](../../../urbit-os/base/threads/README.md). `.arrows` is our built `+arrows` core from Lia, and we expose that namespace with [`=,`](../../../hoon/rune/tis.md#tiscom) for convenient usage later. - -{TODO: link to `+arrows` documentation in the reference section once it exists} +Some more boilerplate. Hoon developers will recognize `.m` by analogy to the `.m` from the boilerplate often seen in [threads](../../../urbit-os/base/threads/README.md). `.arrows` is our built [`+arrows`](./reference/lib-wasm-lia.md#arrows) core from Lia, and we expose that namespace with [`=,`](../../../hoon/rune/tis.md#tiscom) for convenient usage later. ```hoon :: define the monadic interface for the script @@ -216,8 +208,6 @@ Some more boilerplate. Hoon developers will recognize `.m` by analogy to the `.m We'll measure the input list and concatonate all of its elements into a single atom with [`+rep`](../../../hoon/stdlib/2c.md#rep). -{TODO: amend generator code style and update all code blocks accordingly} - ```hoon :: number of items in the list =/ len-vec=@ (lent lit) @@ -240,9 +230,7 @@ With that out of the way we can now interact with Wasm VM, replicating steps 1-4 ;< vec-out=octs try:m (memread &1.ptr-len (mul 8 &2.ptr-len)) ``` -Now we split the resulting octets atom (`$octs`, a cell of byte length and data) into a list of 64-bit atoms with [`+rip`](../../../hoon/stdlib/2c.md) and add missing trailing zeroes if necessary. - -{TODO: why would trailing zeroes be missing?} +Now we split the resulting octets atom (`$octs`, a cell of byte length and data) into a list of 64-bit atoms with [`+rip`](../../../hoon/stdlib/2c.md) and add missing trailing zeroes if necessary. (Note that UrWasm's [`+rope`](./reference/lib-wasm-runner-op-def.md#rope) would preserve the zeroes.) ```hoon :: rip the octet stream into a list of 64-bit atoms From 53cfdb3902c6acaeb6ce6007c65a19dfab68aa88 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 11:16:23 +0100 Subject: [PATCH 40/57] Better core notation in overview --- .../build-on-urbit/wasm-walkthrough/overview.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index 085f4f36..fa98708d 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -90,13 +90,13 @@ UrWasm is structured as several nested cores, with each core in this list being All cores except `/lib/wasm/lia/hoon`, are additionally wrapped in one-armed cores for easy invocation: ``` -/sur/wasm/wasm/hoon :: wasm-sur -/sur/wasm/engine/hoon :: engine-sur -/sur/wasm/lia/hoon :: lia-sur -/lib/wasm/parser/hoon :: parser -/lib/wasm/validator/hoon :: validator -/lib/wasm/runner/op-def/hoon :: op-def -/lib/wasm/runner/engine/hoon :: engine +/sur/wasm/wasm/hoon :: +wasm-sur +/sur/wasm/engine/hoon :: +engine-sur +/sur/wasm/lia/hoon :: +lia-sur +/lib/wasm/parser/hoon :: +parser +/lib/wasm/validator/hoon :: +validator +/lib/wasm/runner/op-def/hoon :: +op-def +/lib/wasm/runner/engine/hoon :: +engine ``` Thus if you imported `/lib/wasm/lia/hoon` as `wasm`, you can get the core with Lia types as `lia-sur:wasm`. From 7829e7f071d45309bcce55c188acf77f56048dd5 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 12:05:20 +0100 Subject: [PATCH 41/57] Expand on Lia --- .../build-on-urbit/wasm-walkthrough/overview.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index fa98708d..d87b286b 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -63,14 +63,14 @@ In our case, we'll have to write our own bindings manually in Hoon. We'll cover ## Lia -The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Urbit's commitments to determinism and referential transparency. UrWasm solves this by executing compiled Wasm in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages Wasm's handful of nondeterministic edge-cases such that the same inputs to a Wasm function will always result in the same output. The interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute Wasm code at near-native speeds. - -* Determinism solved by Lia - * [urwasm-jetting.md](https://gist.github.com/Quodss/196a4deb3e24a652c021469d2c4544fb) - * Jetting - * Motivation - * Higher level interpreting function - * Lia interpreter +The main theoretical blocker to executing non-Hoon code on Urbit was that doing so would violate Arvo's commitments to determinism. Some Wasm instructions like `memory.grow` and floating-point operators have non-deterministic behavior. + +UrWasm solves this by executing compiled Wasm in Lia ("Language for Invocation of (web)Assembly"), a tiny interpreter that manages Wasm's handful of nondeterministic edge-cases such that the same inputs to a Wasm function will always result in the same output. The Lia interpreter itself is small enough to be [jetted](../runtime/jetting.md), such that Urbit can execute Wasm code at near-native speeds. + +Lia handles Wasm's non-determinism like so: +- Some numerical operations may return an empty set of values; this is often equivalent to `undefined` in other languages, e.g. when the Wasm VM attempts to divide by zero. Whenever a function returns an empty set of values, Lia treats it as an error and deterministically crashes. +- Some numerical operations may legally reutrn one of a set of values, from which the Wasm VM may select any. {TODO - how does Lia select this deterministically?} +- Wasm's `memory.grow` may or may not grow the memory; in some cases the choice is left to the host environment like the browser. In Lia, `memory.grow` will always increase the length of linear memory if the module's limits allow. ## UrWasm Structure From 3f1467f48e6af0259ba49030a6652581c5008cb9 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 12:06:08 +0100 Subject: [PATCH 42/57] Fix typo --- content/build-on-urbit/wasm-walkthrough/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index d87b286b..dff15e71 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -69,7 +69,7 @@ UrWasm solves this by executing compiled Wasm in Lia ("Language for Invocation o Lia handles Wasm's non-determinism like so: - Some numerical operations may return an empty set of values; this is often equivalent to `undefined` in other languages, e.g. when the Wasm VM attempts to divide by zero. Whenever a function returns an empty set of values, Lia treats it as an error and deterministically crashes. -- Some numerical operations may legally reutrn one of a set of values, from which the Wasm VM may select any. {TODO - how does Lia select this deterministically?} +- Some numerical operations may legally return one of a set of values, from which the Wasm VM may select any. {TODO - how does Lia select this deterministically?} - Wasm's `memory.grow` may or may not grow the memory; in some cases the choice is left to the host environment like the browser. In Lia, `memory.grow` will always increase the length of linear memory if the module's limits allow. ## UrWasm Structure From 6b30b0349517487e26472e92efe7b53baf7bebdd Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 12:28:35 +0100 Subject: [PATCH 43/57] ABbreviated Core Descriptions --- .../reference/lib-wasm-runner-op-def.md | 68 +++++++++++++++---- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md index 3c7b6c03..31297c79 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md @@ -633,16 +633,20 @@ Reference instruction implementations: ++ simd =< fetch-vec |% - :: ++rope: ++rip but with leading zeros. - :: Takes bloq size, number of blocks and - :: an atom to dissasemble - :: - :: ... + :: +rope + :: +fetch-vec + :: +load + :: +load-lane + :: +store + :: +store-lane + :: +const + :: +shuffle + :: +extract + :: +replace + :: +plain -- ``` -{TODO include comments with +foo, +bar arms in code sample above? did that in another file and i quite like that convention; you get a low-res picture of the whole thing at once to fill in as you read, easier to navigate} - SIMD vector instruction implementations for 128-bit vectors. Handles vector load/store operations, lane manipulation, and parallel arithmetic operations on packed data. ### `+rope` {#rope} @@ -1023,12 +1027,19 @@ SIMD instruction type categories for organizing vector operations. |: i=`$>(vec-unary:kind instr-vec)`[%not ~] ^- $-(@ @) ?- -.i - :: ... + :: %splat + :: %not + :: %any-true + :: %all-true + :: %bitmask + :: %extadd + :: %extend + :: %convert + :: %demote + :: %promote == ``` -{TODO - comment with %foo, %bar branches analogous to core with commented out +foo, +bar etc.} - Unary vector operations including splat, bitwise not, truth testing, type conversions, and lane extensions. #### `+vec-bina:plain` {#vec-bina-plain} @@ -1038,7 +1049,16 @@ Unary vector operations including splat, bitwise not, truth testing, type conver |: i=`$>(vec-binary:kind instr-vec)`[%and ~] ^- $-([@ @] @) ?- -.i - :: ... + :: %swizzle + :: %and + :: %andnot + :: %or + :: %xor + :: %narrow + :: %shl + :: %shr + :: %extmul + :: %dot == ``` @@ -1051,7 +1071,14 @@ Binary vector operations including logical operations, lane narrowing, shifts, a |: i=`$>(lane-wise-unary:kind instr-vec)`[%popcnt ~] ^- $-(@ (unit @)) ?- -.i - :: ... + :: %abs + :: %neg + :: %popcnt + :: %ceil + :: %floor + :: %trunc + :: %nearest + :: %sqrt == ``` @@ -1064,7 +1091,22 @@ Resolve unary operation implementations for lane-wise vector operations. |: i=`$>(lane-wise-binary:kind instr-vec)`[%q15mul-r-sat ~] ^- $-([@ @] (unit @)) ?- -.i - :: ... + :: %eq + :: %ne + :: %lt + :: %gt + :: %le + :: %ge + :: %add + :: %sub + :: %min + :: %max + :: %avgr + :: %q15mul-r-sat + :: %mul + :: %div + :: %pmin + :: %pmax == ``` From c7c1f825f86f8f1edc3a98f6a1efdcc769b6b86b Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 12:46:20 +0100 Subject: [PATCH 44/57] Clarify Lia NaN handling --- content/build-on-urbit/wasm-walkthrough/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm-walkthrough/overview.md index dff15e71..93ea4de3 100644 --- a/content/build-on-urbit/wasm-walkthrough/overview.md +++ b/content/build-on-urbit/wasm-walkthrough/overview.md @@ -69,7 +69,7 @@ UrWasm solves this by executing compiled Wasm in Lia ("Language for Invocation o Lia handles Wasm's non-determinism like so: - Some numerical operations may return an empty set of values; this is often equivalent to `undefined` in other languages, e.g. when the Wasm VM attempts to divide by zero. Whenever a function returns an empty set of values, Lia treats it as an error and deterministically crashes. -- Some numerical operations may legally return one of a set of values, from which the Wasm VM may select any. {TODO - how does Lia select this deterministically?} +- Some numerical operations may legally return one of a set of values, from which the Wasm VM may select any. This typically occurs with floating-point operations that produce NaN results, where different implementations might return different NaN bit patterns. Lia preserves determinism by normalizing all NaN results to one type. - Wasm's `memory.grow` may or may not grow the memory; in some cases the choice is left to the host environment like the browser. In Lia, `memory.grow` will always increase the length of linear memory if the module's limits allow. ## UrWasm Structure From b4ee55e12ba47f8faec9b5fe2af5190d9ad43192 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 12:52:10 +0100 Subject: [PATCH 45/57] Split elem parser H3s --- .../reference/lib-wasm-parser.md | 226 +++++++++++++++++- 1 file changed, 222 insertions(+), 4 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md index 3e1dde5d..7a45d2c9 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -1314,7 +1314,7 @@ Parse element segment in one of eight different formats. Each format has differe Parse element kind (currently only function references references supported). -### `+elem-0` through +elem-7 {#elem-variants} +### `+elem-0` {#elem-0} ```hoon ++ elem-0 @@ -1324,11 +1324,229 @@ Parse element kind (currently only function references references supported). == ``` -Parse different element segment formats. +Parse active element segment with implicit table 0 and function indices. -### `+handle-elem-0` through +handle-elem-7 {#handle-elem-variants} +### `+elem-1` {#elem-1} -Handler functions that convert parsed element data into the standard [`$elem`](./wasm-data-types.md#elem) format, normalizing the different binary representations. +```hoon +++ elem-1 + %+ cook handle-elem-1 + ;~ pfix (just '\01') + ;~(plug elem-kind (vec u32)) + == +``` + +Parse passive element segment with element kind and function indices. + +### `+elem-2` {#elem-2} + +```hoon +++ elem-2 + %+ cook handle-elem-2 + ;~ pfix (just '\02') + ;~(plug u32 const-expr elem-kind (vec u32)) + == +``` + +Parse active element segment with explicit table index, offset expression, element kind, and function indices. + +### `+elem-3` {#elem-3} + +```hoon +++ elem-3 + %+ cook handle-elem-3 + ;~ pfix (just '\03') + ;~(plug elem-kind (vec u32)) + == +``` + +Parse declarative element segment with element kind and function indices. + +### `+elem-4` {#elem-4} + +```hoon +++ elem-4 + %+ cook handle-elem-4 + ;~ pfix (just '\04') + ;~(plug const-expr (vec expr)) + == +``` + +Parse active element segment with implicit table 0 and initialization expressions. + +### `+elem-5` {#elem-5} + +```hoon +++ elem-5 + %+ cook handle-elem-5 + ;~ pfix (just '\05') + ;~(plug ref-type (vec expr)) + == +``` + +Parse passive element segment with reference type and initialization expressions. + +### `+elem-6` {#elem-6} + +```hoon +++ elem-6 + %+ cook handle-elem-6 + ;~ pfix (just '\06') + ;~(plug u32 const-expr ref-type (vec expr)) + == +``` + +Parse active element segment with explicit table index, offset expression, reference type, and initialization expressions. + +### `+elem-7` {#elem-7} + +```hoon +++ elem-7 + %+ cook handle-elem-7 + ;~ pfix (just '\07') + ;~(plug ref-type (vec expr)) + == +``` + +Parse declarative element segment with reference type and initialization expressions. + +### `+handle-elem-0` {#handle-elem-0} + +```hoon +++ handle-elem-0 + |= [e=const-instr:sur y=(list @)] + ^- elem:sur + :+ %func + %+ turn y + |= y=@ + ^- $>(?(%ref-func %ref-null) instruction:sur) + [%ref-func y] + [%acti 0 e] +``` + +Convert parsed elem-0 data into standard [`$elem`](./wasm-data-types.md#elem) format with active mode, table 0, and function references. + +### `+handle-elem-1` {#handle-elem-1} + +```hoon +++ handle-elem-1 + |= [et=@ y=(list @)] + ^- elem:sur + :+ ?+ et ~|(%unrecognized-elem-kind !!) + %0x0 %func + == + %+ turn y + |= y=@ + ^- $>(?(%ref-func %ref-null) instruction:sur) + [%ref-func y] + [%pass ~] +``` + +Convert parsed elem-1 data into standard [`$elem`](./wasm-data-types.md#elem) format with passive mode and function references. + +### `+handle-elem-2` {#handle-elem-2} + +```hoon +++ handle-elem-2 + |= [x=@ e=const-instr:sur et=@ y=(list @)] + ^- elem:sur + :+ ?+ et ~|(%unrecognized-elem-kind !!) + %0x0 %func + == + %+ turn y + |= y=@ + ^- $>(?(%ref-func %ref-null) instruction:sur) + [%ref-func y] + [%acti x e] +``` + +Convert parsed elem-2 data into standard [`$elem`](./wasm-data-types.md#elem) format with active mode, explicit table index, and function references. + +### `+handle-elem-3` {#handle-elem-3} + +```hoon +++ handle-elem-3 + |= [et=@ y=(list @)] + ^- elem:sur + :+ ?+ et ~|(%unrecognized-elem-kind !!) + %0x0 %func + == + %+ turn y + |= y=@ + ^- $>(?(%ref-func %ref-null) instruction:sur) + [%ref-func y] + [%decl ~] +``` + +Convert parsed elem-3 data into standard [`$elem`](./wasm-data-types.md#elem) format with declarative mode and function references. + +### `+handle-elem-4` {#handle-elem-4} + +```hoon +++ handle-elem-4 + |= [e=const-instr:sur el=(list expression:sur)] + ^- elem:sur + :+ %func + %+ turn el + |= ex=expression:sur + ^- $>(?(%ref-func %ref-null) instruction:sur) + ?> ?=([[%ref-func *] ~] ex) + i.ex + [%acti 0 e] +``` + +Convert parsed elem-4 data into standard [`$elem`](./wasm-data-types.md#elem) format with active mode, table 0, and expression-based initialization. + +### `+handle-elem-5` {#handle-elem-5} + +```hoon +++ handle-elem-5 + |= [et=ref-type:sur el=(list expression:sur)] + ^- elem:sur + :+ et + %+ turn el + |= ex=expression:sur + ^- $>(?(%ref-func %ref-null) instruction:sur) + ?> ?=([[%ref-func *] ~] ex) + i.ex + [%pass ~] +``` + +Convert parsed elem-5 data into standard [`$elem`](./wasm-data-types.md#elem) format with passive mode and expression-based initialization. + +### `+handle-elem-6` {#handle-elem-6} + +```hoon +++ handle-elem-6 + |= [x=@ e=const-instr:sur et=ref-type:sur el=(list expression:sur)] + ^- elem:sur + :+ et + %+ turn el + |= ex=expression:sur + ^- $>(?(%ref-func %ref-null) instruction:sur) + ?> ?=([[%ref-func *] ~] ex) + i.ex + [%acti x e] +``` + +Convert parsed elem-6 data into standard [`$elem`](./wasm-data-types.md#elem) format with active mode, explicit table index, and expression-based initialization. + +### `+handle-elem-7` {#handle-elem-7} + +```hoon +++ handle-elem-7 + |= [et=ref-type:sur el=(list expression:sur)] + ^- elem:sur + :+ et + %+ turn el + |= ex=expression:sur + ^- $>(?(%ref-func %ref-null) instruction:sur) + ?> ?=([[%ref-func *] ~] ex) + i.ex + [%decl ~] +``` + +Convert parsed elem-7 data into standard [`$elem`](./wasm-data-types.md#elem) format with declarative mode and expression-based initialization. ### `+code-section` {#code-section} From 137d2b225f73b883b30e1ad3028c17f9787b96cd Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 13:05:31 +0100 Subject: [PATCH 46/57] Fix binary opcode formatting --- .../reference/lib-wasm-parser.md | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md index 7a45d2c9..e0becada 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -2,8 +2,6 @@ The `/lib/wasm/parser.hoon` library converts Wasm bytecode into UrWasm's Hoon types defined in [`+wasm-sur`](./wasm-data-types.md), which is nested in the imported [`/sur/wasm/lia.hoon`](./lia-data-types.md) file. This library implements parsing rules that follow the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/index.html) binary format. -{TODO Implements WebAssembly's [LEB128](https://en.wikipedia.org/wiki/LEB128) unsigned integer encoding.} - ## `+parser` {#parser} ```hoon @@ -359,13 +357,11 @@ First expression (true branch), followed by optional [`+else`](#else) and second ### `+end` {#end} -{TODO change `\0b` in prose to `0x0b` as in actual Wasm binary} - ```hoon ++ end (just '\0b') ``` -Parse Wasm `end` opcode (`\0b`). +Parse Wasm `end` opcode (`0x0B`). ### `+else` {#else} @@ -373,7 +369,7 @@ Parse Wasm `end` opcode (`\0b`). ++ else (just '\05') ``` -Parse Wasm `else` opcode (`\05`). +Parse Wasm `else` opcode (`0x05`). ### `+const-i32` {#const-i32} @@ -381,7 +377,7 @@ Parse Wasm `else` opcode (`\05`). ++ const-i32 (just '\41') ``` -Parse Wasm `i32.const` opcode (`\41`). +Parse Wasm `i32.const` opcode (`0x41`). ### `+const-i64` {#const-i64} @@ -389,7 +385,7 @@ Parse Wasm `i32.const` opcode (`\41`). ++ const-i64 (just '\42') ``` -Parse Wasm `i64.const` opcode (`\42`). +Parse Wasm `i64.const` opcode (`0x42`). ### `+const-f32` {#const-f32} @@ -397,7 +393,7 @@ Parse Wasm `i64.const` opcode (`\42`). ++ const-f32 (just '\43') ``` -Parse Wasm `f32.const` opcode (`\43`). +Parse Wasm `f32.const` opcode (`0x43`). ### `+const-f64` {#const-f64} @@ -405,7 +401,7 @@ Parse Wasm `f32.const` opcode (`\43`). ++ const-f64 (just '\44') ``` -Parse Wasm `f64.const` opcode (`\44`). +Parse Wasm `f64.const` opcode (`0x44`). ### `+block-op` {#block-op} @@ -413,7 +409,7 @@ Parse Wasm `f64.const` opcode (`\44`). ++ block-op (just '\02') ``` -Parse Wasm `block` opcode (`\02`). +Parse Wasm `block` opcode (`0x02`). ### `+loop-op` {#loop-op} @@ -421,7 +417,7 @@ Parse Wasm `block` opcode (`\02`). ++ loop-op (just '\03') ``` -Parse Wasm `loop` opcode (`\03`). +Parse Wasm `loop` opcode (`0x03`). ### `+if-op` {#if-op} @@ -429,7 +425,7 @@ Parse Wasm `loop` opcode (`\03`). ++ if-op (just '\04') ``` -Parse Wasm `if` opcode (`\04`). +Parse Wasm `if` opcode (`0x04`). ### `+form-ranges` {#form-ranges} @@ -1733,7 +1729,7 @@ Parse custom Wasm module sections (ignored during parsing). ++ magic (jest '\00asm') ``` -Parse Wasm magic number (`\00asm`). +Parse Wasm magic number (`0x00`, `0x61`, `0x73`, `0x6D`) which identifies this file as a Wasm module. ### `+version` {#version} From f22e38edbbc9d0b14cbb5e5f2cd16e14bd65c709 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 13:06:01 +0100 Subject: [PATCH 47/57] Remove last TODO --- .../wasm-walkthrough/reference/wasm-data-types.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md index 01e8ed75..84807639 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md @@ -806,8 +806,6 @@ Data segment for initializing the module's state. ++ datacnt-section (unit @) ``` -{TODO check the below} - Data count section of the Wasm module, which may optionally contain the number of data segments ([`$data`](#data)) in the module. This allows validators to check the index validity of the data section before trying to access it. ### `$opcode` {#opcode} From 71ac3c584f03a6578e35d09ef0fb6b5bc4735592 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 13:07:55 +0100 Subject: [PATCH 48/57] Fix intro --- .../reference/wasm-interpreter-data-types.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md index 72b2dbe2..cb94e9cc 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md @@ -1,10 +1,6 @@ # Wasm Interpreter Data Types -{??? not sure abt intro - not very deep / clear, LLM smell} - -UrWasm's engine layer, `+engine-sur`, contains the interpreter data types that represent Wasm modules in their executable form. - -While `+wasm-sur` implements the WebAssembly Core Specification, `+engine-sur` provides the runtime representation needed for execution, with optimized module structure and execution state management. +UrWasm's `+engine-sur` types represent Wasm modules in their executable form. While `+wasm-sur` implements the WebAssembly Core Specification, `+engine-sur` provides the runtime representation needed for execution, with some optimizations. ### `+engine-sur` {#engine-sur} From e99df0c49a6ade4de3fcde43b639c3e826a1b3c6 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 13:19:45 +0100 Subject: [PATCH 49/57] Clarify validator flops --- .../reference/lib-wasm-validator.md | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md index 9260ab02..89bc9bb9 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md @@ -51,25 +51,7 @@ List of all global variable types. -- ``` -Validation output types. - -??? - why are they flopped? - -## `$import` {#import} - -```hoon -+$ import - $: - funcs=(list func-type) :: flopped - tables=(list table) :: flopped - memo=(unit limits) - globs=glob-types :: flopped - == -``` - -??? - why flopped? - -Aggregated import validation results: +Validation output types. The `.funcs`, `.tables`, and `.globs` lists are built in reverse order during parsing, so must be `+flop`ped to get the right order. - `.funcs`: List of imported function types. - `.tables`: List of imported [`$table`s](./wasm-data-types.md#table). - `.memo`: Optional imported memory [`$limits`](./wasm-data-types.md#limits). @@ -81,9 +63,7 @@ Aggregated import validation results: +$ store import:output :: right order ``` -Validation store containing all available types in the correct order for validation context. - -??? - why does order matter here? +Validation store containing all available types in the correct order for validation context. Order matters because the store provides the validation context where imported items come first, followed by locally defined items, matching the WebAssembly spec's indexing requirements. ## `+result-form` {#result-form} From 180e22bbed6e90b0e1ba6cc0c4451400e464d8de Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 13:25:31 +0100 Subject: [PATCH 50/57] Remove Wasm parser questions --- .../wasm-walkthrough/reference/lib-wasm-parser.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md index e0becada..37f07b39 100644 --- a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md +++ b/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md @@ -451,8 +451,6 @@ Parse Wasm `if` opcode (`0x04`). Helper function that converts a list of sorted integers into a list of ranges (`?(@ [@ @])`). -??? - Used to optimize parsing by creating efficient lookup tables for opcodes. - ### `+instr` {#instr} ```hoon @@ -519,7 +517,7 @@ Main instruction parser. Uses `+stew` parser to switch on the given text to the == ``` -??? - Parse Wasm `select` expression with optional type annotation for vectors. +Parses a typed `select` instruction with explicit value types. ### `+br-table` {#br-table} From c1b869c1fd830e6cae398746b6227b38dd5d8c86 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 13:43:49 +0100 Subject: [PATCH 51/57] Rename folders, update summary --- content/SUMMARY.md | 12 ++++++++++++ .../{wasm-walkthrough => wasm}/README.md | 0 .../{wasm-walkthrough => wasm}/generator.md | 0 .../{wasm-walkthrough => wasm}/overview.md | 0 .../{wasm-walkthrough => wasm}/reference/README.md | 0 .../reference/lia-data-types.md | 0 .../reference/lib-wasm-lia.md | 0 .../reference/lib-wasm-parser.md | 0 .../reference/lib-wasm-runner-engine.md | 0 .../reference/lib-wasm-runner-op-def.md | 0 .../reference/lib-wasm-validator.md | 0 .../reference/wasm-data-types.md | 0 .../reference/wasm-interpreter-data-types.md | 0 13 files changed, 12 insertions(+) rename content/build-on-urbit/{wasm-walkthrough => wasm}/README.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/generator.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/overview.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/README.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/lia-data-types.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/lib-wasm-lia.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/lib-wasm-parser.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/lib-wasm-runner-engine.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/lib-wasm-runner-op-def.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/lib-wasm-validator.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/wasm-data-types.md (100%) rename content/build-on-urbit/{wasm-walkthrough => wasm}/reference/wasm-interpreter-data-types.md (100%) diff --git a/content/SUMMARY.md b/content/SUMMARY.md index 1ccb7b31..a4a1a806 100644 --- a/content/SUMMARY.md +++ b/content/SUMMARY.md @@ -8,6 +8,18 @@ * [Contents](build-on-urbit/contents.md) * [Environment Setup](build-on-urbit/environment.md) +* [WebAssembly](build-on-urbit/webassembly/README.md) + * [UrWasm Overview](build-on-urbit/wasm/overview.md) + * [Example Generator](build-on-urbit/wasm/generator.md) + * [UrWasm Reference](build-on-urbit/wasm/reference/README.md) + * [Wasm Data Types](build-on-urbit/wasm/wasm-data-types.md) + * [Wasm Interpreter Data Types](build-on-urbit/wasm/wasm-interpreter-data-types.md) + * [Lia Data Types](build-on-urbit/wasm/lia-data-types.md) + * [Lia Library](build-on-urbit/wasm/lib-wasm-lia.md) + * [Wasm Engine Library](build-on-urbit/wasm/lib-wasm-runner-engine.md) + * [Wasm Validator Library](build-on-urbit/wasm/lib-wasm-validator.md) + * [Wasm Parser Library](build-on-urbit/wasm/lib-wasm-parser.md) + * [Wasm Op Def Library](build-on-urbit/wasm/lib-wasm-runner-op-def.md) * [Hoon School](build-on-urbit/hoon-school/README.md) * [1. Hoon Syntax](build-on-urbit/hoon-school/B-syntax.md) * [2. Azimuth (Urbit ID)](build-on-urbit/hoon-school/C-azimuth.md) diff --git a/content/build-on-urbit/wasm-walkthrough/README.md b/content/build-on-urbit/wasm/README.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/README.md rename to content/build-on-urbit/wasm/README.md diff --git a/content/build-on-urbit/wasm-walkthrough/generator.md b/content/build-on-urbit/wasm/generator.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/generator.md rename to content/build-on-urbit/wasm/generator.md diff --git a/content/build-on-urbit/wasm-walkthrough/overview.md b/content/build-on-urbit/wasm/overview.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/overview.md rename to content/build-on-urbit/wasm/overview.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/README.md b/content/build-on-urbit/wasm/reference/README.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/README.md rename to content/build-on-urbit/wasm/reference/README.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md b/content/build-on-urbit/wasm/reference/lia-data-types.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/lia-data-types.md rename to content/build-on-urbit/wasm/reference/lia-data-types.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md b/content/build-on-urbit/wasm/reference/lib-wasm-lia.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-lia.md rename to content/build-on-urbit/wasm/reference/lib-wasm-lia.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md b/content/build-on-urbit/wasm/reference/lib-wasm-parser.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-parser.md rename to content/build-on-urbit/wasm/reference/lib-wasm-parser.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md b/content/build-on-urbit/wasm/reference/lib-wasm-runner-engine.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-engine.md rename to content/build-on-urbit/wasm/reference/lib-wasm-runner-engine.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md b/content/build-on-urbit/wasm/reference/lib-wasm-runner-op-def.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-runner-op-def.md rename to content/build-on-urbit/wasm/reference/lib-wasm-runner-op-def.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md b/content/build-on-urbit/wasm/reference/lib-wasm-validator.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/lib-wasm-validator.md rename to content/build-on-urbit/wasm/reference/lib-wasm-validator.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md b/content/build-on-urbit/wasm/reference/wasm-data-types.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/wasm-data-types.md rename to content/build-on-urbit/wasm/reference/wasm-data-types.md diff --git a/content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md b/content/build-on-urbit/wasm/reference/wasm-interpreter-data-types.md similarity index 100% rename from content/build-on-urbit/wasm-walkthrough/reference/wasm-interpreter-data-types.md rename to content/build-on-urbit/wasm/reference/wasm-interpreter-data-types.md From bd8d87df8000fb7ff0a4c3ca5a3e8f8d7d01a7e0 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 14:30:39 +0100 Subject: [PATCH 52/57] Move reference stuff to base docs --- content/SUMMARY.md | 24 +++++++++---------- .../base/wasm}/README.md | 0 .../base/wasm}/lia-data-types.md | 0 .../base/wasm}/lib-wasm-lia.md | 0 .../base/wasm}/lib-wasm-parser.md | 0 .../base/wasm}/lib-wasm-runner-engine.md | 0 .../base/wasm}/lib-wasm-runner-op-def.md | 0 .../base/wasm}/lib-wasm-validator.md | 0 .../base/wasm}/wasm-data-types.md | 0 .../base/wasm}/wasm-interpreter-data-types.md | 0 10 files changed, 12 insertions(+), 12 deletions(-) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/README.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/lia-data-types.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/lib-wasm-lia.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/lib-wasm-parser.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/lib-wasm-runner-engine.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/lib-wasm-runner-op-def.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/lib-wasm-validator.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/wasm-data-types.md (100%) rename content/{build-on-urbit/wasm/reference => urbit-os/base/wasm}/wasm-interpreter-data-types.md (100%) diff --git a/content/SUMMARY.md b/content/SUMMARY.md index a4a1a806..bd1e52e7 100644 --- a/content/SUMMARY.md +++ b/content/SUMMARY.md @@ -8,18 +8,6 @@ * [Contents](build-on-urbit/contents.md) * [Environment Setup](build-on-urbit/environment.md) -* [WebAssembly](build-on-urbit/webassembly/README.md) - * [UrWasm Overview](build-on-urbit/wasm/overview.md) - * [Example Generator](build-on-urbit/wasm/generator.md) - * [UrWasm Reference](build-on-urbit/wasm/reference/README.md) - * [Wasm Data Types](build-on-urbit/wasm/wasm-data-types.md) - * [Wasm Interpreter Data Types](build-on-urbit/wasm/wasm-interpreter-data-types.md) - * [Lia Data Types](build-on-urbit/wasm/lia-data-types.md) - * [Lia Library](build-on-urbit/wasm/lib-wasm-lia.md) - * [Wasm Engine Library](build-on-urbit/wasm/lib-wasm-runner-engine.md) - * [Wasm Validator Library](build-on-urbit/wasm/lib-wasm-validator.md) - * [Wasm Parser Library](build-on-urbit/wasm/lib-wasm-parser.md) - * [Wasm Op Def Library](build-on-urbit/wasm/lib-wasm-runner-op-def.md) * [Hoon School](build-on-urbit/hoon-school/README.md) * [1. Hoon Syntax](build-on-urbit/hoon-school/B-syntax.md) * [2. Azimuth (Urbit ID)](build-on-urbit/hoon-school/C-azimuth.md) @@ -110,6 +98,9 @@ * [Serving a JS Game](build-on-urbit/userspace/examples/flap.md) * [Ship Monitoring](build-on-urbit/userspace/examples/ahoy.md) * [Styled Text](build-on-urbit/userspace/examples/track7.md) +* [WebAssembly](build-on-urbit/webassembly/README.md) + * [UrWasm Overview](build-on-urbit/wasm/overview.md) + * [Example Generator](build-on-urbit/wasm/generator.md) ## Urbit ID @@ -155,6 +146,15 @@ * [Poke Agent](urbit-os/base/threads/examples/poke-agent.md) * [Scry](urbit-os/base/threads/examples/scry.md) * [Take Fact](urbit-os/base/threads/examples/take-fact.md) + * [WebAssembly](urbit-os/base/wasm/README.md) + * [Lia Library](urbit-os/base/wasm/lib-wasm-lia.md) + * [Lia Types](urbit-os/base/wasm/lia-data-types.md) + * [Wasm Data Types](urbit-os/base/wasm/wasm-data-types.md) + * [Wasm Engine](urbit-os/base/wasm/lib-wasm-runner-engine.md) + * [Wasm Interpreter Types](urbit-os/base/wasm/wasm-interpreter-data-types.md) + * [Wasm Operator Definitions](urbit-os/base/wasm/lib-wasm-runner-op-def.md) + * [Wasm Parser](urbit-os/base/wasm/lib-wasm-parser.md) + * [Wasm Validator](urbit-os/base/wasm/lib-wasm-validator.md) * [Kernel](urbit-os/kernel/README.md) * [Arvo](urbit-os/kernel/arvo/README.md) * [Cryptography](urbit-os/kernel/arvo/cryptography.md) diff --git a/content/build-on-urbit/wasm/reference/README.md b/content/urbit-os/base/wasm/README.md similarity index 100% rename from content/build-on-urbit/wasm/reference/README.md rename to content/urbit-os/base/wasm/README.md diff --git a/content/build-on-urbit/wasm/reference/lia-data-types.md b/content/urbit-os/base/wasm/lia-data-types.md similarity index 100% rename from content/build-on-urbit/wasm/reference/lia-data-types.md rename to content/urbit-os/base/wasm/lia-data-types.md diff --git a/content/build-on-urbit/wasm/reference/lib-wasm-lia.md b/content/urbit-os/base/wasm/lib-wasm-lia.md similarity index 100% rename from content/build-on-urbit/wasm/reference/lib-wasm-lia.md rename to content/urbit-os/base/wasm/lib-wasm-lia.md diff --git a/content/build-on-urbit/wasm/reference/lib-wasm-parser.md b/content/urbit-os/base/wasm/lib-wasm-parser.md similarity index 100% rename from content/build-on-urbit/wasm/reference/lib-wasm-parser.md rename to content/urbit-os/base/wasm/lib-wasm-parser.md diff --git a/content/build-on-urbit/wasm/reference/lib-wasm-runner-engine.md b/content/urbit-os/base/wasm/lib-wasm-runner-engine.md similarity index 100% rename from content/build-on-urbit/wasm/reference/lib-wasm-runner-engine.md rename to content/urbit-os/base/wasm/lib-wasm-runner-engine.md diff --git a/content/build-on-urbit/wasm/reference/lib-wasm-runner-op-def.md b/content/urbit-os/base/wasm/lib-wasm-runner-op-def.md similarity index 100% rename from content/build-on-urbit/wasm/reference/lib-wasm-runner-op-def.md rename to content/urbit-os/base/wasm/lib-wasm-runner-op-def.md diff --git a/content/build-on-urbit/wasm/reference/lib-wasm-validator.md b/content/urbit-os/base/wasm/lib-wasm-validator.md similarity index 100% rename from content/build-on-urbit/wasm/reference/lib-wasm-validator.md rename to content/urbit-os/base/wasm/lib-wasm-validator.md diff --git a/content/build-on-urbit/wasm/reference/wasm-data-types.md b/content/urbit-os/base/wasm/wasm-data-types.md similarity index 100% rename from content/build-on-urbit/wasm/reference/wasm-data-types.md rename to content/urbit-os/base/wasm/wasm-data-types.md diff --git a/content/build-on-urbit/wasm/reference/wasm-interpreter-data-types.md b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md similarity index 100% rename from content/build-on-urbit/wasm/reference/wasm-interpreter-data-types.md rename to content/urbit-os/base/wasm/wasm-interpreter-data-types.md From 4af426fdf416c7492807a04d10cf1d54c9ab6cdb Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 14:42:52 +0100 Subject: [PATCH 53/57] READMEs --- content/build-on-urbit/wasm/README.md | 7 +++---- content/urbit-os/base/wasm/README.md | 13 +++++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/content/build-on-urbit/wasm/README.md b/content/build-on-urbit/wasm/README.md index eda4e1d6..de90f2e0 100644 --- a/content/build-on-urbit/wasm/README.md +++ b/content/build-on-urbit/wasm/README.md @@ -17,8 +17,7 @@ layout: Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any Wasm-compatible language like Rust, Python, and Go. -These docs cover: -- An [overview](./overview.md) of Wasm and how it interacts with Urbit. -- [Example usage](./generator.md) of a Wasm module sort a large list. -- UrWasm data types and library [reference](./reference). +This section includes an [overview](./overview.md) of Wasm and how it can be run on Urbit. It also includes a trivial [example](./generator.md) of a Hoon generator using a Wasm module to sort a list. + +For a thorough description of UrWasm's types and libraries, see the [`%base`](../../urbit-os/base/wasm/README.md) docs. diff --git a/content/urbit-os/base/wasm/README.md b/content/urbit-os/base/wasm/README.md index d1c58b50..ab1a3bb7 100644 --- a/content/urbit-os/base/wasm/README.md +++ b/content/urbit-os/base/wasm/README.md @@ -21,11 +21,8 @@ This reference section documents UrWasm's data types and library functionality. - [Lia data types](./lia-data-types.md) ## Libraries -- Wasm parser -- Wasm validator -- Wasm operator -- Wasm interpreter -- Lia interpreter - -## Jets -- foobar +- [Wasm parser](./lib-wasm-parser.md) +- [Wasm validator](./lib-wasm-validator.md) +- [Wasm operator definitions](./lib-wasm-runner-op-def.md) +- [Wasm interpreter](./wasm-interpreter-data-types.md) +- [Lia interpreter](./lib-wasm-lia.md) From fc2615b9475a93316c7b82744ec6dcdc8bffad35 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 14:44:18 +0100 Subject: [PATCH 54/57] Change overview title --- content/build-on-urbit/wasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/build-on-urbit/wasm/README.md b/content/build-on-urbit/wasm/README.md index de90f2e0..1458aaa1 100644 --- a/content/build-on-urbit/wasm/README.md +++ b/content/build-on-urbit/wasm/README.md @@ -13,7 +13,7 @@ layout: visible: true --- -# Wasm Walkthrough +# WebAssembly Walkthrough Urbit's WebAssembly affordances (collectively known as "UrWasm") enables Hoon developers to leverage pre-existing libraries from any Wasm-compatible language like Rust, Python, and Go. From 721f26bb2a54dd95b49cbc995eb2f432f7be26a8 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 14:58:34 +0100 Subject: [PATCH 55/57] Descriptions --- content/build-on-urbit/wasm/README.md | 2 +- content/build-on-urbit/wasm/generator.md | 15 +++++++++++++++ content/build-on-urbit/wasm/overview.md | 15 +++++++++++++++ content/urbit-os/base/wasm/README.md | 15 +++++++++++++++ content/urbit-os/base/wasm/lia-data-types.md | 15 +++++++++++++++ content/urbit-os/base/wasm/lib-wasm-lia.md | 15 +++++++++++++++ content/urbit-os/base/wasm/lib-wasm-parser.md | 15 +++++++++++++++ .../base/wasm/lib-wasm-runner-engine.md | 15 +++++++++++++++ .../base/wasm/lib-wasm-runner-op-def.md | 17 ++++++++++++++++- .../urbit-os/base/wasm/lib-wasm-validator.md | 15 +++++++++++++++ content/urbit-os/base/wasm/wasm-data-types.md | 16 +++++++++++++++- .../base/wasm/wasm-interpreter-data-types.md | 15 +++++++++++++++ 12 files changed, 167 insertions(+), 3 deletions(-) diff --git a/content/build-on-urbit/wasm/README.md b/content/build-on-urbit/wasm/README.md index 1458aaa1..36d1ee87 100644 --- a/content/build-on-urbit/wasm/README.md +++ b/content/build-on-urbit/wasm/README.md @@ -1,5 +1,5 @@ --- -description: "foobarbaz" +description: "WebAssembly tutorials" layout: title: visible: true diff --git a/content/build-on-urbit/wasm/generator.md b/content/build-on-urbit/wasm/generator.md index cc2ab5b6..50e157c8 100644 --- a/content/build-on-urbit/wasm/generator.md +++ b/content/build-on-urbit/wasm/generator.md @@ -1,3 +1,18 @@ +--- +description: "Example of a Hoon generator using an imported Wasm module" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # UrWasm Generator Example Let's use UrWasm to write a generator that can quickly sort a large list of 64-bit integers in ascending order. diff --git a/content/build-on-urbit/wasm/overview.md b/content/build-on-urbit/wasm/overview.md index 93ea4de3..b4bc58a7 100644 --- a/content/build-on-urbit/wasm/overview.md +++ b/content/build-on-urbit/wasm/overview.md @@ -1,3 +1,18 @@ +--- +description: "Overview of the UrWasm project, goals, structure" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # UrWasm Overview Onboarding new developers onto Urbit necessarily involves teaching them [Hoon](../../hoon/why-hoon.md). Whatever Hoon's merits as a systems programming language, the time commitment to understanding the language enough to be productive is an obvious barrier to entry. diff --git a/content/urbit-os/base/wasm/README.md b/content/urbit-os/base/wasm/README.md index ab1a3bb7..62037a86 100644 --- a/content/urbit-os/base/wasm/README.md +++ b/content/urbit-os/base/wasm/README.md @@ -1,3 +1,18 @@ +--- +description: "UrWasm reference section, including data types and libraries" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # UrWasm Reference The UrWasm project is structured as a series of nested cores, innermost to outermost: diff --git a/content/urbit-os/base/wasm/lia-data-types.md b/content/urbit-os/base/wasm/lia-data-types.md index 71f21d25..67f1cf44 100644 --- a/content/urbit-os/base/wasm/lia-data-types.md +++ b/content/urbit-os/base/wasm/lia-data-types.md @@ -1,3 +1,18 @@ +--- +description: "Data types for Lia, Urbit's deterministic Wasm interpreter" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # Lia Data Types The `+lia-sur` core builds on top of `+wasm-sur` and `+engine-sur` to define Lia's monadic, deterministic approach to making Wasm function calls and handling their results. diff --git a/content/urbit-os/base/wasm/lib-wasm-lia.md b/content/urbit-os/base/wasm/lib-wasm-lia.md index 236d81b3..d660f246 100644 --- a/content/urbit-os/base/wasm/lib-wasm-lia.md +++ b/content/urbit-os/base/wasm/lib-wasm-lia.md @@ -1,3 +1,18 @@ +--- +description: "Reference for UrWasm's Lia interpreter" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + ## Lia Interpreter The `/lib/wasm/lia.hoon` library implements Lia (Language for Invocation of webAssembly), a high-level scripting interface for executing WebAssembly modules within Urbit. Lia provides deterministic execution of Wasm code while maintaining performance through caching and efficient state management. diff --git a/content/urbit-os/base/wasm/lib-wasm-parser.md b/content/urbit-os/base/wasm/lib-wasm-parser.md index 37f07b39..cf689b87 100644 --- a/content/urbit-os/base/wasm/lib-wasm-parser.md +++ b/content/urbit-os/base/wasm/lib-wasm-parser.md @@ -1,3 +1,18 @@ +--- +description: "Reference for UrWasm's parsing library" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # Wasm Parser The `/lib/wasm/parser.hoon` library converts Wasm bytecode into UrWasm's Hoon types defined in [`+wasm-sur`](./wasm-data-types.md), which is nested in the imported [`/sur/wasm/lia.hoon`](./lia-data-types.md) file. This library implements parsing rules that follow the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/index.html) binary format. diff --git a/content/urbit-os/base/wasm/lib-wasm-runner-engine.md b/content/urbit-os/base/wasm/lib-wasm-runner-engine.md index 27de726d..f9a238f5 100644 --- a/content/urbit-os/base/wasm/lib-wasm-runner-engine.md +++ b/content/urbit-os/base/wasm/lib-wasm-runner-engine.md @@ -1,3 +1,18 @@ +--- +description: "Reference for UrWasm's interpreter library" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # Wasm Runner Engine The `+engine` core implements the core WebAssembly interpreter engine. This runs module instantiation, function invocation, and the main evaluation loop for WebAssembly instructions. diff --git a/content/urbit-os/base/wasm/lib-wasm-runner-op-def.md b/content/urbit-os/base/wasm/lib-wasm-runner-op-def.md index 31297c79..e6b3fdc5 100644 --- a/content/urbit-os/base/wasm/lib-wasm-runner-op-def.md +++ b/content/urbit-os/base/wasm/lib-wasm-runner-op-def.md @@ -1,4 +1,19 @@ -# Wasm Runner Op-Def +--- +description: "Reference for UrWasm's Wasm operation definitions" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + +# Wasm Runner Operation Definitions The `/lib/wasm/runner/op-def` library implements WebAssembly instruction definitions as functions that transform the [`$local-state`](./wasm-interpreter-data-types.md#local-state) of the UrWasm interpreter. This library serves as the operational semantics for WebAssembly instructions, defining how each instruction modifies the interpreter's execution state. diff --git a/content/urbit-os/base/wasm/lib-wasm-validator.md b/content/urbit-os/base/wasm/lib-wasm-validator.md index 89bc9bb9..89b7d332 100644 --- a/content/urbit-os/base/wasm/lib-wasm-validator.md +++ b/content/urbit-os/base/wasm/lib-wasm-validator.md @@ -1,3 +1,18 @@ +--- +description: "Reference for UrWasm's Wasm module validator library" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # Wasm Validator The `+validator` library validates WebAssembly modules for correctness according to the [WebAssembly Core Specification](https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/valid/index.html). It performs static analysis to ensure type safety, proper memory access, and correct control flow before execution. diff --git a/content/urbit-os/base/wasm/wasm-data-types.md b/content/urbit-os/base/wasm/wasm-data-types.md index 84807639..aac5d95a 100644 --- a/content/urbit-os/base/wasm/wasm-data-types.md +++ b/content/urbit-os/base/wasm/wasm-data-types.md @@ -1,5 +1,19 @@ -# Wasm Data Types +--- +description: "Foundational Wasm types" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- +# Wasm Data Types UrWasm's inner core, `+wasm-sur`, contains the foundational Wasm types. diff --git a/content/urbit-os/base/wasm/wasm-interpreter-data-types.md b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md index cb94e9cc..d28b1a12 100644 --- a/content/urbit-os/base/wasm/wasm-interpreter-data-types.md +++ b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md @@ -1,3 +1,18 @@ +--- +description: "Types for Wasm code in its executable form" +layout: + title: + visible: true + description: + visible: false + tableOfContents: + visible: true + outline: + visible: true + pagination: + visible: true +--- + # Wasm Interpreter Data Types UrWasm's `+engine-sur` types represent Wasm modules in their executable form. While `+wasm-sur` implements the WebAssembly Core Specification, `+engine-sur` provides the runtime representation needed for execution, with some optimizations. From d9525f0cac50109be09354df5d7f1f2eaba26c63 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 15:07:31 +0100 Subject: [PATCH 56/57] Fix broken links --- content/SUMMARY.md | 2 +- content/build-on-urbit/wasm/generator.md | 4 ++-- content/build-on-urbit/wasm/overview.md | 2 +- content/urbit-os/base/wasm/wasm-data-types.md | 2 +- content/urbit-os/base/wasm/wasm-interpreter-data-types.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/content/SUMMARY.md b/content/SUMMARY.md index bd1e52e7..d9ee3906 100644 --- a/content/SUMMARY.md +++ b/content/SUMMARY.md @@ -98,7 +98,7 @@ * [Serving a JS Game](build-on-urbit/userspace/examples/flap.md) * [Ship Monitoring](build-on-urbit/userspace/examples/ahoy.md) * [Styled Text](build-on-urbit/userspace/examples/track7.md) -* [WebAssembly](build-on-urbit/webassembly/README.md) +* [WebAssembly](build-on-urbit/wasm/README.md) * [UrWasm Overview](build-on-urbit/wasm/overview.md) * [Example Generator](build-on-urbit/wasm/generator.md) diff --git a/content/build-on-urbit/wasm/generator.md b/content/build-on-urbit/wasm/generator.md index 50e157c8..7c41b34c 100644 --- a/content/build-on-urbit/wasm/generator.md +++ b/content/build-on-urbit/wasm/generator.md @@ -210,7 +210,7 @@ Below, we build Lia's `+run-once` core and run it on our imported `.wasm-bin` mo %^ (run-once yil-mold acc-mold) [wasm-bin [~ ~]] %$ ``` -Some more boilerplate. Hoon developers will recognize `.m` by analogy to the `.m` from the boilerplate often seen in [threads](../../../urbit-os/base/threads/README.md). `.arrows` is our built [`+arrows`](./reference/lib-wasm-lia.md#arrows) core from Lia, and we expose that namespace with [`=,`](../../../hoon/rune/tis.md#tiscom) for convenient usage later. +Some more boilerplate. Hoon developers will recognize `.m` by analogy to the `.m` from the boilerplate often seen in [threads](../../urbit-os/base/threads/README.md). `.arrows` is our built [`+arrows`](../../urbit-os/base/wasm/lib-wasm-lia.md#arrows) core from Lia, and we expose that namespace with [`=,`](../../../hoon/rune/tis.md#tiscom) for convenient usage later. ```hoon :: define the monadic interface for the script @@ -245,7 +245,7 @@ With that out of the way we can now interact with Wasm VM, replicating steps 1-4 ;< vec-out=octs try:m (memread &1.ptr-len (mul 8 &2.ptr-len)) ``` -Now we split the resulting octets atom (`$octs`, a cell of byte length and data) into a list of 64-bit atoms with [`+rip`](../../../hoon/stdlib/2c.md) and add missing trailing zeroes if necessary. (Note that UrWasm's [`+rope`](./reference/lib-wasm-runner-op-def.md#rope) would preserve the zeroes.) +Now we split the resulting octets atom (`$octs`, a cell of byte length and data) into a list of 64-bit atoms with [`+rip`](../../../hoon/stdlib/2c.md) and add missing trailing zeroes if necessary. (Note that UrWasm's [`+rope`](../../../urbit-os/base/wasm/lib-wasm-runner-op-def.md#rope) "BROKEN_LINK" would preserve the zeroes.) ```hoon :: rip the octet stream into a list of 64-bit atoms diff --git a/content/build-on-urbit/wasm/overview.md b/content/build-on-urbit/wasm/overview.md index b4bc58a7..b86fd788 100644 --- a/content/build-on-urbit/wasm/overview.md +++ b/content/build-on-urbit/wasm/overview.md @@ -116,5 +116,5 @@ All cores except `/lib/wasm/lia/hoon`, are additionally wrapped in one-armed cor Thus if you imported `/lib/wasm/lia/hoon` as `wasm`, you can get the core with Lia types as `lia-sur:wasm`. -UrWasm's data types and functionality are covered in detail in the [reference](./reference/README.md) section. +UrWasm's data types and functionality are covered in detail in the [reference](../../urbit-os/base/wasm/README.md) section. diff --git a/content/urbit-os/base/wasm/wasm-data-types.md b/content/urbit-os/base/wasm/wasm-data-types.md index aac5d95a..bfdf68a9 100644 --- a/content/urbit-os/base/wasm/wasm-data-types.md +++ b/content/urbit-os/base/wasm/wasm-data-types.md @@ -157,7 +157,7 @@ Type annotation for lanes (memory elements) in a 128-bit (`@H`) register. Includ Type union of all Wasm instructions. Instructions are categorized here by their operand patterns: -- `%vec`: Vector instructions. (See [`$instr-vec`]($instr-vec).) +- `%vec`: Vector instructions. (See [`$instr-vec`](#instr-vec).) - [`$instr-short`](#instr-short): Non-numeric Wasm instructions. - [`$instr-num`](#instr-num): Standard Wasm instructions categorized by arity. - [`$instr-dbug`](#instr-dbug): Debugging. diff --git a/content/urbit-os/base/wasm/wasm-interpreter-data-types.md b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md index d28b1a12..22433ab4 100644 --- a/content/urbit-os/base/wasm/wasm-interpreter-data-types.md +++ b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md @@ -66,7 +66,7 @@ Wasm [`$module`](./wasm-data-types.md#module) as seen by the engine. Some sectio == ``` -Unlike `+wasm-sur`'s [`$function`](./wasm-data-types.md#function), this includes both the function signature and its implementation merged together: +This includes both the function signature and its implementation merged together: - `.type-id`: Index into the [`$type-section`](./wasm-data-types.md#type-section) for this function's signature. - `.locals`: Local variables for this function. - [`.expression`](./wasm-data-types.md#expression): The function body as a sequence of [`$instruction`s](./wasm-data-types.md#instruction). From 61265a4b72390fa881262d91e7fd339977a61153 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Mon, 18 Aug 2025 15:14:49 +0100 Subject: [PATCH 57/57] Fix some formatting --- content/urbit-os/base/wasm/wasm-interpreter-data-types.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/urbit-os/base/wasm/wasm-interpreter-data-types.md b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md index 22433ab4..0680f029 100644 --- a/content/urbit-os/base/wasm/wasm-interpreter-data-types.md +++ b/content/urbit-os/base/wasm/wasm-interpreter-data-types.md @@ -52,9 +52,9 @@ Wrapper arm around the engine types, making them addressable by limb resolution ``` Wasm [`$module`](./wasm-data-types.md#module) as seen by the engine. Some sections have been removed or modified for efficiency: -- [`$code-section](./wasm-data-types.md#code-section) is merged into the function section. -- [`$datacnt-section](./wasm-data-types.md#datacnt-section) is removed as it's not needed during execution. -- [`$import-section](./wasm-data-types.md#import-section) is restructured for runtime resolution. +- [`$code-section`](./wasm-data-types.md#code-section) is merged into the function section. +- [`$datacnt-section`](./wasm-data-types.md#datacnt-section) is removed as it's not needed during execution. +- [`$import-section`](./wasm-data-types.md#import-section) is restructured for runtime resolution. ### `$function` {#function}