Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upTracking issue for supporting asm.js and WebAssembly without Fastcomp #44006
Comments
Mark-Simulacrum
added
C-tracking-issue
O-asmjs
O-wasm
labels
Aug 21, 2017
This was referenced Aug 27, 2017
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@tlively I'm no LLVM expert, but when I look into rust's fork of LLVM, then |
tlively
referenced this issue
Oct 5, 2017
Closed
Remove support for the deprecated PNaCl technology #42420
This comment has been minimized.
This comment has been minimized.
|
Can confirm - the entire JavaScript backend lives in Every JS-specific modification to LLVM outside of this directory is decorated like so
It is |
bors
added a commit
that referenced
this issue
Oct 9, 2017
This comment has been minimized.
This comment has been minimized.
|
cc #45905 |
This comment has been minimized.
This comment has been minimized.
|
(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? |
This comment has been minimized.
This comment has been minimized.
|
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) |
This comment has been minimized.
This comment has been minimized.
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? |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
Rather than |
This comment has been minimized.
This comment has been minimized.
|
@SimonSapin yeah, maybe. One thing that comes to my mind is threads. WASM threads propolsal (it's still WIP though) suggests adding |
This comment has been minimized.
This comment has been minimized.
|
There is one more point: things that only could be implemented in terms of Also, if I squint enough, I can imagine implementation of |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
|
HashMap being hasher agnostic and residing in liballoc would be helpful btw |
This comment has been minimized.
This comment has been minimized.
Oh, I see. That's unfortunate.
Agree with @NikVolf on that |
This comment has been minimized.
This comment has been minimized.
|
I don’t know if a |
This comment has been minimized.
This comment has been minimized.
|
@SimonSapin I imagine something like |
This comment has been minimized.
This comment has been minimized.
|
It would be |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
Can you elaborate on the duplication and complexity part? |
This comment has been minimized.
This comment has been minimized.
It's about presence of LLVM in both Rust and Emscripten when you could just use Rust directly (and LLVM versions of both currently need to be kept compatible when you use Rust's -emscripten- targets). Also, Emscripten evolves much slower and harder to contribute to in my experience, so when you need to implement something Rust-specific for the WASM/JS output, it might take much longer to try and implement it on Emscripten side than if we had everything done only on Rust side. |
This comment has been minimized.
This comment has been minimized.
cretz
commented
Nov 21, 2017
•
|
I'll drop my two cents here as an author of a non-web WASM backend: Emscripten and the idea that JS emul needs to be Rust's concern is off. The WASM community needs to get together and create a libc-esque set of abstractions that backends can support (like emscripten or mine). In the meantime, I'd really like to not see low-level impls for a specific backend (JS/Web) be part of the Rust lang. That the shim exists already is enough. If you want JS support, do it elsewhere external to the lang. |
This comment has been minimized.
This comment has been minimized.
cretz
commented
Nov 21, 2017
•
|
@chpio - Meh, the abstraction doesn't really matter. It can just be nix syscalls like emscripten does for all I care. Just WASM import what you expect and let the backend fill em in, but of course a consistent abstraction would be nice. But the real nice thing would be if all WASM frontends could define something they share, but that seems unlikely (Emscripten basically uses libc and other libs to assume this). I just tossed my opinion in here that it should not be part of the Rust-lang repo (or even the core devs' concern) to implement JS forms of the stdlib. I haven't yet played w/ the unknown-unknown compilation target yet, but one way would be to have a separate wasm file emitted of all the abstracted functions and just have unreachable as the one and only command for all functions. Then just import that into the real wasm file...it can be supplanted by backend authors as need be. |
This comment has been minimized.
This comment has been minimized.
|
@rpjohnst Separating Either way, Rust doesn't have to know about these JS implementation details, just refer to generic kernel functions as said above, so having |
This comment has been minimized.
This comment has been minimized.
|
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 |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
There is a problem with core, no one supports it. But i like the idea of portability lints. We could even make |
This comment has been minimized.
This comment has been minimized.
@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 |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
@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 comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
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 comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
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. |
This comment has been minimized.
This comment has been minimized.
|
Perhaps an additional target or flag would be helpful- a way to get the |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
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. |
This comment has been minimized.
This comment has been minimized.
|
They can and should, along with targets to organize |
This comment has been minimized.
This comment has been minimized.
|
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). |
This comment has been minimized.
This comment has been minimized.
|
@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. |
This comment has been minimized.
This comment has been minimized.
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 |
This comment has been minimized.
This comment has been minimized.
Definitely, this belongs into crates. std shouldn't have any additional features than it provides on other platforms as well. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
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. |
tlively commentedAug 21, 2017
•
edited
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: