Giter VIP home page Giter VIP logo

Comments (12)

hexane360 avatar hexane360 commented on August 28, 2024 1

I've significantly reduced the reproduction and identified the problem as a symbol conflict.

Here's the reproduction:

#![no_main]

#[no_mangle]
pub extern "C" fn sin_(ptr: i64) -> i64 {
    ptr
}

#[no_mangle]
pub extern "C" fn cos(ptr: i64) -> i64 {
    ptr
}

#[no_mangle]
pub extern "C" fn _start() {
    println!("{}", 5.0f64.sin()); // runs fine
    println!("{}", 5.0f64.cos()); // errors
}

Build with cargo build --target wasm32-unknown-unknown, and it can be run with wasmer run -v target/wasm32-unknown-unknown/debug/wasm-array-bug.wasm

When compiling f64::cos(), a function named cos is generated (un-mangled):

(func $cos (type 4) (param f64) (result f64)
    local.get 0
    call $_ZN17compiler_builtins4math3cos17h1c9c941a8073602cE)

This generated function conflicts with the exported cos function (which takes precedence). During linking, LLVM notices the signature mismatch, and generates the signature_mismatch:sin stub. In my case, the error only happens with f64 because the f32 intrinsic is called cosf instead of cos.

Using codegen-units = 1, the signature mismatch isn't noticed, and the generated WASM file has type errors:

~$ wasm-validate target/wasm32-unknown-unknown/debug/wasm-array-bug.wasm
target/wasm32-unknown-unknown/debug/wasm-array-bug.wasm:00001e5: error: type mismatch in call, expected [i64] but got [f64]
target/wasm32-unknown-unknown/debug/wasm-array-bug.wasm:00001e7: error: type mismatch in local.set, expected [f64] but got [i64]

Remaining questions:

  • Why aren't the sin/cos intrinsics mangled?
  • Why isn't the linking error reported to rustc?

from rust.

workingjubilee avatar workingjubilee commented on August 28, 2024

Your reproducer is incomplete because it does not include the build command you used with wasm-pack. It is possible to compile wasm code without wasm pack.

from rust.

hexane360 avatar hexane360 commented on August 28, 2024

You can build the reproduction using npm run build or npm run serve. I know it's possible to build without wasm-pack, I'll work on a reproduction without wasm-pack or wasm_bindgen but may take me a couple days to get to.

from rust.

workingjubilee avatar workingjubilee commented on August 28, 2024

It is fine if you didn't, but e.g. every time I have touched wasm-pack, nothing flowed through npm, so I am actually surprised to hear you are using it.

from rust.

workingjubilee avatar workingjubilee commented on August 28, 2024

oh neat!

from rust.

workingjubilee avatar workingjubilee commented on August 28, 2024

f32 sin should also be sinf???

from rust.

hexane360 avatar hexane360 commented on August 28, 2024

Yeah, these are the functions generated by f32::sin, f32::cos, f64::sin, f64::cos respectively:

  (func $sinf (type 5) (param f32) (result f32)
    local.get 0
    call $_ZN17compiler_builtins4math4sinf17ha493429580d1ed0cE)
  (func $cosf (type 5) (param f32) (result f32)
    local.get 0
    call $_ZN17compiler_builtins4math4cosf17h2f95fcc8c4a732edE)
  (func $sin (type 7) (param f64) (result f64)
    local.get 0
    call $_ZN17compiler_builtins4math3sin17h958cb507a9dbd375E)
  (func $cos (type 7) (param f64) (result f64)
    local.get 0
    call $_ZN17compiler_builtins4math3cos17h1c9c941a8073602cE)

I believe these symbol names correspond to those exported by libm. I was only running into a problem with sin::f64 and cos::f64 because I was only exporting functions named sin and cos.

from rust.

workingjubilee avatar workingjubilee commented on August 28, 2024

I see.

Hm, so, shadowing the libm names causing problems sounds like an unfortunate and expected hazard of using no_mangle.

I think the rest is a wasm_bindgen bug then...?

from rust.

hexane360 avatar hexane360 commented on August 28, 2024

I'm out of my depth as to whether this is expected behavior or not. Naively, I'd assume this would generate a linker error rather than generating code broken at runtime, though I'm not sure how easy it'd be to fix. It does look like something similar happens with the same code compiled to arm64 (in this case, silent failure at runtime).

I don't think there's any bug in wasm_bindgen, as I get the same behavior with and without. However, in theory it should be possible to change a function name in the wasm module without changing the name exported in the JS shim.

related: #28179

from rust.

tgross35 avatar tgross35 commented on August 28, 2024

It is easy to cause UB with no_mangle if your symbol names happen to conflict, even with no unsafe anywhere

#[no_mangle]
extern "C" fn malloc() {
    panic!(
        "malloc is a good name for a function that finds \
        Original Content at the mall, right?"
    );
}

// doesn't even do anything but the program crashes
fn main() {}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a550cf9f28b03c86187c46e61888d090

For that reason, starting in edition 2024 it will be #[unsafe(no_mangle)].

Symbols can be either strong (always gets picked, duplicates raise errors) or weak (yield to a strong symbol if available, if there are >1 weak symbols it just picks one). Symbols exported by Rust are always strong (the way to configure this is unstable), and I think libm symbols are always weak, as is malloc from this example, so it's just picking the strong ones. (I'm not 100% sure this is the same for wasm but I figure it's similar).

Your best bet here might be to change the names you export to JS, then just wrap them on the JS side with the correct name. Assuming this is coming from wasm-bindgen and there aren't knobs to twiddle.

from rust.

workingjubilee avatar workingjubilee commented on August 28, 2024

adding #![forbid(unsafe_code)] means it won't even compile, regardless of edition:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f78e430f3275cdcfbe35a641e6b25ecd

from rust.

hexane360 avatar hexane360 commented on August 28, 2024

Yeah, it looks like this is a dupe of #28179, and of rustwasm/wasm-bindgen#2338

Thanks for the help debugging.

from rust.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.