Skip to content

Add wasm64-emscripten arm for unwinder_private_data_size#156912

Open
gergelyvagujhelyi wants to merge 1 commit into
rust-lang:mainfrom
nobodywho-ooo:wasm64-emscripten-unwind-arm
Open

Add wasm64-emscripten arm for unwinder_private_data_size#156912
gergelyvagujhelyi wants to merge 1 commit into
rust-lang:mainfrom
nobodywho-ooo:wasm64-emscripten-unwind-arm

Conversation

@gergelyvagujhelyi
Copy link
Copy Markdown

library/unwind/src/libunwind.rs has a cfg dispatch on
(target_arch, target_os) for unwinder_private_data_size. There's an
arm for wasm32-emscripten but none for wasm64-emscripten, so
building std for wasm64-unknown-emscripten (consumed as a tier-3
target via a custom JSON spec and -Z build-std) fails with
E0425: cannot find value 'unwinder_private_data_size' in this scope.

This PR adds the missing arm, mirroring the existing
wasm32-emscripten value of 20. The constant is a count of
_Unwind_Word fields in _Unwind_Exception, not a byte size, so the
same value is correct for both pointer widths — Emscripten's libunwind
is what determines how many private words the struct needs (~18 for
the libcxxabi __cxa_exception overlay, plus the standard Itanium
private_1 / private_2), and that count is target-uniform.

 #[cfg(all(target_arch = "wasm32", target_os = "emscripten"))]
 pub const unwinder_private_data_size: usize = 20;
+
+#[cfg(all(target_arch = "wasm64", target_os = "emscripten"))]
+pub const unwinder_private_data_size: usize = 20;

 #[cfg(all(target_arch = "wasm32", any(target_os = "linux", target_os = "wasi")))]
 pub const unwinder_private_data_size: usize = 2;

Context

wasm64-unknown-emscripten isn't an officially listed target, but it's
buildable today as a tier-3 target via a custom JSON spec mirroring
wasm32-unknown-emscripten with arch=wasm64,
target-pointer-width=64, and Emscripten's -sMEMORY64=1 in
post-link-args. The motivation is running LLM inference workloads
whose working set exceeds 4 GiB (model tensors + KV cache + compute)
in a browser via Emscripten, which is impossible on wasm32 regardless
of how the bytes are loaded.

Without this arm, std itself fails to build because the unwind
crate is foundational — any crate using String / Vec / etc.
transitively pulls in unwind. With it, the entire toolchain chain
(rustc → wasm-bindgen-cli → emcc post-link with -sMEMORY64=1 -fwasm-exceptions) links cleanly and the resulting wasm runs
real-world inference workloads end-to-end. Verified with Gemma 3 4B
(~3.5 GiB on-disk; ~5 GiB working set) on Node 22.

Test plan

No new tests needed — the change is a single const for an inactive
target. Existing CI continues to skip wasm64-emscripten (not in
src/tools/build-manifest / dist-various-2).

Manual verification: cargo +nightly build --target wasm64-unknown-emscripten.json -Z build-std=panic_abort,std -Zjson-target-spec succeeds for a minimal String-using crate
with this patch; fails with E0425 without it.

Prior art for similar arms

The cfg chain in this file already has dedicated arms for several
tier-3 / late-tier-2 targets — riscv32/riscv64, hexagon,
loongarch32/loongarch64, wasm32-wasi, wasm32-emscripten. This
PR follows the same pattern, adding only the missing
wasm64-emscripten line.

wasm64-unknown-emscripten is buildable as a tier-3 target via a custom
JSON spec, but library/unwind has no cfg arm for it in this chain, so
std builds fail with E0425 (unwinder_private_data_size unresolved).

Mirrors the wasm32-emscripten arm right above. unwinder_private_data_size
is a count of _Unwind_Word fields, not a byte size, so the value matches
between wasm32 and wasm64 — only pointer widths differ.
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 25, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 25, 2026

r? @Mark-Simulacrum

rustbot has assigned @Mark-Simulacrum.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Fallback group: @Mark-Simulacrum, @jieyouxu
  • @Mark-Simulacrum, @jieyouxu expanded to Mark-Simulacrum, jieyouxu

gergelyvagujhelyi added a commit to nobodywho-ooo/nobodywho that referenced this pull request May 25, 2026
Post-wasm64 audit caught three stale spots:

js/README.md "v1 limitations": the "Models >2 GiB on disk" item read
as a flat capability gap. Splits into two accurate items now:
  - >2 GiB on disk via modelBytes in Node: use Chat.create({modelPath})
    which streams chunks into MEMFS; browser is unaffected (modelUrl
    streams via fetch + Cache API).
  - >4 GiB total working set on wasm32: build the sibling wasm64
    artifact; ceiling lifts to 16 GiB. Links rust-lang/rust#156912
    for the unwind patch that's gating contributors today.

core/src/llm.rs get_model_from_path doc: parenthetical claimed the
wasm32 4 GiB ceiling "still applies" with no escape hatch. Updated to
point at the sibling wasm64 build script.

js/README.md cfg-shorthand: a stray `cfg(not(wasm32))` reference left
over from before the workspace-wide widening to
`cfg(not(target_family = "wasm"))`. Updated for consistency with the
code.

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

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants