Skip to content

Commit

Permalink
Merge branch 'main' of github.com:bytecodealliance/wasmtime into wasm…
Browse files Browse the repository at this point in the history
…fx-merge
  • Loading branch information
dhil committed Jan 7, 2025
2 parents 7cec864 + 5030709 commit 3df4006
Show file tree
Hide file tree
Showing 19 changed files with 270 additions and 111 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ jobs:
# Build and test the C API with example C programs along with the example
# Rust programs. Note that this only executes if the `determine` step told
# us to test the capi which is off-by-default for PRs.
- run: rustup target add wasm32-wasip2 # wasip2 target needed by example programs
- run: cmake -Sexamples -Bexamples/build -DBUILD_SHARED_LIBS=OFF
- run: cmake --build examples/build --config Debug
- run: cmake -E env CTEST_OUTPUT_ON_FAILURE=1 cmake --build examples/build --config Debug --target RUN_TESTS
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ members = [
"crates/wasi-preview1-component-adapter",
"crates/wasi-preview1-component-adapter/verify",
"examples/fib-debug/wasm",
"examples/wasi/wasm",
"examples/wasm",
"examples/tokio/wasm",
"examples/component/wasm",
"examples/min-platform",
Expand Down
4 changes: 4 additions & 0 deletions crates/jit-debug/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ rust-version.workspace = true
[lints]
workspace = true

[build-dependencies]
cc = { workspace = true }
wasmtime-versioned-export-macros = { workspace = true }

[dependencies]
object = { workspace = true, optional = true }
wasmtime-versioned-export-macros = { workspace = true }
Expand Down
17 changes: 17 additions & 0 deletions crates/jit-debug/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use wasmtime_versioned_export_macros::versioned_suffix;

fn main() {
if !cfg!(feature = "gdb_jit_int") {
return;
}

let mut build = cc::Build::new();
build.warnings(true);
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
build.define(&format!("CFG_TARGET_OS_{os}"), None);
build.define("VERSIONED_SUFFIX", Some(versioned_suffix!()));

println!("cargo:rerun-if-changed=gdbjit.c");
build.file("gdbjit.c");
build.compile("gdbjit-helpers");
}
46 changes: 46 additions & 0 deletions crates/jit-debug/gdbjit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <stdint.h>
#include <stdlib.h>

#define CONCAT2(a, b) a##b
#define CONCAT(a, b) CONCAT2(a, b)
#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX)

#ifdef CFG_TARGET_OS_windows
// export required for external access.
__declspec(dllexport)
#else
// Note the `weak` linkage here, though, which is intended to let other code
// override this symbol if it's defined elsewhere, since this definition doesn't
// matter.
// Just in case cross-language LTO is enabled we set the `noinline` attribute
// and also try to have some sort of side effect in this function with a dummy
// `asm` statement.
__attribute__((weak, noinline))
#endif
void __jit_debug_register_code() {
#ifndef CFG_TARGET_OS_windows
__asm__("");
#endif
}

struct JITDescriptor {
uint32_t version_;
uint32_t action_flag_;
void *relevant_entry_;
void *first_entry_;
};

#ifdef CFG_TARGET_OS_windows
// export required for external access.
__declspec(dllexport)
#else
// Note the `weak` linkage here which is the same purpose as above. We want to
// let other runtimes be able to override this since our own definition isn't
// important.
__attribute__((weak))
#endif
struct JITDescriptor __jit_debug_descriptor = {1, 0, NULL, NULL};

struct JITDescriptor *VERSIONED_SYMBOL(wasmtime_jit_debug_descriptor)() {
return &__jit_debug_descriptor;
}
4 changes: 4 additions & 0 deletions crates/wasmtime/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ impl Engine {
// handlers, etc.
#[cfg(all(feature = "signals-based-traps", not(miri)))]
crate::runtime::vm::init_traps(config.macos_use_mach_ports);
if !cfg!(miri) {
#[cfg(feature = "debug-builtins")]
crate::runtime::vm::debug_builtins::init();
}
}

#[cfg(any(feature = "cranelift", feature = "winch"))]
Expand Down
15 changes: 15 additions & 0 deletions crates/wasmtime/src/runtime/vm/debug_builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,18 @@ pub unsafe extern "C" fn set_vmctx_memory(vmctx_ptr: *mut VMContext) {
// TODO multi-memory
VMCTX_AND_MEMORY = (vmctx_ptr, 0);
}

/// A bit of a hack around various linkage things. The goal here is to force the
/// `wasmtime_*` symbols defined in `helpers.c` to actually get exported. That
/// means they need to be referenced for the linker to include them which is
/// what this function does with trickery in C.
pub fn init() {
extern "C" {
#[wasmtime_versioned_export_macros::versioned_link]
fn wasmtime_debug_builtins_init();
}

unsafe {
wasmtime_debug_builtins_init();
}
}
44 changes: 4 additions & 40 deletions crates/wasmtime/src/runtime/vm/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,54 +96,18 @@ void VERSIONED_SYMBOL(set_vmctx_memory)(void *);
DEBUG_BUILTIN_EXPORT void VERSIONED_SYMBOL(wasmtime_set_vmctx_memory)(void *p) {
VERSIONED_SYMBOL(set_vmctx_memory)(p);
}
#endif // FEATURE_DEBUG_BUILTINS

#ifdef CFG_TARGET_OS_windows
// export required for external access.
__declspec(dllexport)
#else
// Note the `weak` linkage here, though, which is intended to let other code
// override this symbol if it's defined elsewhere, since this definition doesn't
// matter.
// Just in case cross-language LTO is enabled we set the `noinline` attribute
// and also try to have some sort of side effect in this function with a dummy
// `asm` statement.
__attribute__((weak, noinline))
#endif
void __jit_debug_register_code() {
// Helper symbol called from Rust to force the above two functions to not get
// stripped by the linker.
void VERSIONED_SYMBOL(wasmtime_debug_builtins_init)() {
#ifndef CFG_TARGET_OS_windows
__asm__("");
#ifdef FEATURE_DEBUG_BUILTINS
// Make sure these symbols do not get stripped by the compiler or linker.
void *volatile p;
p = (void *)&VERSIONED_SYMBOL(wasmtime_resolve_vmctx_memory_ptr);
p = (void *)&VERSIONED_SYMBOL(wasmtime_set_vmctx_memory);
(void)p;
#endif // FEATURE_DEBUG_BUILTINS
#endif
}

struct JITDescriptor {
uint32_t version_;
uint32_t action_flag_;
void *relevant_entry_;
void *first_entry_;
};

#ifdef CFG_TARGET_OS_windows
// export required for external access.
__declspec(dllexport)
#else
// Note the `weak` linkage here which is the same purpose as above. We want to
// let other runtimes be able to override this since our own definition isn't
// important.
__attribute__((weak))
#endif
struct JITDescriptor __jit_debug_descriptor = {1, 0, NULL, NULL};

struct JITDescriptor *VERSIONED_SYMBOL(wasmtime_jit_debug_descriptor)() {
return &__jit_debug_descriptor;
}
#endif // FEATURE_DEBUG_BUILTINS

// For more information about this see `unix/unwind.rs` and the
// `using_libunwind` function. The basic idea is that weak symbols aren't stable
Expand Down
2 changes: 1 addition & 1 deletion docs/examples-c-wasi.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This example shows off how to instantiate a wasm module using WASI imports.
## Wasm Source code

```rust,ignore
{{#include ../examples/wasi/wasm/wasi.rs}}
{{#include ../examples/wasm/wasi.rs}}
```


Expand Down
90 changes: 25 additions & 65 deletions docs/examples-rust-wasi.md
Original file line number Diff line number Diff line change
@@ -1,101 +1,61 @@
# WASI
# WASIp2

You can also [browse this source code online][code] and clone the wasmtime
repository to run the example locally.

[code]: https://github.com/bytecodealliance/wasmtime/blob/main/examples/wasi/main.rs

This example shows how to use the [`wasi-common`] crate to define WASI
This example shows how to use the [`wasmtime-wasi`] crate to define WASI
functions within a [`Linker`] which can then be used to instantiate a
WebAssembly module.
WebAssembly component.

[`wasi-common`]: https://crates.io/crates/wasi-common
[`wasmtime-wasi`]: https://crates.io/crates/wasmtime-wasi
[`Linker`]: https://docs.rs/wasmtime/*/wasmtime/struct.Linker.html

### WebAssembly module source code
## WebAssembly Component Source Code

For this WASI example, this Hello World program is compiled to a WebAssembly module using the WASI Preview 1 API.
For this WASI example, this Hello World program is compiled to a WebAssembly component using the WASIp2 API.

`wasi.rs`
```rust
{{#include ../examples/wasi/wasm/wasi.rs}}
{{#include ../examples/wasm/wasi.rs}}
```

Building this program generates `target/wasm32-wasip1/debug/wasi.wasm`, used below.
> Building instructions:
> 1. Have Rust installed
> 2. Add WASIp2 target if you haven't already: `rustup target add wasm32-wasip2`
> 3. `cargo build --target wasm32-wasip2`
### Invoke the WASM module
Building this program generates `target/wasm32-wasip2/debug/wasi.wasm`, used below.

This example shows adding and configuring the WASI imports to invoke the above WASM module.
### Invoke the WASM component

This example shows adding and configuring the WASI imports to invoke the above WASM component.

`main.rs`
```rust,ignore
{{#include ../examples/wasi/main.rs}}
```

## WASI state with other custom host state

The [`add_to_linker`] takes a second argument which is a closure to access `&mut
WasiCtx` from within the `T` stored in the `Store<T>` itself. In the above
example this is trivial because the `T` in `Store<T>` is `WasiCtx` itself, but
you can also store other state in `Store` like so:

[`add_to_linker`]: https://docs.rs/wasi-common/*/wasi_common/sync/fn.add_to_linker.html
[`Store`]: https://docs.rs/wasmtime/*/wasmtime/struct.Store.html
[`BorrowMut<WasiCtx>`]: https://doc.rust-lang.org/stable/std/borrow/trait.BorrowMut.html
[`WasiCtx`]: https://docs.rs/wasi-common/*/wasi_common/struct.WasiCtx.html

```rust
# extern crate wasmtime;
# extern crate wasi_common;
# extern crate anyhow;
use anyhow::Result;
use std::borrow::{Borrow, BorrowMut};
use wasmtime::*;
use wasi_common::{WasiCtx, sync::WasiCtxBuilder};

struct MyState {
message: String,
wasi: WasiCtx,
}

fn main() -> Result<()> {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
wasi_common::sync::add_to_linker(&mut linker, |state: &mut MyState| &mut state.wasi)?;

let wasi = WasiCtxBuilder::new()
.inherit_stdio()
.inherit_args()?
.build();
let mut store = Store::new(&engine, MyState {
message: format!("hello!"),
wasi,
});

// ...

# let _linker: Linker<MyState> = linker;
Ok(())
}
```

## WASI Preview 2

An experimental implementation of the WASI Preview 2 API is also available, along with an adapter layer for WASI Preview 1 WebAssembly modules. In future this `preview2` API will become the default. There are some features which are currently only accessible through the `preview2` API such as async support and overriding the clock and random implementations.

### Async example

This [async example code][code2] shows how to use the [wasmtime-wasi::preview2][`preview2`] module to
execute the same WASI Preview 1 WebAssembly module from the example above. This example requires the `wasmtime` crate `async` feature to be enabled.
This [async example code][code2] shows how to use the [wasmtime-wasi][`wasmtime-wasi`] crate to
execute the same WASIp2 component from the example above. This example requires the `wasmtime` crate `async` feature to be enabled.

This does not require any change to the WebAssembly module, it's just the WASI API host functions which are implemented to be async. See [wasmtime async support](https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.async_support).
This does not require any change to the WASIp2 component, it's just the WASIp2 API host functions which are implemented to be async. See [wasmtime async support](https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.async_support).

[code2]: https://github.com/bytecodealliance/wasmtime/blob/main/examples/wasi-async/main.rs
[`preview2`]: https://docs.rs/wasmtime-wasi/*/wasmtime_wasi/preview2/index.html
[`wasmtime-wasi`]: https://docs.rs/wasmtime-wasi/*/wasmtime_wasi/preview2/index.html

```rust,ignore
{{#include ../examples/wasi-async/main.rs}}
```

You can also [browse this source code online][code2] and clone the wasmtime
repository to run the example locally.

## Beyond Basics

Please see these references:
* The [book](https://component-model.bytecodealliance.org) for understanding the component model of WASIp2.
* [Bindgen Examples](https://docs.rs/wasmtime/latest/wasmtime/component/bindgen_examples/index.html) for implementing WASIp2 hosts and guests.
6 changes: 4 additions & 2 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ create_target(multi multi.c)
create_target(multimemory multimemory.c)
create_target(serialize serialize.c)
create_target(threads threads.c)
create_target(wasi wasi/main.c)
create_target(wasip1 wasip1/main.c)

# Add rust tests
create_rust_test(anyref)
create_rust_wasm(fib-debug wasm32-unknown-unknown)
create_rust_wasm(tokio wasm32-wasip1)
create_rust_wasm(wasi wasm32-wasip1)
create_rust_wasm(wasi wasm32-wasip2)
create_rust_wasm(component wasm32-unknown-unknown)
create_rust_test(epochs)
create_rust_test(externref)
Expand All @@ -80,6 +81,7 @@ create_rust_test(multi)
create_rust_test(multimemory)
create_rust_test(serialize)
create_rust_test(threads)
create_rust_test(wasi)
create_rust_test(wasip1)
create_rust_test(wasip2)
create_rust_test(tokio wasi-common/tokio)
create_rust_test(component)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/*
You can execute this example with:
cmake examples/
cargo run --example wasi-async
cargo run --example wasip1-async
*/

use anyhow::Result;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/wasi/main.rs → examples/wasip1/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/*
You can execute this example with:
cmake examples/
cargo run --example wasi
cargo run --example wasip1
*/

use wasi_common::sync::WasiCtxBuilder;
Expand Down
Loading

0 comments on commit 3df4006

Please sign in to comment.