I'm trying to build no_std
code with wasm32-unknown-unknown
target:
#[no_mangle]
pub fn test() {
let mut idx: i32 = 10;
let ptr = &mut idx as *mut i32;
let buffer = unsafe { core::slice::from_raw_parts_mut(ptr, 10) };
for pixel in buffer.iter_mut() {
*pixel = 0x7d2b7500;
}
}
After the build, I get the following wasm binary code (I use wasm2wat
tool):
(module
(type (;0;) (func))
(func (;0;) (type 0)
nop)
(memory (;0;) 16)
(global (;0;) i32 (i32.const 1048576))
(global (;1;) i32 (i32.const 1048576))
(export "memory" (memory 0))
(export "test" (func 0))
(export "__data_end" (global 0))
(export "__heap_base" (global 1)))
My test
function is empty for some reason ("nop").
But when I pass a raw pointer ptr
from outside as test
function argument:
#[no_mangle]
pub fn test(ptr: *mut i32) {
let buffer = unsafe { core::slice::from_raw_parts_mut(ptr, 10) };
for pixel in buffer.iter_mut() {
*pixel = 0x7d2b7500;
}
}
wasm code generates:
(module
(type (;0;) (func (param i32)))
(func (;0;) (type 0) (param i32)
local.get 0
i64.const 9019431323700000000
i64.store offset=32 align=4
local.get 0
i64.const 9019431323700000000
i64.store offset=24 align=4
local.get 0
i64.const 9019431323700000000
i64.store offset=16 align=4
local.get 0
i64.const 9019431323700000000
i64.store offset=8 align=4
local.get 0
i64.const 9019431323700000000
i64.store align=4)
(memory (;0;) 16)
(global (;0;) i32 (i32.const 1048576))
(global (;1;) i32 (i32.const 1048576))
(export "memory" (memory 0))
(export "test" (func 0))
(export "__data_end" (global 0))
(export "__heap_base" (global 1)))
Why it happens?
I'm expecting wasm generated code
You are just modifying local stack memory without returning the value, so it has no side effects and can be optimized out. You could potentially use write_volatile to stop this.
Your code is also UB because you are not meeting the safety requirements in the documentation for from_raw_parts_mut. In particular
data must point to len consecutive properly initialized values of type T.