Skip to content

Commit ab9356f

Browse files
authored
Add initial wasm memory grow/current intrinsics (#361)
This exposes access to the `grow_memory` and `current_memory` instructions provided by wasm in what will hopefully be a stable interface (the stable part being x86 first in theory).
1 parent d6629aa commit ab9356f

File tree

7 files changed

+110
-0
lines changed

7 files changed

+110
-0
lines changed

.travis.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ matrix:
2626
script: ci/dox.sh
2727
- script: cargo test --manifest-path crates/stdsimd-verify/Cargo.toml
2828
install: true
29+
- env: TARGET=wasm32-unknown-unknown
30+
before_script:
31+
- git clone --recursive https://github.com/WebAssembly/wabt
32+
- (cd wabt && make -j4)
33+
- export PATH=$PATH:$PWD/wabt/bin
34+
script:
35+
- cargo build --target wasm32-unknown-unknown -p stdsimd
36+
- cargo build --target wasm32-unknown-unknown -p stdsimd --release
37+
- cargo rustc --target wasm32-unknown-unknown -p stdsimd --release --example wasm -- -C lto
38+
- wasm2wat target/wasm32-unknown-unknown/release/examples/wasm.wasm -o wasm.wat
39+
- cat wasm.wat
40+
- grep current_memory wasm.wat
41+
- grep grow_memory wasm.wat
2942
- env: RUSTFMT=On TARGET=x86_64-unknown-linux-gnu NO_ADD=1
3043
before_script:
3144
- rustup component add rustfmt-preview

coresimd/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ pub mod arch {
6969
pub use coresimd::arm::*;
7070
pub use coresimd::aarch64::*;
7171
}
72+
73+
/// Platform-specific intrinsics for the `wasm32` platform.
74+
///
75+
/// See the [module documentation](../index.html) for more details.
76+
#[cfg(target_arch = "wasm32")]
77+
pub mod wasm32 {
78+
pub use coresimd::wasm32::*;
79+
}
7280
}
7381

7482
mod simd_llvm;
@@ -82,5 +90,7 @@ mod x86_64;
8290
mod arm;
8391
#[cfg(target_arch = "aarch64")]
8492
mod aarch64;
93+
#[cfg(target_arch = "wasm32")]
94+
mod wasm32;
8595

8696
mod nvptx;

coresimd/wasm32.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
extern "C" {
2+
#[link_name = "llvm.wasm.grow.memory.i32"]
3+
fn llvm_grow_memory(pages: i32) -> i32;
4+
#[link_name = "llvm.wasm.current.memory.i32"]
5+
fn llvm_current_memory() -> i32;
6+
}
7+
8+
/// Corresponding intrinsic to wasm's [`current_memory` instruction][instr]
9+
///
10+
/// This function, when called, will return the current memory size in units of
11+
/// pages.
12+
///
13+
/// [instr]: https://github.com/WebAssembly/design/blob/master/Semantics.md#resizing
14+
#[inline]
15+
pub unsafe fn current_memory() -> i32 {
16+
llvm_current_memory()
17+
}
18+
19+
/// Corresponding intrinsic to wasm's [`grow_memory` instruction][instr]
20+
///
21+
/// This function, when called, will attempt to grow the default linear memory
22+
/// by the specified number of pages. If memory is successfully grown then the
23+
/// previous size of memory, in pages, is returned. If memory cannot be grown
24+
/// then -1 is returned.
25+
///
26+
/// [instr]: https://github.com/WebAssembly/design/blob/master/Semantics.md#resizing
27+
#[inline]
28+
pub unsafe fn grow_memory(delta: i32) -> i32 {
29+
llvm_grow_memory(delta)
30+
}

crates/stdsimd/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ path = "../../examples/hex.rs"
4343
[[example]]
4444
name = "nbody"
4545
path = "../../examples/nbody.rs"
46+
47+
[[example]]
48+
name = "wasm"
49+
crate-type = ["cdylib"]
50+
path = "../../examples/wasm.rs"

examples/wasm.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//! A simple slab allocator for pages in wasm
2+
3+
#![feature(stdsimd)]
4+
#![cfg(target_arch = "wasm32")]
5+
6+
extern crate stdsimd;
7+
8+
use std::ptr;
9+
10+
use stdsimd::arch::wasm32::*;
11+
12+
static mut HEAD: *mut *mut u8 = 0 as _;
13+
14+
#[no_mangle]
15+
pub unsafe extern "C" fn page_alloc() -> *mut u8 {
16+
if !HEAD.is_null() {
17+
let next = *HEAD;
18+
let ret = HEAD;
19+
HEAD = next as *mut _;
20+
return ret as *mut u8;
21+
}
22+
23+
let ret = grow_memory(1);
24+
25+
// if we failed to allocate a page then return null
26+
if ret == -1 {
27+
return ptr::null_mut();
28+
}
29+
30+
((ret as u32) * page_size()) as *mut u8
31+
}
32+
33+
#[no_mangle]
34+
pub unsafe extern "C" fn page_free(page: *mut u8) {
35+
let page = page as *mut *mut u8;
36+
*page = HEAD as *mut u8;
37+
HEAD = page;
38+
}
39+
40+
#[no_mangle]
41+
pub unsafe extern "C" fn memory_used() -> usize {
42+
(page_size() * (current_memory() as u32)) as usize
43+
}
44+
45+
fn page_size() -> u32 {
46+
64 * 1024
47+
}

stdsimd/arch/detect/cache.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Caches run-time feature detection so that it only needs to be computed
22
//! once.
33
4+
#![allow(dead_code)] // not used on all platforms
5+
46
use core::sync::atomic::Ordering;
57

68
#[cfg(target_pointer_width = "64")]

stdsimd/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ pub mod arch {
353353
#[cfg(target_arch = "aarch64")]
354354
pub use coresimd::arch::aarch64;
355355

356+
#[cfg(target_arch = "wasm32")]
357+
pub use coresimd::arch::wasm32;
358+
356359
#[doc(hidden)] // unstable implementation detail
357360
pub mod detect;
358361
}

0 commit comments

Comments
 (0)