% WASM, Rust, and C % Michael Stone % June 28, 2022 ## Depict I've been working on a new project named [depict], which helps draw pictures of complex systems. Depict is implemented in [Rust] and runs both on desktops and on the web. Making depict run well on the web has been an exciting challenge because of some normally obscure technical details which I'd like better document. ## On ABIs Today's version of depict relies on a wonderful piece of software called [osqp]. Depict uses osqp to figure out, for a given layout or placement of objects to be drawn, how big the objects should be and where they should be positioned. OSQP is written in (relatively) library-free C. Now, normally, when you want to combine programs written in multiple compiled languages like Rust and C, you do so either via networking or linking. Linking, here, means that the compilers used for each separate unit of code to be linked need to agree on how to communicate, which is called an "ABI", or "application binary interface". As it turns out, ABIs are still in flux for WASM -- specifically for wasm32. As of this writing, there are three wasm32 ABIs in common use and one more under active development: `wasm32-unknown-unknown` : (which uses the [wasm-bindgen] project's ABI and runtime glue provided by wasm-bindgen) `wasm32-wasi` : (which is still under heavy-development, and needs to be polyfilled on the web, e.g., with [wasmer-js]) `wasm32-unknown-emscripten` : (which uses emscripten's/clangl's ABI and runtime glue provided by emscripten) `wasm32-???-???` : (see the [WASM component model], see [wit-bindgen] and Radu Matei's post: [Introduction to WebAssembly components]) (Thanks specifically to [lopopolo] for pointing out [this issue] to me, and to the Rust lang-team for documenting the [ABI mismatch] issue so clearly. More reading: [WebAssembly/tool-conventions #88], [`wasm` ABI commit]) ## On `c2rust` and `wasm32-unknown-unknown` Since I am already targeting `wasm32-unknown-unknown`, it turned out that the most expedient way to make everything play nicely together was quite unusual: to mechanically translate osqp from C to a drop-in rust replacement that I'm calling [osqp-rust] using [c2rust]. A few more details were required to make all this work. 1. while osqp is relatively library free, in "non-embedded" mode, it still needs to know whether a. to use 64-bit or 32-bit integers (cmake's `-DLONG` option) and b. it still needs memory allocation as well as OS-specific timing functionality. I addressed this by translating osqp twice, once in 32-bit mode and once in 64-bit mode, and then adding by using conditional compilation to select which translation to use at (Rust crate) build time. 2. memory allocation is supported by rust on wasm32 via the [dlmalloc] crate, which it turns out is itself a c-to-rust translation of the [dlmalloc allocator]. Consequently, I was able to (somewhat hackishly) reimplement the necessary APIs as wrappers around rust's [System allocator]. 3. timing is provided on the web by interfaces like [Performance.now]. Happily, the wasm-bindgen documentation already contains [an example of how to use Performance.now] so this was also easy to wrap. [depict]: (https://github.com/mstone/depict) [Rust]: https://rust-lang.org [osqp]: https://osqp.org [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen [wasmer-js]: https://github.com/wasmerio/wasmer-js [lopopolo]: https://hyperbo.la [this issue]: https://github.com/rust-lang/rust/issues/63626 [c2rust]: https://c2rust.com [osqp-rust]: https://github.com/mstone/osqp.rs [dlmalloc]: https://github.com/alexcrichton/dlmalloc-rs [dlmalloc allocator]: https://gee.cs.oswego.edu/dl/html/malloc.html [Performance.now]: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now [an example of how to use Performance.now]: https://rustwasm.github.io/wasm-bindgen/examples/performance.html [WASM component model]: https://github.com/WebAssembly/component-model [wit-bindgen]: https://github.com/bytecodealliance/wit-bindgen [Introduction to WebAssembly components]: https://radu-matei.com/blog/intro-wasm-components/ [System allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html [ABI mismatch]: https://github.com/rust-lang/lang-team/blob/master/design-meeting-minutes/2021-04-21-wasm-abi.md [WebAssembly/tool-conventions #88]: https://github.com/WebAssembly/tool-conventions/issues/88 [`wasm` ABI commit]: https://github.com/rust-lang/rust/commit/482a3d06c3d1f83761bf3c94e1bad4fac7d32db4