Comments (12)
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.
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.
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.
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.
oh neat!
from rust.
f32 sin should also be sinf???
from rust.
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.
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.
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.
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() {}
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.
adding #![forbid(unsafe_code)]
means it won't even compile, regardless of edition:
from rust.
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)
- Jump threading MIR opt unsoundly uses bitpattern equality for floats HOT 17
- ICE: `trait takes 1 generic argument but 0 generic arguments were supplied` HOT 2
- Bug when using `cargo check` (my program works with `cargo run`) HOT 1
- zero-sized slices are sometimes placed at 0x1 (1.79+) HOT 16
- Documentation of default value for config.toml's `rust.channel` is inaccurate
- Rustdoc: struct fields are spaced too closely HOT 3
- [Enhancement]: `must_use_xor` to Force Using One of the Functions but not all in a Struct HOT 1
- false positive `dead_code` "never constructed" warning on 1.80.0 for a `struct` where the constructor takes `&'static self` HOT 11
- rustc_contracts: differentiate between exhaustive and non-exhaustive contracts
- ICE: The Rust Compiler Panicked After I Removed A Windows SDK HOT 11
- rustc book does not document RUST_TARGET_PATH HOT 1
- Tracking Issue for `nonzero_bitwise`
- Linking with `rust-lld` causes SIGSEGV in FFI code HOT 7
- Effective breakage to `jiff` due to `ambiguous_negative_literals` HOT 3
- Tracking Issue for `float_semantics` RFC 3514 HOT 1
- Spurious CI failures on x86_64-msvc-ext: "failed to remove file `C:\a\rust\rust\build\x86_64-pc-windows-msvc\stage2-tools\x86_64-pc-windows-msvc\release\cargo.exe`" HOT 1
- compiletest: add a `needs-subprocess` directive HOT 2
- Add back io::copy file to pipe optimization HOT 13
- The suggestion to remove generic parameters proposed by help did not remove comma HOT 6
- Unhelpful error message "Attempt to negate with overflow" when calling `i64::abs(i64::MIN)`.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust.