Overview
I would like to propose a patchset that allows LLVM to be built for WebAssembly/WASI (this includes WASIp1 and WASIp2). I am interested in this functionality for the YoWASP project, and it will be immediately useful for the Amaranth HDL as well as Spade HDL communities, with obvious other applications for projects such as Compiler Explorer. Through the use of wasm2c, it will also bring modern LLVM/Clang to older systems that no longer fit the minimum build requirements.
Previous efforts
Over the years there have been a few efforts to ship Clang built for Wasm. The most complete ones are:
- Applied WebAssembly: Compiling and Running C++ in Your Web Browser - Ben Smith
- demo repository (2019)
- repackaged in WAPM (2019)
- forked/repackaged on NPM (2023)
- wasm-ide (2023)
- wasi-sdk self-hosted build (2023)
Porting to WASI
WASI is a platform that presents a small subset of the POSIX API. Unlike many other platforms subsetting POSIX, I would hesitate to describe it as “*nix-like” because it misses some core *nix features:
- No process management
- No asynchronous signals
- No filesystem permissions
- In some configurations, no Berkeley sockets
- No discretionary access control
In practical terms, WASI is closer to a bare metal RTOS with a POSIX-like API than to a *nix-like OS.
Goal of porting LLVM
The end result of the port I am working on will be a build of Clang and LLD that can be used to translate C++ code to WebAssembly in the browser or in a standalone Wasm engine such that the WebAssembly artifact can be executed on the same engine. This will enable applications such as C++-based simulation for the YoWASP toolchain VS Code extension.
I expect that other online development platforms like Arduino Cloud will pick up the port as well once the initial work is done, since shifting compilation to the client reduces infrastructure costs and addresses privacy concerns.
Porting strategy
I propose the following steps for porting LLVM to WASI:
- Conditionalize use of POSIX features missing in WASI. Some of these features are truly conditional, i.e. some WASI builds will include them and some will not, while other features are expected to be absent in all present day WASI builds. This wouldn’t add any
defined(__wasm__)
ordefined(__wasi__)
yet. - Conditionalize remaining platform-specific code for WASI. These changes mostly relate to signals and subprocesses, with some minor filesystem-related ones. This would only add
defined(__wasm__)
ordefined(__wasi__)
. - (Optional) Fix build without
-pthread
. While WASI does support threads, these complicate deployment, and in many environments would not be desirable. Currently LLVM does not build if STL lacksstd::mutex
, etc, even with-DLLVM_ENABLE_THREADS=OFF
, seemingly due to bitrot. - (Optional) Add
-fintegrated-lld
to the compiler driver. WASI does not have subprocesses, and while the compiler driver will work fine invoked asclang -c
since it supports integrated cc1plus, it is not able to link the binary. If not implemented, the embedder of the WASI build will have to either patch LLVM or to invoke the linker themselves, possibly by invokingclang -###
and parsing its output.
Steps (1) and (2) that touch almost exclusively LLVMSupport are enough to build a practically useful toolchain. Steps (3) and (4) on top of that are enough to build a toolchain that is similar in terms of usability to any other Clang/LLD build when combined with a suitable Wasm engine such as wasmtime.
Prototype
The YoWASP/clang
repository contains a harness based on LLVM 18.1.2 release that builds LLVM, Clang, and LLD. It can compilea and link binaries, both freestanding and those using the C library, although for some reason I can’t reuse the sysroot from wasi-sdk directly.
The main+wasm
branch of the YoWASP/llvm-project
repository contains the same patch set on top of main
and split into commits for review.
Testing
Although a buildbot providing post-commit testing is an ideal solution, this may not be practical to run for me; I already maintain an extensive amount of infrastructure in public interest, and while I would (as it will become clear) contribute maintenance effort I’m not willing to pay for a buildbot runner. I expect that the two principal ways through which this port will stay functional will be:
- YoWASP nightly builds that already cover other FPGA toolchain components like Yosys, nextpnr, and openFPGALoader, maintained by the YoWASP interest group (primarily myself);
- wasi-sdk builds, maintained by the WebAssembly interest group.
Pull requests
Changelog
- 2024-05-19T2135Z: added references to wasi-sdk discussion on shipping a self-hosted build and a section on testing
- 2024-05-20T1716Z: LLVM/Clang/LLD build is verified to be fully functional