Skip to content

[Feature] ADR-0026: lower native Wasm.Int64 and packed numeric-array intrinsics - #47

Open
harryprayiv wants to merge 26 commits into
purs-wasm:mainfrom
harryprayiv:draft_PR
Open

harryprayiv wants to merge 26 commits into
purs-wasm:mainfrom
harryprayiv:draft_PR

Conversation

@harryprayiv

Copy link
Copy Markdown
Contributor

Draft, and deliberately ahead of its dependency. This is the compiler-first
half of the coordinated pair (the merge order you confirmed on the wasm-base PR),
so I'm putting it up before wasm-base v0.2.0 is tagged on purs-wasm. That means
the pin can't resolve in CI yet and the e2e suite can't run here. I've verified it
locally by pointing the wasm-base pin at my fork (which has the v0.2.0 content):
the compiler builds, the e2e fixtures pass, and a downstream pure-PureScript Keccak
built on these intrinsics passes the NIST SHA-3 vectors on wasm. Raising it now so
we can review and sort the release/tag ordering together.

What & why

Compiler support for the wasm-base v0.2.0 primitive families, lowered to native
wasm: Wasm.Int64 (an i64 scalar) and the packed unboxed numeric arrays
Wasm.I32Array / Wasm.F64Array / Wasm.I64Array, so an Int / Number /
Int64 array carries no per-element box (unlike Wasm.Array's $Vals). Per-file
detail is in the commit.

What changed:

  • Intrinsics: the Int64* family (bitwise / shift / rotate / compare,
    fromInt / fromHiLo / lowBits / hiBits) and four constructors each for
    I32Array / F64Array / I64Array, with qualifiedIntrinsic resolutions. All
    pure, so checkWasmBaseCompat allowlists them off the same table.
  • Lower.IR / Lower.Reps: a new I64 rep; result/operand reps for every new
    intrinsic. Shift/rotate amounts are i32 (extended to i64 in codegen),
    matching v0.2.0's Int amount type.
  • Codegen.RuntimeTypes: four value types appended at indices 8-11
    ($I32Arr, $F64Arr, $Int64 = (struct i64), $I64Arr = (array (mut i64)));
    count, destructuring, and guard at 12.
  • Codegen.Value: boxInt64 / unboxInt64Expr, wired into coerce.
  • Codegen.Prim: each op lowered inline; fromHiLo zero-extends the low word by
    masking (no extend_i32_u is bound), array Set re-yields the threaded array.
  • Codegen: a compile-time checkedPrim post-check that the binaryen type
    genPrim emits matches the declared primRep (O(1), separable from the feature).
  • Binaryen.purs / Binaryen.js: the i64 FFI surface.
  • Tests + docs below.

Checklist

CI passing is enforced by the required ci-gate status check, not by a box here.
The items below are the human-judgment gates:

  • Docs updated — ADR-0026 addendum for the Int64 scalar and packed-array surface.
  • [~] Tests — Test.E2E.Cli.Int64 and Test.E2E.Cli.PackedArrays (both registered,
    routinely-run e2e lane) cover Int64 bitwise/shift/rotate/compare and
    build/set/index/length + the zero-init contract for all three arrays. They import
    the v0.2.0 primitives, so they cannot run in CI until that tag exists. Verified
    locally with the pin pointed at my wasm-base fork; the suite passes and NIST SHA-3
    vectors pass on wasm through a downstream Keccak built on these intrinsics.
  • Design changes have an ADR — ADR-0026 (Accepted) extended with a dated update.
  • No perf regression — inert by construction: the four new value types and the
    new intrinsics are unreferenced by any existing code path, and the new types append
    at indices 8-11 (0-7 unchanged), so every benchmark's compiled code is unchanged.
    bench/snapshots / baseline.json left untouched.
  • Runtime GC-type / ABI / canonicalization — $I32Arr, $F64Arr, $Int64,
    $I64Arr are all acyclic, each emitted as its own singleton rec group like the
    existing value types; appending them doesn't perturb the other eight types'
    canonical identity, so the ABI is unchanged and runtime.wat needs no edit.
    $I32Arr is structurally identical to $Bytes and canonicalises with it today;
    it's kept a distinct nominal type so a future packed-byte $Str can't alias it.

Depends on

wasm-base v0.2.0 (Wasm.Int64, Wasm.I32Array, Wasm.F64Array, Wasm.I64Array).
The latest published wasm-base tag is v0.1.1, so I've pinned the additive next
version, purs-wasm/purescript-wasm-base @ v0.2.0. That tag isn't cut yet; if you'd
rather it be a different number, tell me and I'll repoint the pin. (To avoid a
versioning mix-up I made myself: the 0.2.0 in purs-wasm/package.json is the CLI
package's version, a separate line from the wasm-base library tag, which lives in
that repo's spago.yaml.)

Note for the maintainer

To turn CI green, wasm-base v0.2.0 needs to be tagged on purs-wasm so the pin
resolves. Happy to coordinate timing. If you'd like CI to exercise the suite on this
draft before the tag exists, I can temporarily point the pin at my wasm-base fork and
revert it to the canonical tag before merge. Marked draft until the dependency lands.

harryprayiv added 25 commits June 21, 2026 18:40
…as based on my fork instead of origin/main when I started the work. Codegen.purs was the file I needed to most carefully consider, requiring some surgery to resolve conflicts.
…module with both new I32Arrays, F64Arrays, and Int64
…ly provision everything rather than having to read documentation just to benchmark this module. DETERMINISM is the key to getting people to stop having the "it works on my computer" issue.
Lower the wasm-base v0.2.0 primitives to native wasm: Wasm.Int64 (i64 scalar:
bitwise/shift/rotate/compare, fromInt/fromHiLo/lowBits/hiBits) and the packed
unboxed arrays Wasm.I32Array / Wasm.F64Array / Wasm.I64Array. Adds the I64 rep,
four value types ($Int64/$I32Arr/$F64Arr/$I64Arr), the i64 Binaryen FFI, a
compile-time rep-contract check, and e2e fixtures + CLI specs. Depends on
wasm-base v0.2.0.
@katsujukou
katsujukou self-requested a review June 27, 2026 06:45
@katsujukou katsujukou added enhancement New feature or request feature labels Jun 27, 2026
@katsujukou

Copy link
Copy Markdown
Collaborator

@harryprayiv

Hi, thank you for the pull request!

While this PR was open, I merged some major changes into main.
As a result, merge conflicts occurred in a few files (Binaryen.purs and spago.yaml).
I went ahead and resolved those conflicts on my end.

wasm-base now points to v0.2.0 published in the registry, instead of extraPackages.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants