Skip to content

Commit 03cb7de

Browse files
authored
Rollup merge of #131487 - graydon:wasm32v1-none, r=alexcrichton
Add wasm32v1-none target (compiler-team/#791) This is a preliminary implementation of the MCP discussed in [compiler-team#791](rust-lang/compiler-team#791). It's not especially "major" but you know, process! Anyway it adds a new wasm32v1-none target which just pins down a set of wasm features. I think this is close to the consensus that emerged when discussing it on Zulip so I figured I'd sketch to see how hard it is. Turns out not very.
2 parents f267500 + b0f0282 commit 03cb7de

File tree

10 files changed

+192
-8
lines changed

10 files changed

+192
-8
lines changed

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1803,6 +1803,7 @@ supported_targets! {
18031803

18041804
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
18051805
("wasm32-unknown-unknown", wasm32_unknown_unknown),
1806+
("wasm32v1-none", wasm32v1_none),
18061807
("wasm32-wasi", wasm32_wasi),
18071808
("wasm32-wasip1", wasm32_wasip1),
18081809
("wasm32-wasip2", wasm32_wasip2),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! A "bare wasm" target representing a WebAssembly output that does not import
2+
//! anything from its environment and also specifies an _upper_ bound on the set
3+
//! of WebAssembly proposals that are supported.
4+
//!
5+
//! It's equivalent to the `wasm32-unknown-unknown` target with the additional
6+
//! flags `-Ctarget-cpu=mvp` and `-Ctarget-feature=+mutable-globals`. This
7+
//! enables just the features specified in <https://www.w3.org/TR/wasm-core-1/>
8+
//!
9+
//! This is a _separate target_ because using `wasm32-unknown-unknown` with
10+
//! those target flags doesn't automatically rebuild libcore / liballoc with
11+
//! them, and in order to get those libraries rebuilt you need to use the
12+
//! nightly Rust feature `-Zbuild-std`. This target is for people who want to
13+
//! use stable Rust, and target a stable set pf WebAssembly features.
14+
15+
use crate::spec::{Cc, LinkerFlavor, Target, base};
16+
17+
pub(crate) fn target() -> Target {
18+
let mut options = base::wasm::options();
19+
options.os = "none".into();
20+
21+
// WebAssembly 1.0 shipped in 2019 and included exactly one proposal
22+
// after the initial "MVP" feature set: "mutable-globals".
23+
options.cpu = "mvp".into();
24+
options.features = "+mutable-globals".into();
25+
26+
options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::No), &[
27+
// For now this target just never has an entry symbol no matter the output
28+
// type, so unconditionally pass this.
29+
"--no-entry",
30+
]);
31+
options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &[
32+
// Make sure clang uses LLD as its linker and is configured appropriately
33+
// otherwise
34+
"--target=wasm32-unknown-unknown",
35+
"-Wl,--no-entry",
36+
]);
37+
38+
Target {
39+
llvm_target: "wasm32-unknown-unknown".into(),
40+
metadata: crate::spec::TargetMetadata {
41+
description: Some("WebAssembly".into()),
42+
tier: Some(2),
43+
host_tools: Some(false),
44+
std: Some(false),
45+
},
46+
pointer_width: 32,
47+
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
48+
arch: "wasm32".into(),
49+
options,
50+
}
51+
}

compiler/rustc_target/src/spec/tests/tests_impl.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,13 @@ impl Target {
121121
// Check dynamic linking stuff
122122
// BPF: when targeting user space vms (like rbpf), those can load dynamic libraries.
123123
// hexagon: when targeting QuRT, that OS can load dynamic libraries.
124-
if self.os == "none" && (self.arch != "bpf" && self.arch != "hexagon") {
124+
// wasm{32,64}: dynamic linking is inherent in the definition of the VM.
125+
if self.os == "none"
126+
&& (self.arch != "bpf"
127+
&& self.arch != "hexagon"
128+
&& self.arch != "wasm32"
129+
&& self.arch != "wasm64")
130+
{
125131
assert!(!self.dynamic_linking);
126132
}
127133
if self.only_cdylib

src/ci/docker/host-x86_64/dist-various-2/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ ENV TARGETS=$TARGETS,wasm32-wasi
118118
ENV TARGETS=$TARGETS,wasm32-wasip1
119119
ENV TARGETS=$TARGETS,wasm32-wasip1-threads
120120
ENV TARGETS=$TARGETS,wasm32-wasip2
121+
ENV TARGETS=$TARGETS,wasm32v1-none
121122
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
122123
ENV TARGETS=$TARGETS,x86_64-pc-solaris
123124
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32

src/doc/rustc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
8787
- [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md)
8888
- [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
89+
- [wasm32v1-none](platform-support/wasm32v1-none.md)
8990
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
9091
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
9192
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)

src/doc/rustc/src/platform-support.md

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ target | std | notes
195195
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
196196
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
197197
[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
198+
[`wasm32v1-none`](platform-support/wasm32v1-none.md) | * | WebAssembly limited to 1.0 features and no imports
198199
[`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS
199200
[`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64
200201
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX

src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md

+17-7
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,20 @@ As of the time of this writing the proposals that are enabled by default (the
132132

133133
If you're compiling WebAssembly code for an engine that does not support a
134134
feature in LLVM's default feature set then the feature must be disabled at
135-
compile time. Note, though, that enabled features may be used in the standard
136-
library or precompiled libraries shipped via rustup. This means that not only
137-
does your own code need to be compiled with the correct set of flags but the
138-
Rust standard library additionally must be recompiled.
135+
compile time. There are two approaches to choose from:
136+
137+
- If you are targeting a feature set no smaller than the W3C WebAssembly Core
138+
1.0 recommendation -- which is equivalent to the WebAssembly MVP plus the
139+
`mutable-globals` feature -- and you are building `no_std`, then you can
140+
simply use the [`wasm32v1-none` target](./wasm32v1-none.md) instead of
141+
`wasm32-unknown-unknown`, which uses only those minimal features and
142+
includes a core and alloc library built with only those minimal features.
143+
144+
- Otherwise -- if you need std, or if you need to target the ultra-minimal
145+
"MVP" feature set, excluding `mutable-globals` -- you will need to manually
146+
specify `-Ctarget-cpu=mvp` and also rebuild the stdlib using that target to
147+
ensure no features are used in the stdlib. This in turn requires use of a
148+
nightly compiler.
139149

140150
Compiling all code for the initial release of WebAssembly looks like:
141151

@@ -150,9 +160,9 @@ then used to recompile the standard library in addition to your own code. This
150160
will produce a binary that uses only the original WebAssembly features by
151161
default and no proposals since its inception.
152162

153-
To enable individual features it can be done with `-Ctarget-feature=+foo`.
154-
Available features for Rust code itself are documented in the [reference] and
155-
can also be found through:
163+
To enable individual features on either this target or `wasm32v1-none`, pass
164+
arguments of the form `-Ctarget-feature=+foo`. Available features for Rust code
165+
itself are documented in the [reference] and can also be found through:
156166

157167
```sh
158168
$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# `wasm32v1-none`
2+
3+
**Tier: 2**
4+
5+
The `wasm32v1-none` target is a WebAssembly compilation target that:
6+
7+
- Imports nothing from its host environment
8+
- Enables no proposals / features past the [W3C WebAssembly Core 1.0 spec]
9+
10+
[W3C WebAssembly Core 1.0 spec]: https://www.w3.org/TR/wasm-core-1/
11+
12+
The target is very similar to [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) and similarly uses LLVM's `wasm32-unknown-unknown` backend target. It contains only three minor differences:
13+
14+
* Setting the `target-cpu` to `mvp` rather than the default `generic`. Requesting `mvp` disables _all_ WebAssembly proposals / LLVM target feature flags.
15+
* Enabling the [Import/Export of Mutable Globals] proposal (i.e. the `+mutable-globals` LLVM target feature flag)
16+
* Not compiling the `std` library at all, rather than compiling it with stubs.
17+
18+
[Import/Export of Mutable Globals]: https://github.com/WebAssembly/mutable-global
19+
20+
## Target maintainers
21+
22+
- Alex Crichton, https://github.com/alexcrichton
23+
- Graydon Hoare, https://github.com/graydon
24+
25+
## Requirements
26+
27+
This target is cross-compiled. It does not support `std`, only `core` and `alloc`. Since it imports nothing from its environment, any `std` parts that use OS facilities would be stubbed out with functions-that-fail anyways, and the experience of working with the stub `std` in the `wasm32-unknown-unknown` target was deemed not something worth repeating here.
28+
29+
Everything else about this target's requirements, building, usage and testing is the same as what's described in the [`wasm32-unknown-unknown` document](./wasm32-unknown-unknown.md), just using the target string `wasm32v1-none` in place of `wasm32-unknown-unknown`.
30+
31+
## Conditionally compiling code
32+
33+
It's recommended to conditionally compile code for this target with:
34+
35+
```text
36+
#[cfg(all(target_family = "wasm", target_os = "none"))]
37+
```
38+
39+
Note that there is no way to tell via `#[cfg]` whether code will be running on
40+
the web or not.
41+
42+
## Enabled WebAssembly features
43+
44+
As noted above, _no WebAssembly proposals past 1.0_ are enabled on this target by default. Indeed, the entire point of this target is to have a way to compile for a stable "no post-1.0 proposals" subset of WebAssembly _on stable Rust_.
45+
46+
The [W3C WebAssembly Core 1.0 spec] was adopted as a W3C recommendation in December 2019, and includes exactly one "post-MVP" proposal: the [Import/Export of Mutable Globals] proposal.
47+
48+
All subsequent proposals are _disabled_ on this target by default, though they can be individually enabled by passing LLVM target-feature flags.
49+
50+
For reference sake, the set of proposals that LLVM supports at the time of writing, that this target _does not enable by default_, are listed here along with their LLVM target-feature flags:
51+
52+
* Post-1.0 proposals (integrated into the WebAssembly core 2.0 spec):
53+
* [Bulk memory] - `+bulk-memory`
54+
* [Sign-extending operations] - `+sign-ext`
55+
* [Non-trapping fp-to-int operations] - `+nontrapping-fptoint`
56+
* [Multi-value] - `+multivalue`
57+
* [Reference Types] - `+reference-types`
58+
* [Fixed-width SIMD] - `+simd128`
59+
* Post-2.0 proposals:
60+
* [Threads] (supported by atomics) - `+atomics`
61+
* [Exception handling] - `+exception-handling`
62+
* [Extended Constant Expressions] - `+extended-const`
63+
* [Half Precision] - `+half-precision`
64+
* [Multiple memories]- `+multimemory`
65+
* [Relaxed SIMD] - `+relaxed-simd`
66+
* [Tail call] - `+tail-call`
67+
68+
[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
69+
[Sign-extending operations]: https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
70+
[Non-trapping fp-to-int operations]: https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
71+
[Multi-value]: https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
72+
[Reference Types]: https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
73+
[Fixed-width SIMD]: https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
74+
[Threads]: https://github.com/webassembly/threads
75+
[Exception handling]: https://github.com/WebAssembly/exception-handling
76+
[Extended Constant Expressions]: https://github.com/WebAssembly/extended-const
77+
[Half Precision]: https://github.com/WebAssembly/half-precision
78+
[Multiple memories]: https://github.com/WebAssembly/multi-memory
79+
[Relaxed SIMD]: https://github.com/WebAssembly/relaxed-simd
80+
[Tail call]: https://github.com/WebAssembly/tail-call
81+
82+
Additional proposals in the future are, of course, also not enabled by default.
83+
84+
## Rationale relative to wasm32-unknown-unknown
85+
86+
As noted in the [`wasm32-unknown-unknown` document](./wasm32-unknown-unknown.md), it is possible to compile with `--target wasm32-unknown-unknown` and disable all WebAssembly proposals "by hand", by passing `-Ctarget-cpu=mvp`. Furthermore one can enable proposals one by one by passing LLVM target feature flags, such as `-Ctarget-feature=+mutable-globals`.
87+
88+
Is it therefore reasonable to wonder what the difference is between building with this:
89+
90+
```sh
91+
$ rustc --target wasm32-unknown-unknown -Ctarget-cpu=mvp -Ctarget-feature=+mutable-globals
92+
```
93+
94+
and building with this:
95+
96+
```sh
97+
$ rustc --target wasm32v1-none
98+
```
99+
100+
The difference is in how the `core` and `alloc` crates are compiled for distribution with the toolchain, and whether it works on _stable_ Rust toolchains or requires _nightly_ ones. Again referring back to the [`wasm32-unknown-unknown` document](./wasm32-unknown-unknown.md), note that to disable all post-MVP proposals on that target one _actually_ has to compile with this:
101+
102+
```sh
103+
$ export RUSTFLAGS="-Ctarget-cpu=mvp -Ctarget-feature=+mutable-globals"
104+
$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
105+
```
106+
107+
Which not only rebuilds `std`, `core` and `alloc` (which is somewhat costly and annoying) but more importantly requires the use of nightly Rust toolchains (for the `-Zbuild-std` flag). This is very undesirable for the target audience, which consists of people targeting WebAssembly implementations that prioritize stability, simplicity and/or security over feature support.
108+
109+
This `wasm32v1-none` target exists as an alternative option that works on stable Rust toolchains, without rebuilding the stdlib.

src/tools/build-manifest/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ static TARGETS: &[&str] = &[
161161
"wasm32-wasip1",
162162
"wasm32-wasip1-threads",
163163
"wasm32-wasip2",
164+
"wasm32v1-none",
164165
"x86_64-apple-darwin",
165166
"x86_64-apple-ios",
166167
"x86_64-apple-ios-macabi",

tests/assembly/targets/targets-elf.rs

+3
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@
522522
//@ revisions: wasm32_unknown_unknown
523523
//@ [wasm32_unknown_unknown] compile-flags: --target wasm32-unknown-unknown
524524
//@ [wasm32_unknown_unknown] needs-llvm-components: webassembly
525+
//@ revisions: wasm32v1_none
526+
//@ [wasm32v1_none] compile-flags: --target wasm32v1-none
527+
//@ [wasm32v1_none] needs-llvm-components: webassembly
525528
//@ revisions: wasm32_wasi
526529
//@ [wasm32_wasi] compile-flags: --target wasm32-wasi
527530
//@ [wasm32_wasi] needs-llvm-components: webassembly

0 commit comments

Comments
 (0)