-
Notifications
You must be signed in to change notification settings - Fork 13k
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 supporting asm.js and WebAssembly without Fastcomp #44006
Comments
@tlively I'm no LLVM expert, but when I look into rust's fork of LLVM, then |
Can confirm - the entire JavaScript backend lives in Every JS-specific modification to LLVM outside of this directory is decorated like so
It is |
Remove support for the PNaCl target (le32-unknown-nacl) This removes support for the `le32-unknown-nacl` target which is currently supported by rustc on tier 3. Despite the "nacl" in the name, the target doesn't output native code (x86, ARM, MIPS), instead it outputs binaries in the PNaCl format. There are two reasons for the removal: * Google [has announced](https://blog.chromium.org/2017/05/goodbye-pnacl-hello-webassembly.html) deprecation of the PNaCl format. The suggestion is to migrate to wasm. Happens we already have a wasm backend! * Our PNaCl LLVM backend is provided by the fastcomp patch set that the LLVM fork used by rustc contains in addition to vanilla LLVM (`src/llvm/lib/Target/JSBackend/NaCl`). Upstream LLVM doesn't have PNaCl support. Removing PNaCl support will enable us to move away from fastcomp (#44006) and have a lighter set of patches on top of upstream LLVM inside our LLVM fork. This will help distribution packagers of Rust. Fixes #42420
cc #45905 |
(continuing discussion from #45905)
But what should do Web version then? Should it implement fs, net, env, etc emulation in JS? Or should it trap? If we chose to implement emulation then we will need a JS shim library, which will call "real" APIs or emulated ones depending on which "sub-environment" we running on. But then, what if user wants to run only one "sub-environment"? Or user doesn't want either fs or net, or nothing at all? Applications of wasm should be truly beyond the web. Fast, safe and deterministic execution seems to be pretty desired properties!
Some of environments can implement complete
Even not all WASM features are always desired (due to performance reasons and/or need of deterministic execution):
I think, this makes wasm to be more like ISA than end user platform. (Not to mention that we even have problems of combining JS/Web and JS/Node). To properly handle all this zoo, I think, we need something like portability lint and maybe a few more triples, like this strawman:
It will make portability lint useless, isn't it? |
I still think having wasm32-unknown-unknown providing the bare minimum (with a libstd where it makes sense) will get us a long way.
It should implement shims for these things.
Yes, we will need this shim. That's the same as it works in Emscripten today.
If it is possible to modularize these different things, it would be up to the user to load the necessary things before loading the wasm module (again: I did not look into Emscripten's shims yet and how easy it would be to extract those things). (I'm gonna read that portability lint RFC now) |
I agree on this too. But it seems we disagree on what "bare minimum" means : ) For me, "bare minimum" doesn't include fs, net, processes, rng, etc.
OK, here is my direct question then: why don't use Emscripten if one needs full-blown std library with support of Web, Node? 😃 |
IMO, non-web applications of wasm won't want the shims, and code that doesn't use the shims won't want the shims. Keep the minimum small, build from there, IMO. |
Rather than |
@SimonSapin yeah, maybe. One thing that comes to my mind is threads. WASM threads propolsal (it's still WIP though) suggests adding |
There is one more point: things that only could be implemented in terms of Also, if I squint enough, I can imagine implementation of |
liballoc depends on libcore, so I don’t think depending on both is a sufficient reason to have things in libstd. In the case of As to |
HashMap being hasher agnostic and residing in liballoc would be helpful btw |
Oh, I see. That's unfortunate.
Agree with @NikVolf on that |
I don’t know if a |
@SimonSapin I imagine something like |
It would be |
For me, the reason not to use Emscripten is to avoid duplication and complexity in the building toolchain and not because of the libraries. The opposite, having emulation of native APIs that works on Node.js/Web has always been the most exciting part of Emscripten to me as it allows to write fully native apps and libraries and run them on different environments without any hassle. |
So, just to make sure everyone's on the same page here, WebAssembly's spec defines no platform details. Platform details are expected to be layered on top. This is specifically so that wasm can be used outside of a web context, and in fact, not only is that an important use-case overall, but an important use-case for production Rust users: Etherium plans on using wasm as their scripting language, for example. As such, I'd very very much prefer that the |
The thing we are arguing is that there shouldn‘t be a -web. Maybe -std or something that has a proper std implementation, which I‘m totally okay with, if there is actually is a good reason for the target with the stubbed out std. However the fact that people are arguing for a target with a stubbed out std makes it seem that there‘s actually rather something wrong with core, which people really try to avoid. |
To back @CryZe's words: all the bindings we are discussing are not any specific to Web, Node.js or any other host. We don't expect nor want Rust to do any web platform integration - that can be done in custom crates and npm packages. These bindings that we need are very generic and are needed by Rust just for proper functioning of This is completely orthogonal to portability lints, which might or might be not used in conjunction with such generic "kernel" bindings. |
There is a problem with core, no one supports it. But i like the idea of portability lints. We could even make |
@RReverser The fact of the matter is, Node supports a lot of stuff that the web does not and cannot without emulation. This means that there is a place for a
@CryZe To be clear, I am not arguing for a stubbed out std. (I'm not sure anyone else is either??) I'm arguing for a subsetted std that includes only what the web platform supports. That way there are three tiers to using Rust in a browser-hosted wasm:
The |
Far not necessary. There are cases when TcpStreams are implemented in browser with a WebSocket proxy (this actually works and is used in e.g. x86 emulators in browser), File::open can be implemented with File API or point to local storage and so on. It's not the job of Rust to decide what to expect on the other side from a dynamic language and how these APIs are implemented, this is up to the consumer of compiled WASM.
To reiterate points from previous comments - why would this be separated into |
APIs for getting the date or something do need javascript right now, and there is only one way of implementing them. If you want to be free in the choice of the file system, put it into your program! Why should rust play the abstraction layer here? Your library code should work on anything that impls the Read/Write trait, and it can be a cursor.
You also have a separation between windows, mac and linux targets. There is wine, people can just use the windows API everywhere and yet they everyone wants to compile stuff natively. The reason is that then everything is tailored for your specific target. |
The reason for this is simply that you can't expect your consumer to have Wine. Better example would be Linux GNU targets for which Rust compiles just once with We just suggest to do with WebAssembly - list expected bindings for JavaScript libraries have been moving strictly towards being universal (or also, so-called "isomorphic") over the last years, and it would be a huge step back for WebAssembly target to separate |
@est31 Because why not? Would you prefer to have duplicates of each crate that work on different targets, or a single crate that just uses |
This doesn't make any sense. Nobody is opposed to providing a target that includes or supports
You seem confused. We already cross-platform crates via |
I would absolutely hate duplicates. But that won't happen when your library exposes a functionality to work on a Read/Seek/Write trait impl and doesnt just eat a path and serialize it on itself.
Again, C/JVM based targets might not get in touch with javascript at all, and some use cases certainly will not. Don't put the API at the Js layer! About unification, sure it's great, and I think most code will work both on a -node and a -web target, but then there are differences between browsers and for those you should be able to differentiate at compile time, just like you are able to differentiate today between |
Again, the main question: why would you want it? What does it give you? You'll get exactly same error for unsupported stuff right away when you try to import such WebAssembly with missing bindings on your platform, except you'll have a choice to stub it on your side if it's already a dependency of consumed library. This way it will be possible to distribute same WebAssembly library for all supported platforms, and consumers will just need to import it with their platform's bindings, without recompiling Rust code.
Of course, that's the goal we want to enable. None of the suggested bindings are JS-specific, and as I said dozen of times above, none of them have to be - they're all just regular "kernel functions" universal to any platform. |
This all seems to come down to whether WebAssembly should be portable enough to just stick the same WebAssembly module into Java / Web / C / ... or if you should always recompile it. If it should be that portable, then we need one defined kernel interface that the module talks to. If not, then we should go for multiple separate targets, but completely miss out on the wasm module being portable at all then. |
Yup, I think you summarised the two camps in this thread pretty well. I'm in the portable one - after all, it was one of primary goals of WebAssembly to abstract away from specific operating systems, virtual machines and so on, and provide a single binary format executable on any of them right away. Removing this abstraction and recompiling for each target seems unnecessary and makes WASM barely more useful than some C code or LLVM IR. |
@CryZe the portability that wasm is about is for me at least about being portable across operating systems and hardware, not across different embeddings. Embeddings change rarely and if they do, you can recompile stuff. I mean you can disagree with me on the importance of being portable across embeddings, but "completely miss out" is quite overblown in any case. |
You can get that functionality from the There should be a way to compile a wasm module+js glue that you can just throw into a browser and have it work. Thus,
This is an inaccurate description of my argument. We can have both! We should define a standard interface that std requires. We should also allow people to target specific embeddings and generate the glue code for them. |
Perhaps an additional target or flag would be helpful- a way to get the |
Oh, then we must've been talking past each other, cause I totally agree with that. I think the standard interface is necessary for supporting all kinds of random embeds that rust has no specific target for, but specific targets could definitely have more specific bindings and APIs, like a js! macro and maybe some DOM APIs. |
So.... we all agree on a js macro then? I'm writing an RFC to add one to the language. I'll link it here. |
I'd definitely like to these to exist, but I don't really see why custom macro, DOM APIs etc. can't live in custom crates and npm packages just like any other userland code, especially integration-specific one. |
They can and should, along with targets to organize |
So these extra targets would be nice, but for the current
Regardless of how the webassembly is being hosted, the host can choose to set these function pointers or leave them unset. If they are left unset then the behaviour can be as it is today. If they are set, then libstd calls them to handle each case. This solves the current blocker for me, which is that I can run wasm tests in the browser, but I can't tell if they pass or fail... (libstd currently throws away stdout, stderr and the exit code). |
@RReverser We have multiple different implementations of such a macro. If you use one implementation, you are required to use that implementation's tool after the fact. If it is in the compiler, it would serve as minimal standard. Also, it would be usable by std. std can't depend on other crates, so having such a macro would be a requirement for targets with tailored std APIs. About the fully dynamic target idea, I think I'm convinced now that having one would be useful. |
You are probably right, for js! macro it makes sense as it essentially requires own linking step (at least for release builds, for debug builds it could just dynamically create For DOM and such though, I think it makes sense to put them into own crates / packages, they don't require much from compiler or std internals and can build on top of |
Definitely, this belongs into crates. std shouldn't have any additional features than it provides on other platforms as well. |
We've had a ton of progress since this was opened and I'm going to close this now as we're now quite decoupled from the Emscripten backend on master and wasm32-unknown-unknown has started picking up a lot of these elements. In general we're going to follow Emscripten master, but this is mostly a bug for Emscripten rather than rust-lang/rust at this point, so I'm going to close. |
Breaking Rust's dependency on Fastcomp will allow upgrades to Rust's LLVM to be much smoother because they won't depend on Fastcomp being updated. Smoother upgrades will allow LLVM to be kept up to date more easily (#42389), which will be beneficial across the board but especially for WebAssembly as its LLVM backend matures. It is necessary that the asmjs and wasm targets emit object files instead of LLVM bitcode so that bitcode version mismatches between Rust and Emscripten won't be a problem. Work that needs to be done to break the dependency on Fastcomp includes:
The text was updated successfully, but these errors were encountered: