Skip to content
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

Implemented compatibility mode with wasm32-wasi #3324

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .cargo/config
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
# that.
[target.wasm32-unknown-unknown]
runner = 'cargo run -p wasm-bindgen-cli --bin wasm-bindgen-test-runner --'

[target.wasm32-wasi]
runner = 'cargo run -p wasm-bindgen-cli --bin wasm-bindgen-test-runner --'
34 changes: 34 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,40 @@ jobs:
WASM_BINDGEN_EXTERNREF: 1
NODE_ARGS: --experimental-wasm-reftypes

test_wasi_abi:
name: "Run wasm-bindgen crate tests with --wasi-abi (unix)"
runs-on: ubuntu-latest
env:
WASM_BINDGEN_SPLIT_LINKED_MODULES: 1
TEST_WASI_ABI: 1
steps:
- uses: actions/checkout@v3
- run: rustup update --no-self-update stable && rustup default stable
- run: rustup target add wasm32-wasi
- uses: actions/setup-node@v3
with:
node-version: '16'
- uses: ./.github/actions/setup-geckodriver
- run: cargo test --target wasm32-wasi
- run: cargo test --target wasm32-wasi --features serde-serialize
- run: cargo test --target wasm32-wasi --features enable-interning
- run: cargo test --target wasm32-wasi -p no-std
- run: cargo test --target wasm32-wasi -p wasm-bindgen-futures
- run: cargo test --target wasm32-wasi --test wasm
env:
WASM_BINDGEN_WEAKREF: 1
- run: cargo test --target wasm32-wasi --test wasm
env:
WASM_BINDGEN_WEAKREF: 1
WASM_BINDGEN_NO_DEBUG: 1
- run: cargo test --target wasm32-wasi --test wasm --features serde-serialize
env:
WASM_BINDGEN_WEAKREF: 1
- run: cargo test --target wasm32-wasi
env:
WASM_BINDGEN_EXTERNREF: 1
NODE_ARGS: --experimental-wasm-reftypes

test_threads:
name: "Run wasm-bindgen crate tests with multithreading enabled"
runs-on: ubuntu-latest
Expand Down
76 changes: 69 additions & 7 deletions crates/cli-support/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use crate::descriptor::{self, Descriptor, Function};

macro_rules! intrinsics {
(pub enum Intrinsic {
(pub enum $enum_name:ident {
$(
#[symbol = $sym:tt]
#[signature = fn($($arg:expr),*) -> $ret:expr]
Expand All @@ -20,16 +20,16 @@ macro_rules! intrinsics {
/// All wasm-bindgen intrinsics that could be depended on by a wasm
/// module.
#[derive(Debug)]
pub enum Intrinsic {
pub enum $enum_name {
$($name,)*
}

impl Intrinsic {
impl $enum_name {
/// Returns the corresponding intrinsic for a symbol name, if one
/// matches.
pub fn from_symbol(symbol: &str) -> Option<Intrinsic> {
pub fn from_symbol(symbol: &str) -> Option<Self> {
match symbol {
$($sym => Some(Intrinsic::$name),)*
$($sym => Some(Self::$name),)*
_ => None,
}
}
Expand All @@ -40,7 +40,7 @@ macro_rules! intrinsics {
use crate::descriptor::Descriptor::*;
match self {
$(
Intrinsic::$name => {
Self::$name => {
descriptor::Function {
shim_idx: 0,
arguments: vec![$($arg),*],
Expand All @@ -56,7 +56,7 @@ macro_rules! intrinsics {
pub fn name(&self) -> &'static str {
match self {
$(
Intrinsic::$name => $sym,
Self::$name => $sym,
)*
}
}
Expand Down Expand Up @@ -278,3 +278,65 @@ intrinsics! {
InitExternrefTable,
}
}

intrinsics! {
pub enum WasiIntrinsic {
#[symbol = "__wbindgen_wasi_clock_time_get"]
#[signature = fn(I32, I64, I32) -> I32]
ClockTimeGet,
#[symbol = "__wbindgen_wasi_fd_write"]
#[signature = fn(I32, I32, I32, I32) -> I32]
FdWrite,
#[symbol = "__wbindgen_wasi_fd_read"]
#[signature = fn(I32, I32, I32, I32) -> I32]
FdRead,
#[symbol = "__wbindgen_wasi_sched_yield"]
#[signature = fn() -> Unit]
SchedYield,
#[symbol = "__wbindgen_wasi_random_get"]
#[signature = fn(I32, I32) -> I32]
RandomGet,
#[symbol = "__wbindgen_wasi_environ_get"]
#[signature = fn(I32, I32) -> I32]
EnvironGet,
#[symbol = "__wbindgen_wasi_environ_sizes_get"]
#[signature = fn(I32, I32) -> I32]
EnvironSizesGet,
#[symbol = "__wbindgen_wasi_fd_close"]
#[signature = fn(I32) -> I32]
FdClose,
#[symbol = "__wbindgen_wasi_fd_fdstat_get"]
#[signature = fn(I32, I32) -> I32]
FdFdStatGet,
#[symbol = "__wbindgen_wasi_fd_filestat_get"]
#[signature = fn(I32, I32) -> I32]
FdFileStatGet,
#[symbol = "__wbindgen_wasi_path_filestat_get"]
#[signature = fn(I32, I32, I32, I32, I32) -> I32]
PathFileStatGet,
#[symbol = "__wbindgen_wasi_fd_fdstat_set_flags"]
#[signature = fn(I32, U16) -> I32]
FdFdStatSetFlags,
#[symbol = "__wbindgen_wasi_fd_prestat_get"]
#[signature = fn(I32, I32) -> I32]
FdPrestatGet,
#[symbol = "__wbindgen_wasi_fd_prestat_dir_name"]
#[signature = fn(I32, I32) -> I32]
FdPrestatDirName,
#[symbol = "__wbindgen_wasi_fd_seek"]
#[signature = fn(I32, I64, U8) -> I32]
FdSeek,
#[symbol = "__wbindgen_wasi_path_open"]
#[signature = fn(I32, I32, I32, I32, I32, I64, I64, I32, I32) -> I32]
PathOpen,
#[symbol = "__wbindgen_wasi_proc_exit"]
#[signature = fn(I32) -> Unit]
ProcExit,
#[symbol = "__wbindgen_wasi_args_get"]
#[signature = fn(I32, I32) -> I32]
ArgsGet,
#[symbol = "__wbindgen_wasi_args_sizes_get"]
#[signature = fn(I32, I32) -> I32]
ArgsSizesGet,
}
}
118 changes: 118 additions & 0 deletions crates/cli-support/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,124 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) ->
js.string_to_memory(*mem, *malloc, *realloc)?;
}

Instruction::PackSlice(mem) => {
js.cx.inject_stack_pointer_shim()?;

let len = js.pop();
let ptr = js.pop();

let i = js.tmp();
let mem = js.cx.expose_uint32_memory(*mem);

js.prelude(&format!(
"
const argPtr{i} = wasm.__wbindgen_add_to_stack_pointer(-16);
{mem}()[argPtr{i} / 4] = {ptr};
{mem}()[argPtr{i} / 4 + 1] = {len};
"
));

js.push(format!("argPtr{i}"));

js.finally(&format!("wasm.__wbindgen_add_to_stack_pointer(16);"));
}
Instruction::PackMutSlice(mem) => {
js.cx.inject_stack_pointer_shim()?;

let idx = js.pop();
let len = js.pop();
let ptr = js.pop();

let i = js.tmp();
let mem = js.cx.expose_uint32_memory(*mem);

js.prelude(&format!(
"
const argPtr{i} = wasm.__wbindgen_add_to_stack_pointer(-16);
{mem}()[argPtr{i} / 4] = {ptr};
{mem}()[argPtr{i} / 4 + 1] = {len};
{mem}()[argPtr{i} / 4 + 2] = {idx};
"
));

js.push(format!("argPtr{i}"));

js.finally(&format!("wasm.__wbindgen_add_to_stack_pointer(16);"));
}
Instruction::UnpackSlice(mem) => {
let mem = js.cx.expose_uint32_memory(*mem);

let arg_ptr = js.pop();
let i = js.tmp();

js.prelude(&format!(
"
var ptr{i} = {mem}()[{arg_ptr} / 4];
var len{i} = {mem}()[{arg_ptr} / 4 + 1];
"
));

js.push(format!("ptr{i}"));
js.push(format!("len{i}"));
}

Instruction::PackOption(mem, ty) => {
js.cx.inject_stack_pointer_shim()?;

let content = js.pop();
let discriminant = js.pop();

let i = js.tmp();
let mem32 = js.cx.expose_uint32_memory(*mem);

let (content_mem, content_size) = match ty {
AdapterType::I32 => (js.cx.expose_int32_memory(*mem), 4),
AdapterType::U32 => (js.cx.expose_uint32_memory(*mem), 4),
AdapterType::F32 => (js.cx.expose_f32_memory(*mem), 4),
AdapterType::I64 => (js.cx.expose_int64_memory(*mem), 8),
AdapterType::U64 => (js.cx.expose_uint64_memory(*mem), 8),
AdapterType::F64 => (js.cx.expose_f64_memory(*mem), 8),
_ => bail!("Unexpected type passed to PackOption"),
};

js.prelude(&format!(
"
const argPtr{i} = wasm.__wbindgen_add_to_stack_pointer(-16);
{mem32}()[argPtr{i} / 4] = {discriminant};
{content_mem}()[argPtr{i} / {content_size} + 1] = {content};
"
));

js.push(format!("argPtr{i}"));

js.finally(&format!("wasm.__wbindgen_add_to_stack_pointer(16);"));
}
Instruction::UnpackOption(mem, ty) => {
let mem32 = js.cx.expose_uint32_memory(*mem);
let (content_mem, content_size) = match ty {
AdapterType::I32 => (js.cx.expose_int32_memory(*mem), 4),
AdapterType::U32 => (js.cx.expose_uint32_memory(*mem), 4),
AdapterType::F32 => (js.cx.expose_f32_memory(*mem), 4),
AdapterType::I64 => (js.cx.expose_int64_memory(*mem), 8),
AdapterType::U64 => (js.cx.expose_uint64_memory(*mem), 8),
AdapterType::F64 => (js.cx.expose_f64_memory(*mem), 8),
_ => bail!("Unexpected type passed to PackOption"),
};

let arg_ptr = js.pop();
let i = js.tmp();

js.prelude(&format!(
"
var discriminant{i} = {mem32}()[{arg_ptr} / 4];
var content{i} = {content_mem}()[{arg_ptr} / {content_size} + 1];
"
));

js.push(format!("discriminant{i}"));
js.push(format!("content{i}"));
}

Instruction::Retptr { size } => {
js.cx.inject_stack_pointer_shim()?;
js.prelude(&format!(
Expand Down
7 changes: 7 additions & 0 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::path::{Path, PathBuf};
use walrus::{FunctionId, ImportId, MemoryId, Module, TableId, ValType};

mod binding;
mod wasi_intrinsics;

pub struct Context<'a> {
globals: String,
Expand Down Expand Up @@ -3147,6 +3148,12 @@ impl<'a> Context<'a> {
self.invoke_intrinsic(intrinsic, args, prelude)
}

AuxImport::WasiIntrinsic(intrinsic) => {
assert!(kind == AdapterJsImportKind::Normal);
assert!(!variadic);
self.invoke_wasi_intrinsic(intrinsic, args, prelude)
}

AuxImport::LinkTo(path, content) => {
assert!(kind == AdapterJsImportKind::Normal);
assert!(!variadic);
Expand Down
Loading