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

Tracking issue for wasm support #38805

Closed
11 of 15 tasks
brson opened this issue Jan 3, 2017 · 29 comments
Closed
11 of 15 tasks

Tracking issue for wasm support #38805

brson opened this issue Jan 3, 2017 · 29 comments
Labels
C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. E-help-wanted Call for participation: Help is requested to fix this issue. O-wasm Target: WASM (WebAssembly), http://webassembly.org/ T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue.

Comments

@brson
Copy link
Contributor

brson commented Jan 3, 2017

It's been a while since I've looked at the state of wasm in Rust, and
there's a lot more to be done for it to be really usable. Is anybody
doing anything significant with Rust and emscripten yet?

Today I've triaged all the emscripten issues and put together a little
roadmap. I'm hoping others can help fill in the gaps here and get this
across the finish line.

I'll start by outlining the near-term scope, some discussion of the
state of things, then the tasks.

Goal: Make Rust on wasm + emscripten a reliable, 1st class Rust target.

Success metrics:

  • Cross-compilation works from macOS, Windows and Linux
  • Tests are running against wasm on the bots
  • All common crates without significant platform or I/O deps work as expected
    and pass their test suites
  • One can test wasm via the 'cross' tool or some other tool
  • The rustc and emcc LLVM versions are decoupled
  • One can tweak relevant emcc options in a consistent way
  • Rust on emcc is as fast as possible when building in release mode

Out of scope:

  • Automatic installation of emscripten
  • Retaining asm.js compatibility

Discussion

Today I read reports of problems compiling from Windows and macOS;
some important crates that should obviously work just don't, like
regex; I have no idea whether the test suite still passes.

Setting up emcc is not foolproof, but I don't think we should worry
about solving it now, since no other cross target solves the problem
of acquiring the linker. Perhaps something like the cross tool will
suffice - it or something like it will be needed for testing emcc
targets anyway.

The issue of LLVM coupling remains the worst, and with the pending
llvm upgrade it's a pressing matter. To recap, today rustc uses the
emcc 'fastcomp' LLVM backend to communicate LLVM IR to emcc, to
compile to wasm/asm.js. This forces rustc and emcc to share an LLVM
fork, which is not sustainable (emcc LLVM development is basically
complete - the only reason for them to upgrade LLVM is because we
upgrade LLVM).

The only viable solution I see is to migrate to the upstream LLVM wasm
backend, changing the rustc wasm model such that rustc produces wasm
directly, and emcc links that. And this model unfortunately
precludes asm.js support until somebody writes a wasm->asm.js
translator. I think this is just the way it has to be. The future is
wasm, and we can't maintain LLVM in sync with emcc for long.

I don't think though we can do the migration to the LLVM wasm backend
before the next LLVM upgrade though, because that backend is not
ready. So we're probably going to be asking @azakai to upgrade emcc to
LLVM 4.0 and continuing with the LLVM IR -> emcc -> wasm path for a
while.

Tasks

@brson brson added O-wasm Target: WASM (WebAssembly), http://webassembly.org/ E-help-wanted Call for participation: Help is requested to fix this issue. T-tools labels Jan 3, 2017
@kripken
Copy link

kripken commented Jan 3, 2017

Out of scope: [..] Retaining asm.js compatibility

Just curious, why? Doing asm.js first, which is very stable, is the more reliable path, instead of going straight to wasm. It's true it requires the fastcomp update, which might or might not be a lot of work, which I don't think we know yet.

@est31
Copy link
Member

est31 commented Jan 3, 2017

@kripken have you read further below? It seems that @brson wants to use LLVM's wasm backend, which would apparently mean that asm.js compat is dropped. It would make sense as then emcc wouldn't block the LLVM upgrade any more.

@kripken
Copy link

kripken commented Jan 3, 2017

Yeah, that's a bunch of additional questions, though, as currently it is not yet stable and produces larger/slower code. But it does have the advantage of not maintaining an LLVM fork, which is considerable of course.

In principle, if we want to do the least work for rust-on-the-web, we could wait for the wasm backend or use it with the downsides, if we don't mind them.

@chicoxyzzy
Copy link

chicoxyzzy commented Jan 3, 2017

I'm not sure if this is a good place for my comment but I don't know where to create an issue. Please point me to the right repo in case it's off topic.

I was following instructions from https://users.rust-lang.org/t/compiling-to-the-web-with-rust-and-emscripten/7627 and had no luck in generating working example.

  • Resulting JS file doesn't work on node. Error is
no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods
  • Running wasm file on Node doesn't work because latest Node doesn't expose Memory property of WebAssembly object
  • Looking into wast file I don't see "Hello, Emscripten!" string anywhere
  • Then I've created index.html with such content:
<script type='text/javascript'>
 fetch('hello.wasm')
  .then(response => response.arrayBuffer())
  .then(buffer => WebAssembly.compile(buffer))
  .then(console.log)
</script>

and ran Python's SimpleHTTPServer. Running this in latest Chrome Canary with WebAssembly enabled doesn't do anything while not throwing errors and showing an empty wasm module object.

So I'm not sure if Rust code cross-compiles to correct wasm module at all for now (using rustc 1.14.0 and emcc 1.37.0 / 1.37.1). Am I doing something wrong?

@kripken
Copy link

kripken commented Jan 3, 2017

In general you can open an issue on the binaryen tracker (often it's the right place, if not that's fine too). Regarding your issues:

  • Yes, node.js doesn't have wasm support yet. You can use SpiderMonkey or V8 shells (very latest versions), or nightly/canary versions of the browsers. Or, enable the interpreter, which will work everywhere.
  • You should see the string in the wast, that is surprising. It should be in the memory segments, near the top of the file. Are there no memory segments? Earlier binaryen versions didn't use them, but we should now.
  • You can't load the wasm by yourself - it isn't standalone (there is work towards standalone wasm, which perhaps rust can use eventually). The JS code knows how to load it and run it. Try to just create an html page with <script src="the.js"></script> in it.

@chicoxyzzy
Copy link

Just created WebAssembly/binaryen#867

@chicoxyzzy
Copy link

Update: cross-compiling to wasm works as expected

@CryZe
Copy link
Contributor

CryZe commented Jan 5, 2017

There's one massive problem when compiling Rust to WASM which made it fail in about half the Advent of Code puzzles I tried (and a lot of other projects including my current large project). It's the fact that Rust generates auto vectorized code which then fails in the asm2wasm conversion step as it doesn't support vectorization yet. It is impossible to turn off auto vectorization at the moment as it seems. Neither the emscripten flags nor the Rust flags seem to affect it. So this definitely needs to be fixed.

Here's the binaryen issue for it: WebAssembly/binaryen#855

Update: Playing around more with this, this seems to just randomly work now if you pass the no vectorization flags?!

Update 2: Nvm, it still doesn't work in my larger project. This is just super odd. I guess a lot of commonly used crates do manual vectorization which you can't just turn off with flags?!

Update 3: Turns out it's not any crates that cause this. This is definitely either rustc or emcc generating vector instructions that you can't turn off.

@aidanhs
Copy link
Member

aidanhs commented Jan 6, 2017

@kripken

as currently it is not yet stable and produces larger/slower code

I assume the llvm parts are mostly similar, so you're referring to the emscripten asm.js optimizer passes? Which is a partially solved problem if documentation includes the three commands necessary to use ayzim (though this would require the converter to not 'finalize' the asm.js).

@kripken
Copy link

kripken commented Jan 6, 2017

@aidanhs Yes, LLVM IR optimizations are identical - the difference is only in "backend" opts. But the asm.js optimizer isn't necessarily used in this case. On the LLVM backend side, LLVM does the backend opts; on the asm2wasm side, backend opts may be done by either the asm.js optimizer (from emscripten, or in principle could be ayzim) or wasm optimizer (from binaryen), or just with the wasm optimizer by itself. The last option is currently enabled by default, as it has some benefits, although the asm.js optimizer is automatically run if the code is also meant to be runnable as asm.js as an option. (I have a blogpost in the works about this stuff.)

@aidanhs
Copy link
Member

aidanhs commented Jan 7, 2017

Right, I see the issue more clearly now - binaryen is good, but the llvm wasm backend doesn't contain all of binaryen.

If a wasm file generated by the llvm backend were run through the binaryen optimizer, would it 'converge' to be similar to a file generated via the asm2wasm route? If so, it might be reasonable to offer the binaryen optimizer as a separate tool (or ayzim, when I port it). Depending on what the rust team prefer this optimizer (C++ or rust) could be inside rustc as a strange post-compilation pass, with the promise that the code will disappear as the llvm wasm backend gets more mature.

Regarding stability, I'd be in favour of the wasm llvm backend regardless of optimizer thoughts - more exposure will make the backend better, and the rust users giving it a go as a first class target will help make sure that it's robust come wasm 'release'.

@kripken
Copy link

kripken commented Jan 7, 2017

If a wasm file generated by the llvm backend were run through the binaryen optimizer, would it 'converge' to be similar to a file generated via the asm2wasm route?

Not currently. The wasm backend doesn't emit ifs/if_elses, for example, and binaryen doesn't have passes to convert code to that form (because it doesn't need to currently, the asm.js backend uses the relooper to do that). Also the binaryen optimizer would need to undo a bunch of things the wasm backend does, like register allocation. In principle all that could be done, but it hasn't been a priority.

@brson
Copy link
Contributor Author

brson commented Jan 27, 2017

Just curious, why? Doing asm.js first, which is very stable, is the more reliable path, instead of going straight to wasm. It's true it requires the fastcomp update, which might or might not be a lot of work, which I don't think we know yet.

@kripken the reason to move quickly to the LLVM wasm backend and concede asm.js support is that the alternative is to continue upgrading fastcomp to newer LLVM revisions, which I know is a great deal of work (edit: oops I didn't mean to contradict you - maybe it's not a lot of work). I'm happy to keep using the model we have now, running through fastcomp, for as long as it is advantageous, but the tradeoff is significant.

Looks like @dylanmckay has started the fastcomp upgrade. Thank you so much @dylanmckay

@brson
Copy link
Contributor Author

brson commented Jan 27, 2017

The C linkage issue is progressing #39171.

Added to the op a new issue to make sure the extensions we're using are correct for all output types.

@Fishrock123
Copy link
Contributor

Fishrock123 commented Mar 6, 2017

@brson The following issues appear to have been closed, think you could update their status in the OP?

@Fishrock123
Copy link
Contributor

Also, are there any plans/ideas to support WebAssembly standalone (Side Modules)? (https://github.com/kripken/emscripten/wiki/WebAssembly-Standalone)

@CryZe
Copy link
Contributor

CryZe commented Mar 14, 2017 via email

@eholk
Copy link
Contributor

eholk commented Mar 14, 2017

@Fishrock123 WebAssembly standalone is something I think would be great to see. It's one of the things I'm trying to experiment a little with mir2wasm.

@Fishrock123
Copy link
Contributor

@CryZe Oops! Must have copied that wrong, fixed. :)

@eholk Right, saw that repo. Got at least some Rust running yesterday without the emscripten wrapper. :D

@Eh2406
Copy link
Contributor

Eh2406 commented Apr 26, 2017

What Is this up to? How does the update to LLVM 4.0 change things?

@vadimcn
Copy link
Contributor

vadimcn commented Apr 26, 2017

I gave it a try a little while back: upgraded LLVM to the latest master, tweaked wasm target definition, etc.

For a simple self-contained program (factorial), rustc was able to produce correct-looking wasm code.
Back then, LLVM used ELF as a container for said code, but I found a tool to convert it to a straight wasm module. So far so good...
However, in order to interact with the world, you need a runtime. I wanted to re-use emscripten's runtime, but at the time (and this is still true, I think), emcc did not support taking wasm modules as input, so there was no way to link it.

I've heard that LLVM recently had grown support of direct emission of wasm modules, as well as adding wasm linking in lld, so I intend to give it a second try one of these days.

@rschulman
Copy link
Contributor

Is wasm support broken in the latest versions? I've got rustc 1.18.0-nightly (3b5754e5c 2017-04-10) and
emcc (Emscripten gcc/clang-like replacement) 1.37.12 (commit ccaf4e74fa9abf51cff8d1d4823f0b4d84bf3eab) and doing a cargo build --target=wasm32-unknown-emscripten on a generic "Hello, world" is giving me a standalone javascript file in the output directly, but no .wasm file to be found anywhere. I'm totally open to the idea that I'm missing something obvious, but I have no idea what it could be at this point.

@CryZe
Copy link
Contributor

CryZe commented May 8, 2017 via email

@Mark-Simulacrum Mark-Simulacrum added T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. and removed T-tools labels May 24, 2017
@lilianmoraru
Copy link

@kripken

as currently it is not yet stable and produces larger/slower code

Wasm seems to perform better in this demo/benchmark(I'd say, very well - since it reaches almost the performance of the native application): https://davidmcneil.github.io/the-rusty-web/#benchmarks

@kripken
Copy link

kripken commented Jun 7, 2017

@lilianmoraru I'm not sure, but I think that benchmark was built using asm2wasm, not the wasm backend, which is what I was referring to in that quote. What I mean is that there are two separate ways to emit wasm, asm2wasm and the wasm backend, and only the wasm backend is not yet stable or optimized for size or speed. But emitting wasm using asm2wasm is considered stable and should be faster and smaller than asm.js (and close to native).

@lilianmoraru
Copy link

@kripken It was built using this command: cargo build --release --target wasm32-unknown-emscripten.
Reference here: https://github.com/davidMcneil/the-rusty-web#running-on-the-web

Btw, a note on the performance, it is "finicky": davidMcneil/the-rusty-web#3

@lilianmoraru
Copy link

@brson If you think it is related, here is another issue I just opened for Wasm32: #42518 .
Brotli has great compression rate/decompression speed ratio(https://quixdb.github.io/squash-benchmark/), so I wanted to see if I can make Dropbox's Brotli decompressor compile for Wasm32.
Thinking of something like docs.rs where it could compress very well the documentation(a lot of text) once and then decompress it with Brotli on the user's side, with the help of Wasm32.

@Mark-Simulacrum Mark-Simulacrum added the C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. label Jul 26, 2017
@Herschel
Copy link
Contributor

I'm having the same problem as @rschulman, where no .wasm file is output when using cargo build --target=wasm32-unknown-emscripten. Building using rustc outputs the file. I'm on darwin nightly rustc 1.21.0-nightly (7ac979d8c 2017-08-16) and emcc 1.37.18.

@alexcrichton
Copy link
Member

I'm going to close this as lots of progress has happened in the meantime and the best metabug-like-tracker for this is now currently at https://github.com/rust-lang-nursery/rust-wasm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. E-help-wanted Call for participation: Help is requested to fix this issue. O-wasm Target: WASM (WebAssembly), http://webassembly.org/ T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests