Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

wasm link failures - "The end of the file was unexpectedly encountered" #38558

Closed
lilyball opened this issue Dec 22, 2016 · 25 comments
Closed

wasm link failures - "The end of the file was unexpectedly encountered" #38558

lilyball opened this issue Dec 22, 2016 · 25 comments
Labels
O-asmjs Target: asm.js - http://asmjs.org/ O-wasm Target: WASM (WebAssembly), http://webassembly.org/

Comments

@lilyball
Copy link
Contributor

With the release of Rust 1.14.0, I wanted to try out the emscripten support. I've never used emscripten before, so here's the steps I took:

> brew install emscripten
# installing
# brew instructed me to edit ~/.emscripten
> vim ~/.emscripten # edit as instructed
> rustup target add wasm32-unknown-emscripten
> echo 'fn main() { println!("Hello, Emscripten!"); }' > hello.rs
> rustc --target=wasm32-unknown-emscripten hello.rs

At this point, emcc spewed a bunch of link errors:

error: linking with `emcc` failed: exit code: 1
  |
  = note: "emcc" "-L" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib" "hello.0.o" "-o" "hello.js" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libstd-610aec1c0c2edd5b.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libpanic_unwind-f2d5dd75c5a64c5f.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libunwind-cce8009dda26867d.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/librand-d2f56491199d3b9f.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libcollections-4f02fd86535a3157.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/librustc_unicode-8d6c34ad46f07f91.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/liballoc-198f48436646c796.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/liballoc_system-22e63f2ceba0e6f8.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/liblibc-9b19cb4b417215a8.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libcore-ec0461203eec19c8.rlib" "/Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libcompiler_builtins-ad8606f391af463e.rlib" "-l" "c" "-s" "BINARYEN=1" "-s" "ERROR_ON_UNDEFINED_SYMBOLS=1"
  = note: /usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libstd-610aec1c0c2edd5b.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libpanic_unwind-f2d5dd75c5a64c5f.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libunwind-cce8009dda26867d.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/librand-d2f56491199d3b9f.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libcollections-4f02fd86535a3157.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/librustc_unicode-8d6c34ad46f07f91.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/liballoc-198f48436646c796.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/liballoc_system-22e63f2ceba0e6f8.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/liblibc-9b19cb4b417215a8.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libcore-ec0461203eec19c8.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

/usr/local/opt/emscripten/libexec/llvm/bin/llvm-nm: /Users/kevinballard/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/wasm32-unknown-emscripten/lib/libcompiler_builtins-ad8606f391af463e.rlib(rust.metadata.bin) The end of the file was unexpectedly encountered

Traceback (most recent call last):
  File "/usr/local/bin/emcc", line 13, in <module>
    emcc.run()
  File "/usr/local/Cellar/emscripten/1.36.14/libexec/emcc.py", line 1609, in run
    wasm_js_glue = open(os.path.join(shared.Settings.BINARYEN_ROOT, 'src', 'js', 'wasm.js-post.js')).read()
IOError: [Errno 2] No such file or directory: u'/usr/bin/src/js/wasm.js-post.js'

This is on macOS 10.12.2, Rust 1.14.0, and emscripten 1.36.14.

@brson
Copy link
Contributor

brson commented Dec 22, 2016

Thanks for the report @kballard. I intend to make a sweep through all the emscripten issues soon and try to make some fresh progress.

@brson brson added O-asmjs Target: asm.js - http://asmjs.org/ O-wasm Target: WASM (WebAssembly), http://webassembly.org/ labels Dec 30, 2016
@brson brson changed the title emscripten link failures on macOS emscripten link failures on macOS "The end of the file was unexpectedly encountered" Dec 31, 2016
@brson brson changed the title emscripten link failures on macOS "The end of the file was unexpectedly encountered" emscripten link failures on macOS - "The end of the file was unexpectedly encountered" Dec 31, 2016
@brson
Copy link
Contributor

brson commented Dec 31, 2016

Same as the secondary issue in #37185

@wehlutyk
Copy link

I'm seeing the same issue on an up-to-date ArchLinux, with Rust 1.14.0 and Emscripten 1.37.1 (following the same steps). The asm.js build works fine though.

@mckinnsb
Copy link

mckinnsb commented Jan 25, 2017

Also seeing what @wehlutyk reported on Ubuntu 16 on nightly.

In this case, it only happens when I build for release, but the debug build fails regardless ( with error: "Uncaught no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: " ).

@brson brson changed the title emscripten link failures on macOS - "The end of the file was unexpectedly encountered" wasm link failures - "The end of the file was unexpectedly encountered" Jan 27, 2017
@brson
Copy link
Contributor

brson commented Jan 27, 2017

Thanks for the additional reports @wehlutyk @mckinnsb . I've updated the title to indicate it's multiplatform.

@donhcd
Copy link

donhcd commented Feb 14, 2017

on OSX 10.11.5, rustc 1.17.0-nightly (956e2bc 2017-02-12), emcc 1.36.11 (commit c5af8f63f00bb03aa2177c71d16628474918b60f), I get a similar but slightly different error if I compile with target wasm and with the --release flag.

It works perfectly if I leave out the --release flag.

@CryZe
Copy link
Contributor

CryZe commented Feb 16, 2017

This is a "duplicate" of this issue: WebAssembly/binaryen#855

Pretty sure this is due to the vector instructions that rustc emits. This should happen a lot more with the recent changes @RReverser introduced, since --release now actually produces vector instructions, which it didn't before, because --release didn't actually run any optimizations.

@RReverser
Copy link
Contributor

@CryZe --release did still run Rust / LLVM optimizations before, the only difference is that it now also asks Emscripten to run JS-specific optimizations. If, as it sounds from the description, the error is on Rust side emitting unsupported instructions (and not Emscripten's), then nothing should have changed compared to previous state.

@CryZe
Copy link
Contributor

CryZe commented Feb 17, 2017

@RReverser That's pretty weird then. Cause Rust passing -O3 to emcc is what breaks it. But the thing is that half of all trivial projects and no larger Rust project can be compiled to wasm because of this bug. If this is not caused by Rust, then it would be really weird how no one on emscripten's side noticed that. They are even starting to prepare to release 1.0 now, so I doubt that they fail to build trivial projects and all larger ones. I guess I'll look into the generated IR later today.

@RReverser
Copy link
Contributor

@CryZe Given the original report in this thread, it appears that it was throwing even without -O3?

@CryZe
Copy link
Contributor

CryZe commented Feb 17, 2017

@RReverser the original issue might be unrelated then. Anyways, -O3 is definitely what makes it not compile due to vector instruction in about half of the ~30 projects I tried to compile to wasm (with the rest working).

@RReverser
Copy link
Contributor

Ok I can reproduce this, but only with wasm target and only with -O3 as @CryZe said. Original report could reproduce without -O3, but I noticed it used older Emscripten issue.

Now, I tried small file with few functions, one of which works with array in vectorizable manner (for item in x { *item |= 10; }) and I can indeed see that issue happens with it, and doesn't without it, so agree with conclusion it's vectorization that specifically binaryen might not support (while regular emscripten does).

@CryZe
Copy link
Contributor

CryZe commented Feb 19, 2017

I think the next step would be figuring out if those vector instructions get emitted on emscripten's side or rustc.

@RReverser
Copy link
Contributor

Yep.

Function:

#[no_mangle]
pub extern fn f3(x: &mut [i32]) {
    for item in x {
        *item |= 10;
    }
}

LL:

; Function Attrs: nounwind uwtable
define void @f3(i32* nonnull, i32) unnamed_addr #0 {
entry-block:
  %2 = getelementptr inbounds i32, i32* %0, i32 %1
  %3 = icmp eq i32 %1, 0
  br i1 %3, label %bb4, label %bb5.preheader

bb5.preheader:                                    ; preds = %entry-block
  %4 = shl i32 %1, 2
  %5 = add i32 %4, -4
  %6 = lshr exact i32 %5, 2
  %7 = add nuw nsw i32 %6, 1
  %min.iters.check = icmp ult i32 %7, 4
  br i1 %min.iters.check, label %bb5.preheader19, label %min.iters.checked

bb5.preheader19:                                  ; preds = %middle.block, %min.iters.checked, %bb5.preheader
  %iter.sroa.0.0.in12.ph = phi i32* [ %0, %min.iters.checked ], [ %0, %bb5.preheader ], [ %ind.end, %middle.block ]
  br label %bb5

min.iters.checked:                                ; preds = %bb5.preheader
  %n.vec = and i32 %7, 2147483644
  %cmp.zero = icmp eq i32 %n.vec, 0
  %ind.end = getelementptr i32, i32* %0, i32 %n.vec
  br i1 %cmp.zero, label %bb5.preheader19, label %vector.body.preheader

vector.body.preheader:                            ; preds = %min.iters.checked
  br label %vector.body

vector.body:                                      ; preds = %vector.body.preheader, %vector.body
  %index = phi i32 [ %index.next, %vector.body ], [ 0, %vector.body.preheader ]
  %next.gep = getelementptr i32, i32* %0, i32 %index
  %8 = bitcast i32* %next.gep to <4 x i32>*
  %wide.load = load <4 x i32>, <4 x i32>* %8, align 4
  %9 = or <4 x i32> %wide.load, <i32 10, i32 10, i32 10, i32 10>
  %10 = bitcast i32* %next.gep to <4 x i32>*
  store <4 x i32> %9, <4 x i32>* %10, align 4
  %index.next = add i32 %index, 4
  %11 = icmp eq i32 %index.next, %n.vec
  br i1 %11, label %middle.block, label %vector.body, !llvm.loop !1

middle.block:                                     ; preds = %vector.body
  %cmp.n = icmp eq i32 %7, %n.vec
  br i1 %cmp.n, label %bb4, label %bb5.preheader19

bb4.loopexit:                                     ; preds = %bb5
  br label %bb4

bb4:                                              ; preds = %bb4.loopexit, %middle.block, %entry-block
  ret void

bb5:                                              ; preds = %bb5.preheader19, %bb5
  %iter.sroa.0.0.in12 = phi i32* [ %12, %bb5 ], [ %iter.sroa.0.0.in12.ph, %bb5.preheader19 ]
  %12 = getelementptr inbounds i32, i32* %iter.sroa.0.0.in12, i32 1
  %13 = load i32, i32* %iter.sroa.0.0.in12, align 4
  %14 = or i32 %13, 10
  store i32 %14, i32* %iter.sroa.0.0.in12, align 4
  %15 = icmp eq i32* %12, %2
  br i1 %15, label %bb4.loopexit, label %bb5, !llvm.loop !4
}

@CryZe
Copy link
Contributor

CryZe commented Feb 19, 2017

Oh btw, whenever this gets fixed, we may want to turn vectorization off for asm.js as well, as it's a non-standard extension that turns it into "almost asm", which probably isn't even interpreted as asm.js by any Browser other than Firefox. So vectorization is mostly hurtful for most browsers anyway.

@RReverser
Copy link
Contributor

@CryZe Well there are ways to compile it efficiently even w/o SIMD at least for cases like above, but otherwise agree.

@CryZe
Copy link
Contributor

CryZe commented Feb 20, 2017

Pretty weird how setting loop-vectorize to false has no effect then.

Update: Uhhhh, they do work?! At least in the code you provided. I don't know how larger code is still vectorized then.

@CryZe
Copy link
Contributor

CryZe commented Feb 20, 2017

Oh, I think I may know what the problem is. The standard library. It's built with vectorization!

@RReverser
Copy link
Contributor

@CryZe Ah yes, makes sense. Want to submit a PR that disables vectorization for emscripten targets?

@RReverser
Copy link
Contributor

@CryZe Although I still don't fully understand where this happens. Is standard library built with vectorization and -O3 already or is it link-time issue?

@RReverser
Copy link
Contributor

@CryZe And doesn't explain why issue isn't present when compiling code without such a function that uses vectorization on its own. If issue would be in precompiled standard library, it should be present even on files with just fn main() {}.

@CryZe
Copy link
Contributor

CryZe commented Feb 20, 2017

Okay, so this is interesting. I just have a BinaryHeap and I'm pushing a struct of 4 usize fields into it. And that gets turned into a vector instruction. However, since this is a generic, this can't be prebuilt in any way and yet there's still vector instructions.

@CryZe
Copy link
Contributor

CryZe commented Feb 20, 2017

Alright, this still breaks it, even with the two no-vectorize flags: https://gist.github.com/CryZe/eed7f1f47c638f14f92daebe1a1ca17e

Update: Looks like this is yet another bug. This affects asm.js too?!

@CryZe
Copy link
Contributor

CryZe commented Feb 20, 2017

Okay, so apparently cargo rustc doesn't transitively apply the rustc flags you provide, which caused all those additional issues. However .cargo/config does and it fixed all the issues I found. So I'm fairly certain now that turning those two flags off for wasm will work in most cases. I'm not fully sure if it's all, but we can definitely implement this and then see if there's still some issues.

@RReverser
Copy link
Contributor

Oh yeah, I never use cargo for such precise testing, best is to use rustc directly.

CryZe added a commit to CryZe/rust that referenced this issue Feb 20, 2017
When targeting Emscripten, rustc emits Vector Instructions by default.
However Web Assembly doesn't support Vector Instructions yet, which
causes Binaryen to fail converting the intermediate asm.js code to Web
Assembly. While asm.js kind of supports Vector Instructions, they
aren't supported by any browser other than Firefox, often meaning that
they need to be emulated very slowly. So it should just be turned off
for all Emscripten targets.

Fixes rust-lang#38558
bors added a commit that referenced this issue Feb 21, 2017
Turn off Vectorization for Emscripten

When targeting Emscripten, rustc emits Vector Instructions by default. However Web Assembly doesn't support Vector Instructions yet, which causes Binaryen to fail converting the intermediate asm.js code to Web Assembly. While asm.js kind of supports Vector Instructions, they aren't supported by any browser other than Firefox, often meaning that they need to be emulated very slowly. So it should just be turned off
for all Emscripten targets.

Fixes #38558
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-asmjs Target: asm.js - http://asmjs.org/ O-wasm Target: WASM (WebAssembly), http://webassembly.org/
Projects
None yet
Development

No branches or pull requests

7 participants