Skip to content

Accessing foreign global variables under wasm32-unknown-unknown target #60825

Closed
@mpapierski

Description

@mpapierski

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.O-wasmTarget: WASM (WebAssembly), http://webassembly.org/T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions