-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
std: Add a new wasm32-unknown-unknown target #45905
Conversation
I'd also like to doubly and triply emphasize how this target is a work in progress. The precise semantics of how it works and how everything gets hooked up will likely change over time, but I feel that it's also beneficial if we can get more testing of this backend and more testing of the integration, and hopefully start seeing some neat projects leveraging these benefits! |
df2c76e
to
7552aa5
Compare
@alexcrichton I just want to say how exciting it is to see so much progress toward making wasm work well with Rust :) Thanks for doing all of this! |
Let's pick a reviewer... r? @eddyb |
@alexcrichton you've some tidy failures:
|
LGTM but this is a pretty large change. cc @rust-lang/compiler @rust-lang/libs |
@@ -39,8 38,7 @@ unsafe impl<'a> Alloc for &'a A { | |||
static GLOBAL: A = A; | |||
|
|||
fn main() { | |||
env::set_var("FOO", "bar"); | |||
drop(env::var("FOO")); | |||
println!("hello!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stray print?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah this is just intended to force an allocation somewhere that LLVM can't optimize away
src/libpanic_unwind/wasm32.rs
Outdated
//! | ||
//! Right now we don't support this, so this is just stubs | ||
|
||
#![allow(private_no_mangle_fns)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it really needed here?
Out of curiosity, how does this work? Is there an allocator runtime? |
This is great!
If I simply clone this branch, run
Edit: I managed to build successfully using LLVM 5, using the |
.gitmodules
Outdated
url = https://github.com/alexcrichton/dlmalloc-rs | ||
[submodule "src/binaryen"] | ||
path = src/binaryen | ||
url = https://github.com/WebAssembly/binaryen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a small inconsistency here: All the other crates use https://github.com/owner/repo.git
instead of https://github.com/owner/repo
7552aa5
to
dde8f95
Compare
@SimonSapin indeed there is! Wasm actually has memory allocation instructions which the allocator runtime leverages to implement a runtime allocator. |
dde8f95
to
f483780
Compare
@jasondavies oops sorry! Was pinned to the wrong commit of dlmalloc-rs, I believe it should work now. |
f41e64f
to
f483780
Compare
Does https://github.com/WebAssembly/lld/tree/wasm have to be merged upstream before you can just use the WebAssembly port of LLD? |
New tidy errors:
|
f483780
to
9bdb989
Compare
@ElvishJerricco "just use the WebAssembly port of LLD" is actually quite involved, so I wanted to get something working (aka this PR) before starting on a new venture to discover even more integration and/or LLD bugs. This is the final state, though, to use LLD to link WebAsembly (AFAIK) |
FYI: If someone wants to play with this branch and WASM in Node, I've pushed some of my experiments to this repo: https://github.com/killercup/wasm-experiments |
☔ The latest upstream changes (presumably #45870) made this pull request unmergeable. Please resolve the merge conflicts. |
9bdb989
to
3a89d09
Compare
Yeah, Wasm (as x86) is just an ISA. fs and stuff like that is just a different level of abstraction. For me wasm32-unknown-unknown seems more like a bare metal environment (like Arm MCU). “apps” for mcus doesnt require (and usually doesnt have a notion of) fs and networking. So is wasm Also, as I mentioned before, you can use Rust with |
Please, again, I'm not trying to diminish the importance of this addition, no need to try and prove to me how awesome it is 😄 I'm just saying that applicability will be pretty limited until most of standard library gets bindings to JS side. |
Let's work together and provide the missing pieces then (either as JavaScript shims or Rust-side implementations of functionality). I don't know how easy it will be to extract this stuff from Emscripten. Anyway, this is not the place to discuss it. |
It seemed like the best place (as it's related to the context of PR), but if you have other suggestions, sure. |
My point is that many things from the standart library shouldn't get any bindings to host environment. For example, what means to spawn a process in wasm? What character should be used as a path seperator? How
I didn't even think of that! |
Well other environments might provide own implementations of these system bindings if they need to. |
A better place would be #44006 . It is a bit underused sadly :/ |
@alexcrichton Now, the linker has some support for wasm: https://reviews.llvm.org/rL318539 |
Thank you @est31 ! I've moved discussion there |
@alexcrichton You mention LLVM 5. Where is your branch and how do I use it? I'm playing with the wasm target but get a segfault during compilation. Before I dig deeper I'd like to try a more recent LLVM as it might be fixed already. |
@RReverser the option of not having the extra libraries and runtimes bolted on enables use of this for embedded systems where including additional support code is unnecessary or even undesirable. Ensuring that remains an option would be an important consideration for at least these scenarios. |
@Dessix One absolutely doesn't contradict another, you can always just not include runtime and not use anything that requires it. But anyway, this discussion was moved to another issue, please see above. |
I've now also opened a PR to start running tests on CI over at #46291 |
Since this is basically the same as #37133, I wouldn't have expected this to get merged in this state in light of the comments there and in https://internals.rust-lang.org/t/refactoring-std-for-ultimate-portability/4301. Will you reconsider #37133 for merging if I rebase that? |
@jethrogb it's definitely worth revisiting, yes. Note that the wasm target is a somewhat special case, since it exists at the liballoc level and will eventually include some of the libstd layer as well (e.g. threads). It's also a specific (highly desired) platform, so the motivation was pretty different. For #37133, is the motivation primarily to have a kind of "template" for tackling other, similar cases? re: the PAL, AFAIK not much has happened there, and I think the whole story should be rebooted. In particular, we should take into account (and implement...) the portability lint, which in the long term may allow us to do away with the core/std layering altogether. In any case, before rebasing, I'd suggest at least an internals thread laying out the motivation and attempting to reach some consensus there. You could ping me, @alexcrichton and @sfackler on the thread to ensure visibility. |
pub fn cosh(n: f64) -> f64; | ||
#[link_name = "Math_expm1"] | ||
pub fn expm1(n: f64) -> f64; | ||
pub fn fdim(a: f64, b: f64) -> f64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you forgot to add a #[link_name = "Math_fdim"]
attribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately Math.fdim
isn't actually a function, and hopefully none of these will be necessary in the future regardless, it's mostly a bug that they're all here in the first place.
This commit adds a new target to the compiler: wasm32-unknown-unknown. This target is a reimagining of what it looks like to generate WebAssembly code from Rust. Instead of using Emscripten which can bring with it a weighty runtime this instead is a target which uses only the LLVM backend for WebAssembly and a "custom linker" for now which will hopefully one day be direct calls to lld.
Notable features of this target include:
HashMap
,Vec
, etc).#[no_std]
crate should be 100% compatible with this new target.This target is currently somewhat janky due to how linking works. The "linking" is currently unconditional whole program LTO (aka LLVM is being used as a linker). Naturally that means compiling programs is pretty slow! Eventually though this target should have a linker.
This target is also intended to be quite experimental. I'm hoping that this can act as a catalyst for further experimentation in Rust with WebAssembly. Breaking changes are very likely to land to this target, so it's not recommended to rely on it in any critical capacity yet. We'll let you know when it's "production ready".
Building yourself
First you'll need to configure the build of LLVM and enable this target
Next you'll want to remove any previously compiled LLVM as it needs to be rebuilt with WebAssembly support. You can do that with:
And then you're good to go! A
./x.py build
should give you a rustc with the appropriate libstd target.Test support
Currently testing-wise this target is looking pretty good but isn't complete. I've got almost the entire
run-pass
test suite working with this target (lots of tests ignored, but many passing as well). Thecore
test suite is still getting LLVM bugs fixed to get that working and will take some time. Relatively simple programs all seem to work though!In general I've only tested this with a local fork that makes use of LLVM 5 rather than our current LLVM 4 on master. The LLVM 4 WebAssembly backend AFAIK isn't broken per se but is likely missing bug fixes available on LLVM 5. I'm hoping though that we can decouple the LLVM 5 upgrade and adding this wasm target!
But the modules generated are huge!
It's worth nothing that you may not immediately see the "smallest possible wasm module" for the input you feed to rustc. For various reasons it's very difficult to get rid of the final "bloat" in vanilla rustc (again, a real linker should fix all this). For now what you'll have to do is:
And then
bar.wasm
should be the smallest we can get it!In any case for now I'd love feedback on this, particularly on the various integration points if you've got better ideas of how to approach them!