Skip to content

Commit

Permalink
Try #1313:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored Mar 31, 2020
2 parents 3639ef6 + bde319d commit 815ecac
Show file tree
Hide file tree
Showing 36 changed files with 1,454 additions and 291 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
- [#1329](https://github.com/wasmerio/wasmer/pull/1329) New numbers and strings instructions for WIT
- [#1332](https://github.com/wasmerio/wasmer/pull/1332) Add option to `CompilerConfig` to force compiler IR verification off even when `debug_assertions` are enabled. This can be used to make debug builds faster, which may be important if you're creating a library that wraps Wasmer and depend on the speed of debug builds.
- [#1320](https://github.com/wasmerio/wasmer/pull/1320) Change `custom_sections` field in `ModuleInfo` to be more standards compliant by allowing multiple custom sections with the same name. To get the old behavior with the new API, you can add `.last().unwrap()` to accesses. For example, `module_info.custom_sections["custom_section_name"].last().unwrap()`.
- [#1313](https://github.com/wasmerio/wasmer/pull/1313) Add new high-level public API through `wasmer` crate. Includes many updates including:
- Minor improvement: `imports!` macro now handles no trailing comma as well as a trailing comma in namespaces and between namespaces.
- New methods on `Module`: `exports`, `imports`, and `custom_sections`.
- New way to get exports from an instance with `let func_name: Func<i32, i64> = instance.exports.get("func_name");`.
- Improved `Table` APIs including `set` which now allows setting functions directly. TODO: update this more if `Table::get` gets made public in this PR
- TODO: finish the list of changes here
- [#1303](https://github.com/wasmerio/wasmer/pull/1303) NaN canonicalization for singlepass backend.
- [#1292](https://github.com/wasmerio/wasmer/pull/1292) Experimental Support for Android (x86_64 and AArch64)
- [#1305](https://github.com/wasmerio/wasmer/pull/1305) Handle panics from DynamicFunc.
Expand Down
19 changes: 19 additions & 0 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "wasmer"
name = "wasmer-bin"
version = "0.16.2"
authors = ["The Wasmer Engineering Team <[email protected]>"]
edition = "2018"
Expand Down Expand Up @@ -27,6 +27,7 @@ fern = { version = "0.5", features = ["colored"], optional = true }
log = "0.4"
structopt = "0.3"
wabt = { version = "0.9.1", optional = true }
wasmer = { path = "lib/api" }
wasmer-clif-backend = { path = "lib/clif-backend", optional = true }
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true }
wasmer-middleware-common = { path = "lib/middleware-common" }
Expand All @@ -44,6 +45,8 @@ wasmer-wasi-experimental-io-devices = { path = "lib/wasi-experimental-io-devices

[workspace]
members = [
"lib/api",
"lib/api-tests",
"lib/clif-backend",
"lib/singlepass-backend",
"lib/runtime",
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ test-capi: test-capi-singlepass test-capi-cranelift test-capi-llvm test-capi-ems
capi-test: test-capi

test-rest:
cargo test --release -p api-tests
cargo test --release -p wasmer-dev-utils
cargo test --release -p wasmer-interface-types
cargo test --release -p wasmer-kernel-loader
Expand Down
4 changes: 2 additions & 2 deletions examples/callback.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// This example demonstrates the use of callbacks: calling functions (Host and Wasm)
/// passed to us from the Wasm via hostcall
use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, Backend, Ctx};
use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, Backend, Ctx, Func};
use wasmer_runtime_core::{structures::TypedIndex, types::TableIndex};

static WASM: &'static str = "examples/callback-guest/callback-guest.wasm";
Expand Down Expand Up @@ -40,7 +40,7 @@ fn main() {
.instantiate(&imports)
.expect("failed to instantiate wasm module");

let entry_point = instance.func::<(u32, u32), u32>("main").unwrap();
let entry_point: Func<(u32, u32), u32> = instance.exports.get("main").unwrap();

entry_point.call(0, 0).expect("START");
}
9 changes: 6 additions & 3 deletions examples/parallel/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use rayon::prelude::*;
use wasmer_runtime::{compile_with, compiler_for_backend, func, imports, instantiate, Backend};
use wasmer_runtime::{
compile_with, compiler_for_backend, func, imports, instantiate, Backend, Func,
};
use wasmer_runtime_core::{
memory::ptr::{Array, WasmPtr},
vm::Ctx,
Expand Down Expand Up @@ -61,7 +63,8 @@ fn main() {
.clone()
.instantiate(&imports)
.expect("failed to instantiate wasm module");
let check_password = instance.func::<(u64, u64), u64>("check_password").unwrap();
let check_password: Func<(u64, u64), u64> =
instance.exports.get("check_password").unwrap();
let j = i * 10000;
let result = check_password.call(j, j + 10000).unwrap();
print!(".");
Expand Down Expand Up @@ -101,7 +104,7 @@ fn main() {
let instance =
instantiate(&wasm_bytes[..], &imports).expect("failed to instantiate wasm module");

let check_password = instance.func::<(u64, u64), u64>("check_password").unwrap();
let check_password: Func<(u64, u64), u64> = instance.exports.get("check_password").unwrap();

let mut out: Option<RetStr> = None;
for i in (0..=u64::max_value()).step_by(10000) {
Expand Down
4 changes: 2 additions & 2 deletions examples/plugin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use wasmer_runtime::{compile, func, imports};
use wasmer_runtime::{compile, func, imports, Func};
use wasmer_runtime_core::vm::Ctx;
use wasmer_wasi::{
generate_import_object_for_version,
Expand Down Expand Up @@ -159,7 +159,7 @@ fn main() {
initialize(instance.context_mut());

// get a reference to the function "plugin_entrypoint" which takes an i32 and returns an i32
let entry_point = instance.func::<(i32), i32>("plugin_entrypoint").unwrap();
let entry_point: Func<i32, i32> = instance.exports.get("plugin_entrypoint").unwrap();
// call the "entry_point" function in WebAssembly with the number "2" as the i32 argument
let result = entry_point.call(2).expect("failed to execute plugin");
println!("result: {}", result);
Expand Down
4 changes: 2 additions & 2 deletions fuzz/fuzz_targets/validate_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
#[macro_use]
extern crate libfuzzer_sys;

extern crate wasmer;
extern crate wasmer_bin;
extern crate wasmer_runtime_core;

use wasmer_runtime_core::backend::Features;

fuzz_target!(|data: &[u8]| {
let _ = wasmer::utils::is_wasm_binary(data);
let _ = wasmer_bin::utils::is_wasm_binary(data);
let _ = wasmer_runtime_core::validate_and_report_errors_with_features(
&data,
Features {
Expand Down
15 changes: 15 additions & 0 deletions lib/api-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "api-tests"
version = "0.16.2"
authors = ["The Wasmer Engineering Team <[email protected]>"]
edition = "2018"
license = "MIT"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
wasmer = { version = "0.16.2", path = "../api" }

[dev-dependencies]
wabt = "0.9.1"
1 change: 1 addition & 0 deletions lib/api-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

211 changes: 211 additions & 0 deletions lib/api-tests/tests/high_level_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
static TEST_WAT: &str = r#"
(module
(import "env" "outside-global" (global $outside-global (mut i32)))
(import "env" "update-func" (func $update-func (param i32) (result i32)))
(table $test-table (export "test-table") 2 anyfunc)
(global $test-global (export "test-global") (mut i32) (i32.const 3))
(elem (;0;) (i32.const 0) $ret_2)
(func $ret_2 (export "ret_2") (result i32)
i32.const 2)
(func $ret_4 (export "ret_4") (result i32)
i32.const 4)
(func $set_test_global (export "set_test_global") (param i32)
(global.set $test-global
(local.get 0)))
(func $update-outside-global (export "update_outside_global")
(global.set $outside-global
(call $update-func (global.get $outside-global))))
)
"#;

fn append_custom_section(
wasm: &mut Vec<u8>,
custom_section_name: &str,
custom_section_contents: &[u8],
) {
wasm.reserve(
// 1 for custom section id, 5 for max length of custom section, 5 for max length of name
custom_section_name.len() + custom_section_contents.len() + 1 + 5 + 5,
);

wasm.push(0);

let name_length = custom_section_name.as_bytes().len() as u32;
let mut name_length_as_leb128 = vec![];
write_u32_leb128(&mut name_length_as_leb128, name_length);

let custom_section_length = (custom_section_contents.len()
+ custom_section_name.as_bytes().len()
+ name_length_as_leb128.len()) as u32;

let mut custom_section_length_as_leb128 = vec![];
write_u32_leb128(&mut custom_section_length_as_leb128, custom_section_length);

wasm.extend(&custom_section_length_as_leb128);
wasm.extend(&name_length_as_leb128);
wasm.extend(custom_section_name.as_bytes());
wasm.extend(custom_section_contents);
}

#[test]
fn custom_section_parsing_works() {
use wasmer::{CompiledModule, Module};
let wasm = {
let mut wasm = wabt::wat2wasm(TEST_WAT).unwrap();
append_custom_section(&mut wasm, "test_custom_section", b"hello, world!");
append_custom_section(&mut wasm, "test_custom_section", b"goodbye, world!");
append_custom_section(&mut wasm, "different_name", b"different value");
wasm
};

let module = Module::new(wasm).unwrap();

assert_eq!(
module.custom_sections("test_custom_section"),
Some(&[b"hello, world!".to_vec(), b"goodbye, world!".to_vec()][..])
);
}

#[test]
fn module_exports_are_ordered() {
use wasmer::{export, CompiledModule, Module};

let wasm = wabt::wat2wasm(TEST_WAT).unwrap();
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be
// misleading, if so we may want to do something about it.
let module = Module::new(wasm).unwrap();
let exports = module.exports().collect::<Vec<_>>();
assert_eq!(
exports,
vec![
export::ExportDescriptor {
name: "test-table",
ty: export::ExportType::Table,
},
export::ExportDescriptor {
name: "test-global",
ty: export::ExportType::Global,
},
export::ExportDescriptor {
name: "ret_2",
ty: export::ExportType::Function,
},
export::ExportDescriptor {
name: "ret_4",
ty: export::ExportType::Function,
},
export::ExportDescriptor {
name: "set_test_global",
ty: export::ExportType::Function,
},
export::ExportDescriptor {
name: "update_outside_global",
ty: export::ExportType::Function,
},
]
);
}

#[test]
fn module_imports_are_correct() {
use wasmer::{CompiledModule, Module};

let wasm = wabt::wat2wasm(TEST_WAT).unwrap();
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be
// misleading, if so we may want to do something about it.
let module = Module::new(wasm).unwrap();

// TODO: test this more later
let imports = module.imports();
assert_eq!(imports.len(), 2);
}

#[test]
fn module_can_be_instantiated() {
use wasmer::wasm::{Global, Value};
use wasmer::{func, imports, CompiledModule, Module};

let wasm = wabt::wat2wasm(TEST_WAT).unwrap();
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be
// misleading, if so we may want to do something about it.
let module = Module::new(wasm).unwrap();

let outside_global = Global::new_mutable(Value::I32(15));
let import_object = imports! {
"env" => {
"update-func" => func!(|x: i32| x * 2),
"outside-global" => outside_global.clone(),
}
};
let instance = module.instantiate(&import_object);

assert!(instance.is_ok());
}

#[test]
fn exports_work() {
use wasmer::wasm::{Global, Value};
use wasmer::{func, imports, CompiledModule, Func, Module, Table};

let wasm = wabt::wat2wasm(TEST_WAT).unwrap();
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be
// misleading, if so we may want to do something about it.
let module = Module::new(wasm).unwrap();

let outside_global = Global::new_mutable(Value::I32(15));

let import_object = imports! {
"env" => {
"update-func" => func!(|x: i32| x * 2),
"outside-global" => outside_global.clone(),
}
};
let instance = module.instantiate(&import_object).unwrap();

let ret_2: Func<(), i32> = instance.exports.get("ret_2").unwrap();
let ret_4: Func<(), i32> = instance.exports.get("ret_4").unwrap();
let set_test_global: Func<i32> = instance.exports.get("set_test_global").unwrap();
let update_outside_global: Func = instance.exports.get("update_outside_global").unwrap();

assert_eq!(ret_2.call(), Ok(2));
assert_eq!(ret_4.call(), Ok(4));

let _test_table: Table = instance.exports.get("test-table").unwrap();
// TODO: when table get is stablized test this

let test_global: Global = instance.exports.get("test-global").unwrap();
// TODO: do we want to make global.get act like exports.get()?
assert_eq!(test_global.get(), Value::I32(3));
set_test_global.call(17).unwrap();
assert_eq!(test_global.get(), Value::I32(17));

assert_eq!(outside_global.get(), Value::I32(15));
update_outside_global.call().unwrap();
assert_eq!(outside_global.get(), Value::I32(15 * 2));
update_outside_global.call().unwrap();
assert_eq!(outside_global.get(), Value::I32(15 * 2 * 2));
}

// copied from Rust stdlib: https://doc.rust-lang.org/nightly/nightly-rustc/src/serialize/leb128.rs.html#4-14
macro_rules! impl_write_unsigned_leb128 {
($fn_name:ident, $int_ty:ident) => {
#[inline]
pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) {
loop {
if value < 0x80 {
out.push(value as u8);
break;
} else {
out.push(((value & 0x7f) | 0x80) as u8);
value >>= 7;
}
}
}
};
}

impl_write_unsigned_leb128!(write_u16_leb128, u16);
impl_write_unsigned_leb128!(write_u32_leb128, u32);
impl_write_unsigned_leb128!(write_u64_leb128, u64);
impl_write_unsigned_leb128!(write_u128_leb128, u128);
impl_write_unsigned_leb128!(write_usize_leb128, usize);
Loading

0 comments on commit 815ecac

Please sign in to comment.