Description
When trying to compile a code that uses foreign global variables under wasm32-unknown-unknown
it appears that wrong code is generated. My use case is that I want to export a variable foo
from the host, so Rust program compiled into wasm can use value of this variable.
I tried this code:
extern "C" {
#[no_mangle]
static foo: i32;
}
#[no_mangle]
pub extern "C" fn bar() -> i32 {
unsafe { foo }
}
Compiled with:
rustc --target wasm32-unknown-unknown -O --crate-type=cdylib src/main.rs -o wasm_test.wasm
Produces following WASM code:
(module
(type (;0;) (func))
(type (;1;) (func (result i32)))
(func $__wasm_call_ctors (type 0))
(func $bar (type 1) (result i32)
i32.const 0
i32.load)
(table (;0;) 1 1 anyfunc)
(memory (;0;) 16)
(global (;0;) (mut i32) (i32.const 1048576))
(global (;1;) i32 (i32.const 1048576))
(global (;2;) i32 (i32.const 1048576))
(export "memory" (memory 0))
(export "__heap_base" (global 1))
(export "__data_end" (global 2))
(export "bar" (func $bar)))
Rust appears to treat variable extern "C" static foo: i32;
as variable with local linkage without emitting "import global" opcodes.
This should be the direct translation into C++ code. This also declares a variable with external linkage:
extern int foo;
int bar() { return foo; }
Compiled into WASM:
(module
(import "env" "foo" (global $foo i32))
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "_Z3barv" (func $_Z3barv))
(func $_Z3barv (; 0 ;) (result i32)
(i32.load
(get_global $foo)
)
)
)
Note the (import "env" "foo" (global $foo i32))
: This is what C++ compiler emits when it encounters a variable declared with an external linkage. Source
I believe current behaviour of Rust compiler is incorrect and wrong WASM code is generated for variables with external C linkage. Perhaps there is a special syntax for emitting (import "env" "foo" (global $foo i32))
? Right now the only workaround seems to be using functions instead of variables to communicate between host and the wasm program which works perfectly fine. Please let me know if I missed something and there is an easy way to achieve this.
Meta
rustc --version --verbose
:
rustc 1.36.0-nightly (a9ec99f 2019-05-13)
I've also tried on stable, and other versions of rust nightly.