wai/wai-int-module is one WebAssembly module with the interface of waism §5 and nothing else: no import, one memory with a declared maximum, and every allocation trapping where memory cannot grow (R13). It decodes the integer payloads (WIV1, WIH1, WIA1, WIS1), int_synth, int_mlicpp, opus.dred.int and avatar.face through wai-rs's integer decoders, whose networks run on wai-ops/1; networks and weights arrive as each capability's set. - record/: the scalar and SIMD128 builds (7,099 vector instructions), named by SHA-256 in manifest.json, each held at the integer level by the Rust checker and check-module.mjs. build.sh builds both with the machine's paths remapped and checks both with both checkers. A build on another host has other bytes (the compiler's crate hashes take in each path dependency's absolute path and the host) and gives every case the same outcome. - corpus.json (corpus.py): every committed vector and refusal fixture of those capabilities, 120 cases, from the committed corpora. - host/ (wasmtime 50.0.1 Cranelift and Winch, Wasmi 2.0.0 with floats off), run-node.mjs and browser/run-browser.mjs run every case as a sink does and print one run digest; every run, on Linux x86_64, Linux arm64 and macOS arm64, gives the same. - plant.py plants a float or a relaxed vector instruction in a module, for the checkers. - waism §5, The set: one file as its bytes, several as their file sequence. avatars §6 names generator.wfg and identity.wfi; avatars §7.8, opus-dred §4.8 and determinism-tiers §5 state the module as a fabric. Co-Authored-By: Claude Opus 5.5 <[email protected]>
85 lines
3.9 KiB
Shell
85 lines
3.9 KiB
Shell
#!/usr/bin/env bash
|
|
# The operator-set module, built and checked: the module of record of WAISM's integer level.
|
|
#
|
|
# bash wai/wai-int-module/build.sh [--out DIR]
|
|
#
|
|
# Builds the crate for wasm32-unknown-unknown twice, each with its own target directory:
|
|
#
|
|
# wai_int.wasm scalar
|
|
# wai_int.simd128.wasm with SIMD128 (-C target-feature=+simd128): the same source, which
|
|
# the compiler lowers to WebAssembly's integer vector instructions
|
|
# where it can
|
|
#
|
|
# and holds each to the profile with both of its checkers (../wai-module-check): the Rust
|
|
# checker and check-module.mjs must each give `held` at the integer level, and the two must
|
|
# give the same verdict at both levels. Then it writes each to DIR (default: the target
|
|
# directory's `module/`) and prints its size and SHA-256. (`host/`'s `--count` says how many
|
|
# of each build's instructions are 128-bit vector instructions.)
|
|
#
|
|
# The module names no path of this machine: the checkout, the Cargo home and the toolchain are
|
|
# remapped to /open-standards, /cargo and /rustup, as reach/record's package was built. Its
|
|
# bytes still depend on where and on what it is built: the compiler's crate hashes take in the
|
|
# absolute path of each path dependency and the host the compiler runs on, and they order what
|
|
# it emits. So record/ is named by its SHA-256 (record/manifest.json), and what a build of
|
|
# this source on another host or from another checkout shows is the outputs: every case of
|
|
# the corpus the same.
|
|
#
|
|
# Needs bash, cargo with the wasm32-unknown-unknown target of the pinned toolchain, python3
|
|
# and node >= 18.
|
|
set -euo pipefail
|
|
|
|
CRATE="$(cd "$(dirname "$0")" && pwd -P)"
|
|
WAI="$(cd "$CRATE/.." && pwd -P)"
|
|
ROOT="$(cd "$WAI/.." && pwd -P)"
|
|
OUT=
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--out) OUT="$2"; shift 2 ;;
|
|
*) echo "usage: bash build.sh [--out DIR]" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
for t in cargo rustc node python3; do
|
|
command -v "$t" >/dev/null || { echo "wai-int-module: needs $t" >&2; exit 1; }
|
|
done
|
|
|
|
cd "$CRATE"
|
|
TARGET_BASE="${CARGO_TARGET_DIR:-$CRATE/target}"
|
|
OUT="${OUT:-$TARGET_BASE/module}"
|
|
mkdir -p "$OUT"
|
|
CARGO_HOME_DIR="$(cd "${CARGO_HOME:-$HOME/.cargo}" && pwd -P)"
|
|
RUSTUP_HOME_DIR="$(cd "${RUSTUP_HOME:-$HOME/.rustup}" && pwd -P)"
|
|
REMAP="--remap-path-prefix=$ROOT=/open-standards --remap-path-prefix=$CARGO_HOME_DIR=/cargo --remap-path-prefix=$RUSTUP_HOME_DIR=/rustup"
|
|
|
|
# The checker, built once.
|
|
cargo build --locked --release -q --manifest-path "$WAI/wai-module-check/Cargo.toml" --target-dir "$TARGET_BASE/checker"
|
|
CHECK="$TARGET_BASE/checker/release/wai-module-check"
|
|
|
|
for variant in scalar simd128; do
|
|
flags="$REMAP"
|
|
name=wai_int.wasm
|
|
if [ "$variant" = simd128 ]; then
|
|
flags="$flags -C target-feature=+simd128"
|
|
name=wai_int.simd128.wasm
|
|
fi
|
|
RUSTFLAGS="$flags" cargo build --locked --release --target wasm32-unknown-unknown --target-dir "$TARGET_BASE/$variant"
|
|
built="$TARGET_BASE/$variant/wasm32-unknown-unknown/release/wai_int_module.wasm"
|
|
[ -f "$built" ] || { echo "wai-int-module: the build left no $built" >&2; exit 1; }
|
|
rm -f "$OUT/$name"
|
|
# Both checkers, at both levels: held at the integer level, and the same verdict at each.
|
|
for level in integer float; do
|
|
rust=$("$CHECK" --level "$level" "$built" || true)
|
|
js=$(node "$WAI/wai-module-check/check-module.mjs" --level "$level" "$built" || true)
|
|
if [ "$rust" != "$js" ]; then
|
|
echo "wai-int-module: $variant at the $level level: the Rust checker says '$rust', check-module.mjs '$js'" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$rust" != held ]; then
|
|
echo "wai-int-module: $variant is not held at the $level level: $rust" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
cp "$built" "$OUT/$name"
|
|
sum=$(python3 -I -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$OUT/$name")
|
|
size=$(wc -c < "$OUT/$name" | tr -d ' ')
|
|
echo "wai-int-module: $OUT/$name: $size bytes, SHA-256 $sum, held at the integer level by both checkers"
|
|
done
|