Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

rustc disagrees with emcc about WASM struct ABI in parameters #88152

Open
Manishearth opened this issue Aug 19, 2021 · 5 comments
Open

rustc disagrees with emcc about WASM struct ABI in parameters #88152

Manishearth opened this issue Aug 19, 2021 · 5 comments
Labels
A-ABI Area: Concerning the application binary interface (ABI) C-bug Category: This is a bug. O-emscripten Target: 50% off wasm32-unknown-musl. the savings come out of stdio.h, but hey, you get SDL! O-wasm Target: WASM (WebAssembly), http://webassembly.org/

Comments

@Manishearth
Copy link
Member

I have the following Rust code, being compiled with cargo +nightly build --target wasm32-unknown-unknown

// in crate "em"

#[repr(C)]
pub struct Options {
    a: u8,
    b: u8
}

#[no_mangle]
pub extern "C" fn take_struct(o: Options) {}

And the following C++ code, compiled with emcc -std=c++17 test.cpp target/wasm32-unknown-unknown/debug/libem.a -ldl -lpthread -lm -g -o main.html --emrun -sWASM=1 (using the emscripten sdk)

# test.cpp 
extern "C" {
    typedef struct Options {
        uint8_t a;
        uint8_t b;
    } Options;
    void take_struct(Options o);
}

int main() {
    Options o;
    take_struct(o);
    return 0;
}

I expected to see this happen: The code would compile without warnings and run fine.

Instead, this happened:

emcc shows up the following warning:

wasm-ld: warning: function signature mismatch: take_struct
>>> defined as (i32) -> void in /tmp/emscripten_temp_qz2pbc3_/test_0.o
>>> defined as (i32, i32) -> void in target/wasm32-unknown-unknown/debug/libem.a(em.zb05z167nruq6bs.rcgu.o)

and running main.html in the browser throws the following error (to be expected based on the warning)

exception thrown: RuntimeError: unreachable,RuntimeError: unreachable
    at signature_mismatch:take_struct (http://localhost:8000/main.wasm:wasm-function[1]:0x165)
    at __original_main (http://localhost:8000/main.wasm:wasm-function[2]:0x1f1)
    at main (http://localhost:8000/main.wasm:wasm-function[3]:0x20e)
    at http://localhost:8000/main.js:1560:22
    at callMain (http://localhost:8000/main.js:2142:15)
    at doRun (http://localhost:8000/main.js:2212:23)
    at http://localhost:8000/main.js:2223:7

Seems like rustc believes that the signature for fn({u8, u8}) should be (i32, i32) -> void, whereas emcc believes it should be (i32) -> void.

A lot of other function signatures work (including returning Option), it's specifically when such a struct is a parameter that this happens.

I'm not sure which side is at fault here, but an incompatibility between Rust and emcc means that it won't be possible to use WASM with C++ programs that embed a little Rust (or vice versa), which seems like a problem worth highlighting. I think there are other ways to compile C++ to WASM via clang that I need to check out next.

Meta

Version info
$ rustc --version --verbose
rustc 1.56.0-nightly (2d2bc94c8 2021-08-15)
binary: rustc
commit-hash: 2d2bc94c8c3aa778e191f80261c726e4777439f1
commit-date: 2021-08-15
host: x86_64-unknown-linux-gnu
release: 1.56.0-nightly
LLVM version: 12.0.1
$ emcc --version
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.27 (7e538a419c3649f3a540a57beab347aa8f6c6271)
Copyright (C) 2014 the Emscripten authors (see AUTHORS.txt)
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

cc @fitzgen

@Manishearth Manishearth added O-wasm Target: WASM (WebAssembly), http://webassembly.org/ C-bug Category: This is a bug. labels Aug 19, 2021
@Manishearth
Copy link
Member Author

This might be because I'm building with --target wasm32-unknown-unknown, however under wasm32-unknown-emscripten I get a bunch of link errors so it seems like that's not well suited for this:

  = note: emcc: warning: please replace -g4 with -gsource-map [-Wdeprecated]
          error: undefined symbol: __gxx_personality_v0 (referenced by top-level compiled C/C++ code)
          warning: Link with `-s LLD_REPORT_UNDEFINED` to get more information on undefined symbols
          warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
          warning: ___gxx_personality_v0 may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
          error: undefined symbol: main (referenced by top-level compiled C/C++ code)
          warning: _main may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
          warning: To build in STANDALONE_WASM mode without a main(), use emcc --no-entry
          Error: Aborting compilation due to previous errors
          emcc: error: '/home/manishearth/Installs/emsdk/node/14.15.5_64bit/bin/node /home/manishearth/Installs/emsdk/upstream/emscripten/src/compiler.js /tmp/tmpf5dpw2l1.txt' failed (returned 1)

@workingjubilee
Copy link
Member

Relevant commentary in #83763

@fitzgen
Copy link
Member

fitzgen commented Aug 19, 2021

Yeah, this is an unfortunate historical mistake, but one which can't be fixed without breaking a bunch of code (everything that uses wasm-bindgen).

The wasm32-wasi target agrees with clang's wasm32-wasi target, fwiw, and linking C and Rust on that target is trivial.

I don't know anything about the emscripten target.

@Manishearth
Copy link
Member Author

@fitzgen thanks!

and linking C and Rust on that target is trivial.

Seems like C++ is a bit more challenging, can't get iostream to work.

@gregbuchholz
Copy link

@Manishearth the Emscripten link errors you were getting can be solved using this tip, or this one.

@workingjubilee workingjubilee added the O-emscripten Target: 50% off wasm32-unknown-musl. the savings come out of stdio.h, but hey, you get SDL! label Oct 11, 2024
@workingjubilee workingjubilee added the A-ABI Area: Concerning the application binary interface (ABI) label Jan 22, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-ABI Area: Concerning the application binary interface (ABI) C-bug Category: This is a bug. O-emscripten Target: 50% off wasm32-unknown-musl. the savings come out of stdio.h, but hey, you get SDL! O-wasm Target: WASM (WebAssembly), http://webassembly.org/
Projects
None yet
Development

No branches or pull requests

4 participants