What's required to make global_asm!
/asm!
usable for wasm targets? Does LLVM already have the capability for inline wat when targeting wasm (making it mostly rustc implementation effort), or does LLVM still need to grow support? (Is it possibly already possible on nightly and I just missed it becoming available?)
It'll probably be a bit of design work, since wasm is (mostly?) a stack machine as opposed to a register machine. The simple way is to have local
as a register class and always go through local.get
/local.set
(relying on optimizations to mitigate data shuffling overhead). inout("name")
also works for named locals. But there could be maybe some way to interact with putting primitive values on the wasm stack.
The main reason I'm curious is access to things Rust can't express in the surface language (e.g. externref[1]) but it's also useful/interesting as a way to have access to a sort of "poor man's intrinsics" before (and mitigating need for) the compiler exposing them more directly.
XY: wasm_bindgen currently uses a wasm postprocessing step to adjust external symbols, e.g. to let interfaces use externref. I'm interested in experimenting with wasm interfaces without requiring a post-processing step, if possible[2]. Purpose: plugin IPC.[3]
-
It's not possible to directly use wasm externref from surface Rust since they can't be stored in linear memory, and thus you can't take a reference of them. Instead, they're stored into a global table and Rust code manipulates the index into the table. While it's interesting intellectually to consider if Rust could somehow work with externref directly by restricting it to be used by-value, it's far too removed from a von Neumann architecture to be practical. ↩︎
-
I'm aware that postprocessing can still be desirable (e.g. wasm-opt), but I see optional interface preserving transforms as a different class from interface adjusting. Primarily because at least when running under cargo it's nice to not need the postprocessing step for dev/test cycles and only do it as part of dist. ↩︎
-
I could just use
i32
on the boundary instead of externref and duplicating slot management on both sides of the boundary (and probably will for the time being), but I have a slight preference for using the more "wasm native" interface shape. Additionally, the guaranteed-accurate lifecycle tracking of externref (only possible because they can't be stored in linear memory) is a nice benefit. ↩︎