Skip to content

WebAssembly ABI mismatch between clang and rust #71871

Closed
@tomaka

Description

@tomaka
Contributor

When I compile this C code to wasm32-wasi:

typedef struct Vector {
    int a;
    int b;
} Vector;

extern int extract_a(Vector v) {
    return v.a;
}

And this Rust code to wasm32-wasi:

#[repr(C)]
struct Vector {
    a: i32,
    b: i32,
}

extern "C" {
    fn extract_a(v: Vector) -> i32;
}

fn main() {
    unsafe {
        extract_a(Vector { a: 5, b: 4 });
    }
}

And try link them together, I'm getting linking errors:

  = note: lld: error: function signature mismatch: extract_a
          >>> defined as (i32, i32) -> i32 in /home/pierre/Projets/wasm-abi-test/target/wasm32-wasi/debug/deps/wasm_abi_test.67xpw7l331r9o5x.rcgu.o
          >>> defined as (i32) -> i32 in /home/pierre/Projets/wasm-abi-test/target/wasm32-wasi/debug/build/wasm-abi-test-9c49ce7f6c5ca031/out/libfoo.a(test.o)

It seems that, according to clang, passing a struct by value should inline the fields, while for Rust it should be passed by pointer.

I uploaded an example project here: https://github.com/tomaka/wasm-abi-test
It can be built with something like:

AR_wasm32_wasi=/path/to/wasi-sdk-10.0/bin/ar CC_wasm32_wasi=/path/to/wasi-sdk-10.0/bin/clang cargo run --target=wasm32-wasi

Rust version: rustc 1.44.0-nightly (38114ff 2020-03-21)

Activity

added
A-FFIArea: Foreign function interface (FFI)
O-wasmTarget: WASM (WebAssembly), http://webassembly.org/
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on May 4, 2020
TheBlueMatt

TheBlueMatt commented on Jan 9, 2021

@TheBlueMatt

This is mostly tracked at rustwasm/team#291 and would be fixed by #79998.

TheBlueMatt

TheBlueMatt commented on Jan 12, 2021

@TheBlueMatt

This should now work for wasm32-wasi (on current git head).

added
A-ABIArea: Concerning the application binary interface (ABI)
on Jul 1, 2022
programmerjake

programmerjake commented on Aug 28, 2022

@programmerjake
Member

Note that #83763 changed the default, so only wasm32-unknown-unknown uses the mismatched ABI, all other wasm targets (including custom targets) now default to using the ABI that matches clang:

// This is a default for backwards-compatibility with the original
// definition of this target oh-so-long-ago. Once the "wasm" ABI is
// stable and the wasm-bindgen project has switched to using it then there's
// no need for this and it can be removed.
//
// Currently this is the reason that this target's ABI is mismatched with
// clang's ABI. This means that, in the limit, you can't merge C and Rust
// code on this target due to this ABI mismatch.
options.default_adjusted_cabi = Some(Abi::Wasm);

temeddix

temeddix commented on Oct 26, 2023

@temeddix

There are discussions going on at wasm-bindgen to extend the support to wasm32-wasi in addition to the current wasm32-unknown-unknown.

In short, wasm-bindgen needs a consistent C ABI between wasm32-unknown-unknown and wasm32-wasi to support both of them.

Note that #83763 changed the default, so only wasm32-unknown-unknown uses the mismatched ABI, all other wasm targets (including custom targets) now default to using the ABI that matches clang:

// This is a default for backwards-compatibility with the original
// definition of this target oh-so-long-ago. Once the "wasm" ABI is
// stable and the wasm-bindgen project has switched to using it then there's
// no need for this and it can be removed.
//
// Currently this is the reason that this target's ABI is mismatched with
// clang's ABI. This means that, in the limit, you can't merge C and Rust
// code on this target due to this ABI mismatch.
options.default_adjusted_cabi = Some(Abi::Wasm);

Can we have ABI that matches clang on wasm32-unknown-unknown as well? I can help with this, but would it be a hard task?

bjorn3

bjorn3 commented on Oct 26, 2023

@bjorn3
Member

The change itself would be removing options.default_adjusted_cabi = Some(Abi::Wasm) from the target spec and that's it. Because it breaks older wasm-bindgen versions it will probably require waiting months to years before we can actually make this change. And preferably we would introduce a future compat warning for this change. Either against older wasm-bindgen versions or against any extern "C" function for which changing the abi actually has any effect.

59 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ABIArea: Concerning the application binary interface (ABI)A-FFIArea: Foreign function interface (FFI)C-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

      Participants

      @davidar@rpjohnst@RalfJung@tritao@TheBlueMatt

      Issue actions

        WebAssembly ABI mismatch between clang and rust · Issue #71871 · rust-lang/rust