WASM: how to remove runtime artifacts (__data_end, __heap_base)

Sometimes I need to write fast calculations for a browser. For that use case, I can use Rust to compile WASM code.

When I use these Rustflags:
-Ctarget-feature=+multivalue -Clink-args=-zstack-size=64000

And I use these settings in Cargo.toml:

[profile.release]
lto = true
opt-level = "z"
strip = "debuginfo"

[lib]
crate-type = ["cdylib"]

And I use this code:

#[no_mangle]
fn flip(a: u32, b: u32) -> (u32, u32) {
    (b, a)
}

And I build using cargo build --release --target=wasm32-unknown-unknown, I can then convert the resulting .wasm to .wat. When I do, I get this:

(module
  (type $t0 (func (param i32 i32) (result i32 i32)))
  (func $flip (export "flip") (type $t0) (param $p0 i32) (param $p1 i32) (result i32 i32)
    (local.get $p1)
    (local.get $p0))
  (memory $memory (export "memory") 1)
  (global $__data_end (export "__data_end") i32 (i32.const 64000))
  (global $__heap_base (export "__heap_base") i32 (i32.const 64000)))

I get that __data_end and __heap_base are probably needed by the Rust runtime, and as soon as I bring in a crate, they will likely be used somehow. But as it stands, I'm not ever going to use __data_end or __heap_base in this example. Can I tell Rust to omit them? (It seems buggy that unused variables would end up in the final program.)

Try running wasmopt on your *.wasm file. It'll do this sort of optimisation and steipping of unused symbols.

wasm-opt can't remove exports, since those don't count as unused. That's why they weren't removed by rustc either.


The old wasi preview1 ABI spec says this:

Environments shall not access exports named __heap_base or __data_end. Toolchains are encouraged to avoid providing these exports.

("Environments" being host runtimes like the browser, or wasmtime, or what have you)

Strange that Rust woulde export these, or even include them in non-wasi builds. I wonder why they're mentioned at all, I've never been able to figure out what they're for.

1 Like

is the code responsible for exporting these symbols. Based on https://github.com/rust-lang/rust/pull/62809 it seems like they are necessary for multithreading on webassembly.

1 Like

Thanks so much for your research!

It sounds like the answer for now is that these artifacts cannot be avoided by the compiler.

I have requested this feature separately.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.