Description
This is a tracking issue where I'm going to propose that we stabilize two functions in the standard library:
These intrinsics are currently existing as memory::size
and memory::grow
, but I'm going to propose here that we don't do that and flatten them in the wasm32
module. As a reference, their signatures are:
fn memory_size(memory_index: u32) -> usize;
fn memory_grow(memory_index: u32, delta_pages: usize) -> isize;
Semantics
These two intrinsics represent instructions stabilized in the WebAssembly specification.
The memory.size
instruction will return the current size, in WebAssembly pages, of the specified memory index. Currently only index 0 is allowed, the index is required to be a constant value, and the return value is an usize
value. Note that usize
is used instead of the spec's i32
for two reasons: this is more forward compatible with a possible wasm64 architecture and the return value is always an unsigned number.
The memory.grow
instruction will grow the memory index specified by the given number of pages. The old size of memory, in pages, is returned. If the grow operation fails, then -1 is returned. LIke memory_size
, the memory index is currently required to be 0 and must be a constant value. The delta
may be a runtime value, however.
The binary encoding of these two instructions each have a reserved zero byte which is intended to be used to specify a different nonzero memory index in the future. As a recap, each WebAssembly module may have multiple "memory" instances, each assigned a unique index starting from zero. In the WebAssembly MVP, however, only at most one memory can be assigned with each wasm module, always located at index 0. (the memory may be omitted as well)
While the memory
argument is currently required to be zero, it's expected that future versions of WebAssembly will no longer have this requirement and any u32
value can be specified. It's also worth noting that the zero byte in the encoding of memory.size
and memory.grow
may not only be exclusively used for new indices. Current proposals to WebAssembly have repurposed required zero bytes as flags fields in addition to specified more than nonzero indices. While I'm not aware of any proposal to do so, it may be possible that a future feature to WebAssembly will have more than just a memory index argument to these instructions.
Stabilization in Rust
Stabilization of these intrinsics would be a significant step for Rust on multiple axes:
- Primarily these would be the first non-x86 intrinsics stabilized. This means it's the first architecture to have a stable
std::arch
module which isn't x86/x86_64. - Unlike x86 intrinsics, there is no prior art for how these intrinsics should be stabilized. Unlike x86/x86_64 the "vendor" (the WebAssembly specification) isn't giving us a document of functions with signatures.
Stabilization here will be paving a path forward for future stabilization of WebAssembly intrinsics, so it's good to consider conventions! It's unclear if the WebAssembly specification will, if ever, provide a document like Intel does for intrinsics with function names and function signatures for other languages to provide.
We've had some discussion on the naming of wasm intrinsics. We'd like to ensure that we match Clang (like we do for x86/x86_64), but Clang doesn't currently (AFAIK) have a naming convention beyond the __builtin_*
internal defines it has today.
What I'm proposing here is basically a convention of:
- We provide intrinsics for instructions not natively expressable in Rust. For example we don't give an
i32.add
intrinsic function as it's justa + b
. - Intrinsic signatures match the effective signature of the instruction, to the best it can. Above the
memory.grow
andmemory.size
intrinsics are fairly simple. - Intrinsic names match the name of the wasm intstructions, with non-rust-identifier characters mapped to an underscore.
The thinking behind these set of conventions it that it should be very easy to figure out what each intrinsic does, just like it is for Intel. The Rust documentation would always link to the WebAssembly specification for stabilized intrinsics.
Additionally we won't have any sort of automatic verification of WebAssembly intrinsics just yet like we do for x86 intrinsics in the stdsimd repository. There's so few WebAssembly intrinsics it's thought that we can simply manually verify each intrinsic.
TODO items before stabilization is finalized
- FCP (this issue)
- Rename the intrinsics (if that's decided on)
- Fix the "This is supported on MIPS only" message in documentation
- Update documentation to link to WebAssembly specification
- maybe flag functions as safe
- Update documentation on behavior with nonzero indexes
- Document the page size on these intrinsics.