-
Notifications
You must be signed in to change notification settings - Fork 349
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
Compilation to WASM? #722
Comments
I think a first step would be to create a new codegen backend which doesn't actually do any codegen and just dumps the metadata. That way we should be able to build a rustc which doesn't depend on llvm or other C code. |
I had created one in the past but it bitrotted and it was unused, so I removed it in rust-lang/rust#58847. If you copy https://github.com/bjorn3/rustc_codegen_cranelift/blob/11d816c/src/lib.rs#L182-L190 into Another thing necessary is replacing the |
I want to do the same for https://github.com/bjorn3/rustc_codegen_cranelift/, but I want it to pass the rustc test suite first and |
Intriguing. :) I should add one warning though: Miri isn't a fast interpreter. It's really slow. So I don't think it is actually a good environment to use to run code, I see it as more useful for debugging and testing. But, don't let me stop you! I just felt I should give you a fair warning. And if ideas like this leak to people making Miri lightning fast while maintaining all the UB checking, I'll be even more happier. :D |
That's understandable, but I think it's ought to be good enough for typical playground snippets :) |
I guess that's one way, although I was wondering if Miri actually needs the main |
The codegen backend is necessary for |
Fair enough. |
I am currently trying to compile rustc for wasm (https://github.com/bjorn3/rust/tree/compile_rustc_for_wasm), but I am hitting a compiler bug: rust-lang/rust#60540. |
@bjorn3 I've rebased your branch onto master, updated deps and fixed cfg's from Eventually it compiled successfully, but then ran into the same runtime validation issue with invalid code generated by Rust. However, I recompiled in release mode and then it passed validation! That got me thinking it should work now, but running the generated file with |
@bjorn3 Oh... maybe it's just been taking so long (especially the compilation part). I've tried
|
Yes, it takes several minutes to compile it using
🎉 🎉 🎉
I tried actually compiling something, but it errors with:
I am currently trying to figure out were it errors. |
Places needing patching:
Edit: pushed bjorn3/rust@15f980f (based on @RReverser's branch). Now it errors at
Which is expected, as I had to remove the codegen backend dynamic loader. Will try to get https://github.com/bjorn3/rustc_codegen_cranelift to work with it. |
This needs a rustc compiled for wasi (see rust-lang/miri#722) It also needs bytecodealliance/target-lexicon#14
FWIW previously (before even filing this issue) I tried compiling rustc with Emscripten instead, which should, in theory, reduce number of these places to patch, as it supports a bit more than WASI does. Haven't gotten too far though, because I tried to build completely unpatched rustc and there were few things that still didn't compile and probably needed similar fixes as in your branch.
I thought the plan was to build it without any codegen, just with miri? Or do you want to build an actual full rustc? |
I want them both. :) I currently have |
Yeah for that I think you'll need to do the proper build (via |
Seems like it doesn't even reach the rustc version check for the libraries. I added |
Switching from wasmer to wasmtime fixed it. It even got to the beginning of codegen. Edit: filled wasmerio/wasmer#434. |
I am currently working on making miri compile for wasi, which this issue was actually about. |
It seems to trap while calling the
I pushed the wip stuff to my branch. |
@bjorn3 Left a comment on your MIRI commit on your branch. |
@bjorn3 But also, I'm not sure why rustc is now depending on miri... shouldn't it be the other way around? (like in non-WASI version) |
I did that to be able to prevent having to recompile every rustc crate, which is slow and to prevent having to copy all files in the dir layout rustc wants a sysroot to be. |
I'm not sure I understand what you're saying... neither should be affected by which crate you compile as an entry point. I've changed my local copy of Rust & MIRI to do just that, and got |
I meant that I had already compiled all crates in |
Opened rust-lang/rust#120348 to upstream most of the build system changes, pushed rust-lang/rustc_codegen_cranelift@7d3b293 to upstream a cg_clif change and managed to somewhat reduce the diff on the compile_rustc_for_wasm13 branch. The second commit on that branch uses the wasm32-wasi-preview1-threads target to further reduce the diff, but requires wasi-threads, which browser_wasi_shim currently doesn't support. |
rust-lang/rust#120348 has been merged. Opened rust-lang/rust#121392 to make patching away dlopen usage easier. I rebased the compile_rustc_for_wasm13 branch and removed a couple of unnecessary changes. Edit: rust-lang/rust#121392 has been merged too. Rebased. |
I took https://github.com/bjorn3/browser_wasi_shim/blob/main/examples/rustc.html and made it invoke the miri I built from the second to last commit of the compile_rustc_for_wasm13 branch instead. |
For others trying to run it, thats
|
Somehow no one pasted this here: https://garriga.dev/rubri/
cc @LyonSyonII |
New version available at the compile_rustc_for_wasm16 branch of https://github.com/bjorn3/rust. @oligamiq created a PR to use @whitequark's LLVM fork, so it should now be able to build for wasm, though I haven't tested linking yet. It also currently requires using wasm32-wasip1-threads, which doesn't work with browser_wasi_shim yet. You can still use the cg_clif backend with wasm32-wasip1 without threads instead by omitting |
FWIW, I'm happy to see this effort and will support it from my side as much as I'm able to. Let me know if you need any further adjustments LLVM-side (though I'm sorta waiting on consensus on handling pthreads shims in wasi-libc at the moment). |
The pthread shims thing (or adding wasip1-threads support to browser_wasi_shim) is the biggest blocker for getting this working in the browser. For complete end-to-end execution in the browser, lld would also need to be supported. I haven't checked if it already works though. Would need to rebuild LLVM again to check. And I did probably need to patch the rust standard library to support a custom host call for spawning processes such that rustc can actually invoke lld. |
Regarding
However, since no thread pool has been created and files are accessible from multiple workers, the speed has significantly dropped... I feel bad for Bjorn since I continued working after submitting the pull request when I made the file system accessible from multiple workers. Currently, I'm working on a different branch. ※Require SharedArrayBuffer |
I hadn't looked at your browser_wasi_shim PR yet as I assumed it to be under heavy development. Let me know when it is ready for review/ready for me to try it out. |
I've looked into that. Ideally, LLD would be built as a library and linked into the rustc binary. LLD already has a function you can call to run its main routine in-process, so you should probably use that instead of a hostcall; this has the advantage that the resulting |
Do you have any pointers on how to do that?
Be aware that rustc.wasm is pretty large at 134MB. And it needs another 72MB for the standard library compiled to wasm32-wasip1-threads. |
How familiar are you with LLVM? You're looking to call
That sounds about right. I woulde expect LLD to add ~50M more, so ~250M before compression, maybe ~100M after. In my view this is still worth it since the object can be cached indefinitely at the client. The distribution infrastructure I'm using supports such large packages just fine. Have you seen my FPGA toolchain integration with VS Code? The packages used in the demo are a ~50M download in total (from memory), which is a little high but is fine if you have broadband. ~100M of rustc isn't such a stretch, and I was planning on shipping yowasp-clang that would be of a similar size, anyway. |
Is enabling building of the lld standalone tool enough to build whatever static library I need to link against for |
I think so, since the lld executable is a really thin wrapper (which is, iirc, autogenerated) over the function I linked to. But I would personally still scour the build system to see which target it is that does it. |
So after looking into it, I think you should probably build the |
Managed to get linking using lld working: bjorn3/rust#8 |
I also use miri (and a few other solutions) here to run various programming languages in the browser: https://x0k.github.io/ppp/editor |
And you can use the YoWASP VS Code toolchain if you want a full editor in your browser when running programming language compilers. |
https://github.com/oligamiq/rubrc @bjorn3 Also, regarding the environment variable WASI_SYSROOT, it is required by cc, so it cannot be removed. Although the compilation can still proceed without it, unresolved imports such as |
wasm32-wasip2 uses wasm-component-ld, which is a wrapper around lld. It should be possible to integrate it directly into rustc, though depending on how exactly wasm-component-ld is designed, it may require patching wasm-component-ld itself. As for native targets, it is harder than conventional cross-compilation as those generally depend on gcc or clang wrapping the linker. |
LLVM's ELF, COFF, and Mach-O linker should be included as well, but is there no way to make use of them? |
You can use lld for non-wasm targets with rustc.wasm, but on Unix targets you don't normally directly invoke the linker. Instead what you invoke is gcc or clang, which in turn invoke the linker with the right arguments. Rustc doesn't (yet) support directly invoking the linker for Unix targets as it doesn't know all the arguments that are necessary to successfully link that gcc or clang would pass to the linker. |
Oh, it seems I may need to pull in Clang or contribute to the Rustc code. |
Miri maintainer note: this is a fun project, but not something we currently intend to support officially. To keep maintenance manageable, Miri only supports running on platforms that rustc supports running on.
Compiling the whole Rustc to WASM is a pretty big undertaking for many reasons.
However, Miri doesn't need an actual codegen and many other parts of the whole Rustc, so I wonder how realistic it would be to compile it and the pieces it depends on to WASM instead? Are there any obvious blockers?
Mostly opening this to gauge interest and estimate complexity, as I believe there is an interest in running Rust directly in the browser on playground-like websites.
P.S. Despite what I said in the first sentence, this was actually done for Clang a while ago - https://tbfleming.github.io/cib/ - which includes LLVM compiled to WASM that, in turn, generates more WASM dynamically during runtime. In theory, it should be possible to do the same for Rust, especially since they share LLVM, but for now having just an interpreter could already be an interesting starting goal.
The text was updated successfully, but these errors were encountered: