Skip to content

Commit 1d83f98

Browse files
authored
Rollup merge of rust-lang#79997 - coolreader18:wasm-reactor, r=alexcrichton
Emit a reactor for cdylib target on wasi Fixes rust-lang#79199, and relevant to rust-lang#73432 Implements wasi reactors, as described in WebAssembly/WASI#13 and [`design/application-abi.md`](https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md) Empty `lib.rs`, `lib.crate-type = ["cdylib"]`: ```shell $ cargo +reactor build --release --target wasm32-wasi Compiling wasm-reactor v0.1.0 (/home/coolreader18/wasm-reactor) Finished release [optimized] target(s) in 0.08s $ wasm-dis target/wasm32-wasi/release/wasm_reactor.wasm >reactor.wat ``` `reactor.wat`: ```wat (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "wasi_snapshot_preview1" "fd_prestat_get" (func $__wasi_fd_prestat_get (param i32 i32) (result i32))) (import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func $__wasi_fd_prestat_dir_name (param i32 i32 i32) (result i32))) (import "wasi_snapshot_preview1" "proc_exit" (func $__wasi_proc_exit (param i32))) (import "wasi_snapshot_preview1" "environ_sizes_get" (func $__wasi_environ_sizes_get (param i32 i32) (result i32))) (import "wasi_snapshot_preview1" "environ_get" (func $__wasi_environ_get (param i32 i32) (result i32))) (memory $0 17) (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 1048576)) (global $global$1 i32 (i32.const 1049096)) (global $global$2 i32 (i32.const 1049096)) (export "memory" (memory $0)) (export "_initialize" (func $_initialize)) (export "__data_end" (global $global$1)) (export "__heap_base" (global $global$2)) (func $__wasm_call_ctors (call $__wasilibc_initialize_environ_eagerly) (call $__wasilibc_populate_preopens) ) (func $_initialize (call $__wasm_call_ctors) ) (func $malloc (param $0 i32) (result i32) (call $dlmalloc (local.get $0) ) ) ;; lots of dlmalloc, memset/memcpy, & libpreopen code ) ``` I went with repurposing cdylib because I figured that it doesn't make much sense to have a wasi shared library that can't be initialized, and even if someone was using it adding an `_initialize` export is a very small change.
2 parents c5eae56 + 92d3537 commit 1d83f98

File tree

9 files changed

+69
-20
lines changed

9 files changed

+69
-20
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,7 @@ fn exec_linker(
12761276

12771277
fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
12781278
let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
1279+
(CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
12791280
(CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
12801281
(CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
12811282
(CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,

compiler/rustc_codegen_ssa/src/back/linker.rs

+11
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ impl<'a> Linker for GccLinker<'a> {
314314
self.cmd.arg("-static");
315315
self.build_dylib(out_filename);
316316
}
317+
LinkOutputKind::WasiReactorExe => {
318+
self.linker_arg("--entry");
319+
self.linker_arg("_initialize");
320+
}
317321
}
318322
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
319323
// it switches linking for libc and similar system libraries to static without using
@@ -662,6 +666,9 @@ impl<'a> Linker for MsvcLinker<'a> {
662666
arg.push(out_filename.with_extension("dll.lib"));
663667
self.cmd.arg(arg);
664668
}
669+
LinkOutputKind::WasiReactorExe => {
670+
panic!("can't link as reactor on non-wasi target");
671+
}
665672
}
666673
}
667674

@@ -1085,6 +1092,10 @@ impl<'a> Linker for WasmLd<'a> {
10851092
LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
10861093
self.cmd.arg("--no-entry");
10871094
}
1095+
LinkOutputKind::WasiReactorExe => {
1096+
self.cmd.arg("--entry");
1097+
self.cmd.arg("_initialize");
1098+
}
10881099
}
10891100
}
10901101

compiler/rustc_interface/src/tests.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate
77
use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
88
use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
99
use rustc_session::config::{
10-
Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion,
10+
Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel,
1111
};
1212
use rustc_session::lint::Level;
1313
use rustc_session::search_paths::SearchPath;
@@ -597,6 +597,7 @@ fn test_debugging_options_tracking_hash() {
597597
tracked!(unleash_the_miri_inside_of_you, true);
598598
tracked!(use_ctors_section, Some(true));
599599
tracked!(verify_llvm_ir, true);
600+
tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
600601
}
601602

602603
#[test]

compiler/rustc_session/src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,7 @@ crate mod dep_tracking {
21722172
SymbolManglingVersion, TrimmedDefPaths,
21732173
};
21742174
use crate::lint;
2175+
use crate::options::WasiExecModel;
21752176
use crate::utils::NativeLibKind;
21762177
use rustc_feature::UnstableFeatures;
21772178
use rustc_span::edition::Edition;
@@ -2227,6 +2228,7 @@ crate mod dep_tracking {
22272228
impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
22282229
impl_dep_tracking_hash_via_hash!(Option<CodeModel>);
22292230
impl_dep_tracking_hash_via_hash!(Option<TlsModel>);
2231+
impl_dep_tracking_hash_via_hash!(Option<WasiExecModel>);
22302232
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
22312233
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
22322234
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);

compiler/rustc_session/src/options.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ macro_rules! options {
279279
pub const parse_tls_model: &str =
280280
"one of supported TLS models (`rustc --print tls-models`)";
281281
pub const parse_target_feature: &str = parse_string;
282+
pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
282283
}
283284

284285
#[allow(dead_code)]
@@ -722,6 +723,15 @@ macro_rules! options {
722723
None => false,
723724
}
724725
}
726+
727+
fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool {
728+
match v {
729+
Some("command") => *slot = Some(WasiExecModel::Command),
730+
Some("reactor") => *slot = Some(WasiExecModel::Reactor),
731+
_ => return false,
732+
}
733+
true
734+
}
725735
}
726736
) }
727737

@@ -1166,9 +1176,17 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
11661176
"in general, enable more debug printouts (default: no)"),
11671177
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
11681178
"verify LLVM IR (default: no)"),
1179+
wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
1180+
"whether to build a wasi command or reactor"),
11691181

11701182
// This list is in alphabetical order.
11711183
//
11721184
// If you add a new option, please update:
1173-
// - src/librustc_interface/tests.rs
1185+
// - compiler/rustc_interface/src/tests.rs
1186+
}
1187+
1188+
#[derive(Clone, Hash)]
1189+
pub enum WasiExecModel {
1190+
Command,
1191+
Reactor,
11741192
}

compiler/rustc_session/src/session.rs

+8
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,14 @@ impl Session {
796796
self.opts.debugging_opts.tls_model.unwrap_or(self.target.tls_model)
797797
}
798798

799+
pub fn is_wasi_reactor(&self) -> bool {
800+
self.target.options.os == "wasi"
801+
&& matches!(
802+
self.opts.debugging_opts.wasi_exec_model,
803+
Some(config::WasiExecModel::Reactor)
804+
)
805+
}
806+
799807
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
800808
// "mcount" function relies on stack pointer.
801809
// See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.

compiler/rustc_target/src/spec/crt_objects.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
//! The `crtx` ones are generally distributed with libc and the `begin/end` ones with gcc.
66
//! See <https://dev.gentoo.org/~vapier/crt.txt> for some more details.
77
//!
8-
//! | Pre-link CRT objects | glibc | musl | bionic | mingw | wasi |
9-
//! |----------------------|------------------------|------------------------|------------------|-------------------|------|
10-
//! | dynamic-nopic-exe | crt1, crti, crtbegin | crt1, crti, crtbegin | crtbegin_dynamic | crt2, crtbegin | crt1 |
11-
//! | dynamic-pic-exe | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 |
12-
//! | static-nopic-exe | crt1, crti, crtbeginT | crt1, crti, crtbegin | crtbegin_static | crt2, crtbegin | crt1 |
13-
//! | static-pic-exe | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 |
14-
//! | dynamic-dylib | crti, crtbeginS | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - |
15-
//! | static-dylib (gcc) | crti, crtbeginT | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - |
16-
//! | static-dylib (clang) | crti, crtbeginT | N/A | crtbegin_static | dllcrt2, crtbegin | - |
8+
//! | Pre-link CRT objects | glibc | musl | bionic | mingw | wasi |
9+
//! |----------------------|------------------------|------------------------|------------------|-------------------|--------------|
10+
//! | dynamic-nopic-exe | crt1, crti, crtbegin | crt1, crti, crtbegin | crtbegin_dynamic | crt2, crtbegin | crt1 |
11+
//! | dynamic-pic-exe | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 |
12+
//! | static-nopic-exe | crt1, crti, crtbeginT | crt1, crti, crtbegin | crtbegin_static | crt2, crtbegin | crt1 |
13+
//! | static-pic-exe | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin | crt1 |
14+
//! | dynamic-dylib | crti, crtbeginS | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - |
15+
//! | static-dylib (gcc) | crti, crtbeginT | crti, crtbeginS | crtbegin_so | dllcrt2, crtbegin | - |
16+
//! | static-dylib (clang) | crti, crtbeginT | N/A | crtbegin_static | dllcrt2, crtbegin | - |
17+
//! | wasi-reactor-exe | N/A | N/A | N/A | N/A | crt1-reactor |
1718
//!
1819
//! | Post-link CRT objects | glibc | musl | bionic | mingw | wasi |
1920
//! |-----------------------|---------------|---------------|----------------|--------|------|
@@ -105,6 +106,7 @@ pub(super) fn pre_wasi_fallback() -> CrtObjects {
105106
(LinkOutputKind::DynamicPicExe, &["crt1.o"]),
106107
(LinkOutputKind::StaticNoPicExe, &["crt1.o"]),
107108
(LinkOutputKind::StaticPicExe, &["crt1.o"]),
109+
(LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]),
108110
])
109111
}
110112

compiler/rustc_target/src/spec/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ pub enum LinkOutputKind {
408408
DynamicDylib,
409409
/// Dynamic library with bundled libc ("statically linked").
410410
StaticDylib,
411+
/// WASI module with a lifetime past the _initialize entry point
412+
WasiReactorExe,
411413
}
412414

413415
impl LinkOutputKind {
@@ -419,6 +421,7 @@ impl LinkOutputKind {
419421
LinkOutputKind::StaticPicExe => "static-pic-exe",
420422
LinkOutputKind::DynamicDylib => "dynamic-dylib",
421423
LinkOutputKind::StaticDylib => "static-dylib",
424+
LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
422425
}
423426
}
424427

@@ -430,6 +433,7 @@ impl LinkOutputKind {
430433
"static-pic-exe" => LinkOutputKind::StaticPicExe,
431434
"dynamic-dylib" => LinkOutputKind::DynamicDylib,
432435
"static-dylib" => LinkOutputKind::StaticDylib,
436+
"wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
433437
_ => return None,
434438
})
435439
}
@@ -1378,7 +1382,7 @@ impl Target {
13781382
let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
13791383
format!("{}: '{}' is not a valid value for CRT object kind. \
13801384
Use '(dynamic,static)-(nopic,pic)-exe' or \
1381-
'(dynamic,static)-dylib'", name, k)
1385+
'(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k)
13821386
})?;
13831387

13841388
let v = v.as_array().ok_or_else(||

src/bootstrap/compile.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,16 @@ fn copy_self_contained_objects(
188188
}
189189
} else if target.ends_with("-wasi") {
190190
let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
191-
copy_and_stamp(
192-
builder,
193-
&libdir_self_contained,
194-
&srcdir,
195-
"crt1.o",
196-
&mut target_deps,
197-
DependencyType::TargetSelfContained,
198-
);
191+
for &obj in &["crt1.o", "crt1-reactor.o"] {
192+
copy_and_stamp(
193+
builder,
194+
&libdir_self_contained,
195+
&srcdir,
196+
obj,
197+
&mut target_deps,
198+
DependencyType::TargetSelfContained,
199+
);
200+
}
199201
} else if target.contains("windows-gnu") {
200202
for obj in ["crt2.o", "dllcrt2.o"].iter() {
201203
let src = compiler_file(builder, builder.cc(target), target, obj);

0 commit comments

Comments
 (0)