Merge branch 'master' into feature/more-wasi-syscalls

This commit is contained in:
Mark McCaskey 2019-08-05 09:55:40 +09:00 committed by GitHub
commit 09acf3e581
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 1499 additions and 887 deletions

View File

@ -5,6 +5,7 @@ All PRs to the Wasmer repository must add to this file.
Blocks of changes will separated by version increments. Blocks of changes will separated by version increments.
## **[Unreleased]** ## **[Unreleased]**
- [#609](https://github.com/wasmerio/wasmer/issues/609) Update dependencies
## 0.6.0 - 2019-07-31 ## 0.6.0 - 2019-07-31
- [#603](https://github.com/wasmerio/wasmer/pull/603) Update Wapm-cli, bump version numbers - [#603](https://github.com/wasmerio/wasmer/pull/603) Update Wapm-cli, bump version numbers

578
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -19,11 +19,10 @@ include = [
] ]
[dependencies] [dependencies]
byteorder = "1.3.1" byteorder = "1.3.2"
errno = "0.2.4" errno = "0.2.4"
structopt = "0.2.11" structopt = "0.2.18"
wabt = "0.9.0" wabt = "0.9.0"
hashbrown = "0.1.8"
wasmer-clif-backend = { path = "lib/clif-backend" } wasmer-clif-backend = { path = "lib/clif-backend" }
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true } wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true }
wasmer-middleware-common = { path = "lib/middleware-common" } wasmer-middleware-common = { path = "lib/middleware-common" }
@ -62,7 +61,7 @@ members = [
[build-dependencies] [build-dependencies]
wabt = "0.9.0" wabt = "0.9.0"
glob = "0.2.11" glob = "0.3.0"
rustc_version = "0.2.3" rustc_version = "0.2.3"
[features] [features]

View File

@ -84,7 +84,7 @@ singlepass: spectests-singlepass emtests-singlepass middleware-singlepass wasite
cranelift: spectests-cranelift emtests-cranelift middleware-cranelift wasitests-cranelift cranelift: spectests-cranelift emtests-cranelift middleware-cranelift wasitests-cranelift
cargo test -p wasmer-clif-backend --release cargo test -p wasmer-clif-backend --release
llvm: spectests-llvm emtests-llvm middleware-llvm wasitests-llvm llvm: spectests-llvm emtests-llvm wasitests-llvm
cargo test -p wasmer-llvm-backend --release cargo test -p wasmer-llvm-backend --release

View File

@ -15,26 +15,26 @@ cranelift-codegen = { version = "0.31" }
cranelift-entity = { version = "0.31" } cranelift-entity = { version = "0.31" }
cranelift-frontend = { package = "wasmer-clif-fork-frontend", version = "0.33" } cranelift-frontend = { package = "wasmer-clif-fork-frontend", version = "0.33" }
cranelift-wasm = { package = "wasmer-clif-fork-wasm", version = "0.33" } cranelift-wasm = { package = "wasmer-clif-fork-wasm", version = "0.33" }
hashbrown = "0.1"
target-lexicon = "0.4.0" target-lexicon = "0.4.0"
wasmparser = "0.35.1" wasmparser = "0.35.1"
byteorder = "1" byteorder = "1.3.2"
nix = "0.14.0" nix = "0.14.1"
libc = "0.2.49" libc = "0.2.60"
rayon = "1.0" rayon = "1.1.0"
# Dependencies for caching. # Dependencies for caching.
[dependencies.serde] [dependencies.serde]
version = "1.0" version = "1.0.98"
features = ["rc"]
[dependencies.serde_derive] [dependencies.serde_derive]
version = "1.0" version = "1.0.98"
[dependencies.serde_bytes] [dependencies.serde_bytes]
version = "0.10" version = "0.11.1"
[dependencies.serde-bench] [dependencies.serde-bench]
version = "0.0.7" version = "0.0.7"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] } winapi = { version = "0.3.7", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.6.0" } wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.6.0" }
[features] [features]

View File

@ -1,6 +1,6 @@
use crate::relocation::{ExternalRelocation, TrapSink}; use crate::relocation::{ExternalRelocation, TrapSink};
use hashbrown::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::{sys::Memory, CacheGen}, backend::{sys::Memory, CacheGen},

View File

@ -89,10 +89,12 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
func, func,
func_translator, func_translator,
next_local: 0, next_local: 0,
clif_signatures: self.clif_signatures.clone(), position: Position::default(),
func_env: FunctionEnvironment {
module_info: Arc::clone(&module_info), module_info: Arc::clone(&module_info),
target_config: self.isa.frontend_config().clone(), target_config: self.isa.frontend_config().clone(),
position: Position::default(), clif_signatures: self.clif_signatures.clone(),
},
}; };
debug_assert_eq!(func_env.func.dfg.num_ebbs(), 0, "Function must be empty"); debug_assert_eq!(func_env.func.dfg.num_ebbs(), 0, "Function must be empty");
@ -391,10 +393,8 @@ pub struct CraneliftFunctionCodeGenerator {
func: Function, func: Function,
func_translator: FuncTranslator, func_translator: FuncTranslator,
next_local: usize, next_local: usize,
pub clif_signatures: Map<SigIndex, ir::Signature>,
module_info: Arc<RwLock<ModuleInfo>>,
target_config: isa::TargetFrontendConfig,
position: Position, position: Position,
func_env: FunctionEnvironment,
} }
pub struct FunctionEnvironment { pub struct FunctionEnvironment {
@ -1138,11 +1138,6 @@ impl FunctionCodeGenerator<CodegenError> for CraneliftFunctionCodeGenerator {
//let builder = self.builder.as_mut().unwrap(); //let builder = self.builder.as_mut().unwrap();
//let func_environment = FuncEnv::new(); //let func_environment = FuncEnv::new();
//let state = TranslationState::new(); //let state = TranslationState::new();
let mut function_environment = FunctionEnvironment {
module_info: Arc::clone(&self.module_info),
target_config: self.target_config.clone(),
clif_signatures: self.clif_signatures.clone(),
};
if self.func_translator.state.control_stack.is_empty() { if self.func_translator.state.control_stack.is_empty() {
return Ok(()); return Ok(());
@ -1154,7 +1149,7 @@ impl FunctionCodeGenerator<CodegenError> for CraneliftFunctionCodeGenerator {
&mut self.position, &mut self.position,
); );
let state = &mut self.func_translator.state; let state = &mut self.func_translator.state;
translate_operator(op, &mut builder, state, &mut function_environment)?; translate_operator(op, &mut builder, state, &mut self.func_env)?;
Ok(()) Ok(())
} }

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
mod cache; mod cache;
mod code; mod code;
mod libcalls; mod libcalls;

View File

@ -5,7 +5,7 @@ use cranelift_codegen::{
ir::{self, InstBuilder}, ir::{self, InstBuilder},
isa, Context, isa, Context,
}; };
use hashbrown::HashMap; use std::collections::HashMap;
use std::{iter, mem, ptr::NonNull}; use std::{iter, mem, ptr::NonNull};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
backend::sys::{Memory, Protect}, backend::sys::{Memory, Protect},

View File

@ -8,4 +8,4 @@ edition = "2018"
repository = "https://github.com/wasmerio/wasmer" repository = "https://github.com/wasmerio/wasmer"
[dependencies] [dependencies]
libc = "0.2.49" libc = "0.2.60"

View File

@ -20,7 +20,7 @@ wabt = "0.9.0"
wasmer-dev-utils = { path = "../dev-utils", version = "0.6.0"} wasmer-dev-utils = { path = "../dev-utils", version = "0.6.0"}
[build-dependencies] [build-dependencies]
glob = "0.2.11" glob = "0.3.0"
[features] [features]
clif = [] clif = []

View File

@ -8,15 +8,14 @@ repository = "https://github.com/wasmerio/wasmer"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
byteorder = "1" byteorder = "1.3.2"
hashbrown = "0.1" lazy_static = "1.3.0"
lazy_static = "1.2.0" libc = "0.2.60"
libc = "0.2.49" time = "0.1.42"
time = "0.1.41"
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
rand = "0.6" rand = "0.7.0"
[features] [features]
debug = ["wasmer-runtime-core/debug"] debug = ["wasmer-runtime-core/debug"]

View File

@ -30,6 +30,7 @@ pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 {
.unwrap() .unwrap()
} }
#[warn(dead_code)]
pub fn call_malloc_with_cast<T: Copy, Ty>(ctx: &mut Ctx, size: u32) -> WasmPtr<T, Ty> { pub fn call_malloc_with_cast<T: Copy, Ty>(ctx: &mut Ctx, size: u32) -> WasmPtr<T, Ty> {
WasmPtr::new(call_malloc(ctx, size)) WasmPtr::new(call_malloc(ctx, size))
} }

View File

@ -1,11 +1,16 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#[macro_use] #[macro_use]
extern crate wasmer_runtime_core; extern crate wasmer_runtime_core;
use hashbrown::HashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::{f64, ffi::c_void}; use std::{f64, ffi::c_void};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
@ -25,11 +30,11 @@ use wasmer_runtime_core::{
}; };
#[cfg(unix)] #[cfg(unix)]
use ::libc::DIR as libcDIR; use ::libc::DIR as LibcDir;
// We use a placeholder for windows // We use a placeholder for windows
#[cfg(not(unix))] #[cfg(not(unix))]
type libcDIR = u8; type LibcDir = u8;
#[macro_use] #[macro_use]
mod macros; mod macros;
@ -93,7 +98,7 @@ pub struct EmscriptenData<'a> {
pub memset: Option<Func<'a, (u32, u32, u32), u32>>, pub memset: Option<Func<'a, (u32, u32, u32), u32>>,
pub stack_alloc: Option<Func<'a, u32, u32>>, pub stack_alloc: Option<Func<'a, u32, u32>>,
pub jumps: Vec<UnsafeCell<[u32; 27]>>, pub jumps: Vec<UnsafeCell<[u32; 27]>>,
pub opened_dirs: HashMap<i32, Box<*mut libcDIR>>, pub opened_dirs: HashMap<i32, Box<*mut LibcDir>>,
pub dyn_call_i: Option<Func<'a, i32, i32>>, pub dyn_call_i: Option<Func<'a, i32, i32>>,
pub dyn_call_ii: Option<Func<'a, (i32, i32), i32>>, pub dyn_call_ii: Option<Func<'a, (i32, i32), i32>>,

View File

@ -5,5 +5,5 @@ authors = ["Heyang Zhou <zhy20000919@hotmail.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
libc = "0.2.49" libc = "0.2.60"
wasmer-runtime-core = { path = "../runtime-core" } wasmer-runtime-core = { path = "../runtime-core" }

View File

@ -8,12 +8,11 @@ readme = "README.md"
[dependencies] [dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" }
wasmparser = "0.35.1" wasmparser = "0.35.1"
hashbrown = "0.1.8" smallvec = "0.6.10"
smallvec = "0.6.8" goblin = "0.0.24"
goblin = "0.0.20" libc = "0.2.60"
libc = "0.2.49" nix = "0.14.1"
nix = "0.14.0" capstone = { version = "0.6.0", optional = true }
capstone = { version = "0.5.0", optional = true }
[dependencies.inkwell] [dependencies.inkwell]
git = "https://github.com/wasmerio/inkwell" git = "https://github.com/wasmerio/inkwell"
@ -22,12 +21,12 @@ default-features = false
features = ["llvm8-0", "target-x86"] features = ["llvm8-0", "target-x86"]
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["memoryapi"] } winapi = { version = "0.3.7", features = ["memoryapi"] }
[build-dependencies] [build-dependencies]
cc = "1.0" cc = "1.0"
lazy_static = "1.2.0" lazy_static = "1.3.0"
regex = "1.1.0" regex = "1.2.0"
semver = "0.9" semver = "0.9"
rustc_version = "0.2.3" rustc_version = "0.2.3"

View File

@ -17,28 +17,31 @@ public:
callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size); callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size);
} }
virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { virtual uint8_t *allocateCodeSection(uintptr_t size, unsigned alignment,
unsigned section_id,
llvm::StringRef section_name) override {
return allocate_bump(code_section, code_bump_ptr, size, alignment); return allocate_bump(code_section, code_bump_ptr, size, alignment);
} }
virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { virtual uint8_t *allocateDataSection(uintptr_t size, unsigned alignment,
// Allocate from the read-only section or the read-write section, depending on if this allocation unsigned section_id,
// should be read-only or not. llvm::StringRef section_name,
bool read_only) override {
// Allocate from the read-only section or the read-write section, depending
// on if this allocation should be read-only or not.
if (read_only) { if (read_only) {
return allocate_bump(read_section, read_bump_ptr, size, alignment); return allocate_bump(read_section, read_bump_ptr, size, alignment);
} else { } else {
return allocate_bump(readwrite_section, readwrite_bump_ptr, size, alignment); return allocate_bump(readwrite_section, readwrite_bump_ptr, size,
alignment);
} }
} }
virtual void reserveAllocationSpace( virtual void reserveAllocationSpace(uintptr_t code_size, uint32_t code_align,
uintptr_t code_size,
uint32_t code_align,
uintptr_t read_data_size, uintptr_t read_data_size,
uint32_t read_data_align, uint32_t read_data_align,
uintptr_t read_write_data_size, uintptr_t read_write_data_size,
uint32_t read_write_data_align uint32_t read_write_data_align) override {
) override {
auto aligner = [](uintptr_t ptr, size_t align) { auto aligner = [](uintptr_t ptr, size_t align) {
if (ptr == 0) { if (ptr == 0) {
return align; return align;
@ -46,62 +49,69 @@ public:
return (ptr + align - 1) & ~(align - 1); return (ptr + align - 1) & ~(align - 1);
}; };
uint8_t *code_ptr_out = nullptr; uint8_t *code_ptr_out = nullptr;
size_t code_size_out = 0; size_t code_size_out = 0;
auto code_result = callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); auto code_result =
callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE,
&code_ptr_out, &code_size_out);
assert(code_result == RESULT_OK); assert(code_result == RESULT_OK);
code_section = Section { code_ptr_out, code_size_out }; code_section = Section{code_ptr_out, code_size_out};
code_bump_ptr = (uintptr_t)code_ptr_out; code_bump_ptr = (uintptr_t)code_ptr_out;
uint8_t *read_ptr_out = nullptr; uint8_t *read_ptr_out = nullptr;
size_t read_size_out = 0; size_t read_size_out = 0;
auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096), PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096),
PROTECT_READ_WRITE, &read_ptr_out,
&read_size_out);
assert(read_result == RESULT_OK); assert(read_result == RESULT_OK);
read_section = Section { read_ptr_out, read_size_out }; read_section = Section{read_ptr_out, read_size_out};
read_bump_ptr = (uintptr_t)read_ptr_out; read_bump_ptr = (uintptr_t)read_ptr_out;
uint8_t *readwrite_ptr_out = nullptr; uint8_t *readwrite_ptr_out = nullptr;
size_t readwrite_size_out = 0; size_t readwrite_size_out = 0;
auto readwrite_result = callbacks.alloc_memory(aligner(read_write_data_size, 4096), PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); auto readwrite_result = callbacks.alloc_memory(
aligner(read_write_data_size, 4096), PROTECT_READ_WRITE,
&readwrite_ptr_out, &readwrite_size_out);
assert(readwrite_result == RESULT_OK); assert(readwrite_result == RESULT_OK);
readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; readwrite_section = Section{readwrite_ptr_out, readwrite_size_out};
readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out;
} }
/* Turn on the `reserveAllocationSpace` callback. */ /* Turn on the `reserveAllocationSpace` callback. */
virtual bool needsToReserveAllocationSpace() override { virtual bool needsToReserveAllocationSpace() override { return true; }
return true;
}
virtual void registerEHFrames(uint8_t* addr, uint64_t LoadAddr, size_t size) override { virtual void registerEHFrames(uint8_t *addr, uint64_t LoadAddr,
// We don't know yet how to do this on Windows, so we hide this on compilation size_t size) override {
// so we can compile and pass spectests on unix systems // We don't know yet how to do this on Windows, so we hide this on compilation
#ifndef _WIN32 // so we can compile and pass spectests on unix systems
#ifndef _WIN32
eh_frame_ptr = addr; eh_frame_ptr = addr;
eh_frame_size = size; eh_frame_size = size;
eh_frames_registered = true; eh_frames_registered = true;
callbacks.visit_fde(addr, size, __register_frame); callbacks.visit_fde(addr, size, __register_frame);
#endif #endif
} }
virtual void deregisterEHFrames() override { virtual void deregisterEHFrames() override {
// We don't know yet how to do this on Windows, so we hide this on compilation // We don't know yet how to do this on Windows, so we hide this on compilation
// so we can compile and pass spectests on unix systems // so we can compile and pass spectests on unix systems
#ifndef _WIN32 #ifndef _WIN32
if (eh_frames_registered) { if (eh_frames_registered) {
callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame); callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame);
} }
#endif #endif
} }
virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override {
auto code_result = callbacks.protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); auto code_result =
callbacks.protect_memory(code_section.base, code_section.size,
mem_protect_t::PROTECT_READ_EXECUTE);
if (code_result != RESULT_OK) { if (code_result != RESULT_OK) {
return false; return false;
} }
auto read_result = callbacks.protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); auto read_result = callbacks.protect_memory(
read_section.base, read_section.size, mem_protect_t::PROTECT_READ);
if (read_result != RESULT_OK) { if (read_result != RESULT_OK) {
return false; return false;
} }
@ -111,15 +121,19 @@ public:
return false; return false;
} }
virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override {} virtual void
notifyObjectLoaded(llvm::RuntimeDyld &RTDyld,
const llvm::object::ObjectFile &Obj) override {}
private: private:
struct Section { struct Section {
uint8_t* base; uint8_t *base;
size_t size; size_t size;
}; };
uint8_t* allocate_bump(Section& section, uintptr_t& bump_ptr, size_t size, size_t align) { uint8_t *allocate_bump(Section &section, uintptr_t &bump_ptr, size_t size,
auto aligner = [](uintptr_t& ptr, size_t align) { size_t align) {
auto aligner = [](uintptr_t &ptr, size_t align) {
ptr = (ptr + align - 1) & ~(align - 1); ptr = (ptr + align - 1) & ~(align - 1);
}; };
@ -131,12 +145,12 @@ private:
assert(bump_ptr <= (uintptr_t)section.base + section.size); assert(bump_ptr <= (uintptr_t)section.base + section.size);
return (uint8_t*)ret_ptr; return (uint8_t *)ret_ptr;
} }
Section code_section, read_section, readwrite_section; Section code_section, read_section, readwrite_section;
uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr;
uint8_t* eh_frame_ptr; uint8_t *eh_frame_ptr;
size_t eh_frame_size; size_t eh_frame_size;
bool eh_frames_registered = false; bool eh_frames_registered = false;
@ -147,7 +161,7 @@ struct SymbolLookup : llvm::JITSymbolResolver {
public: public:
SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {} SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {}
void lookup(const LookupSet& symbols, OnResolvedFunction OnResolved) { void lookup(const LookupSet &symbols, OnResolvedFunction OnResolved) {
LookupResult result; LookupResult result;
for (auto symbol : symbols) { for (auto symbol : symbols) {
@ -172,20 +186,19 @@ private:
callbacks_t callbacks; callbacks_t callbacks;
}; };
WasmModule::WasmModule( WasmModule::WasmModule(const uint8_t *object_start, size_t object_size,
const uint8_t *object_start, callbacks_t callbacks)
size_t object_size, : memory_manager(
callbacks_t callbacks std::unique_ptr<MemoryManager>(new MemoryManager(callbacks))) {
) : memory_manager(std::unique_ptr<MemoryManager>(new MemoryManager(callbacks)))
{
if (auto created_object_file =
if (auto created_object_file = llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef(
llvm::StringRef((const char *)object_start, object_size), "object" llvm::StringRef((const char *)object_start, object_size),
))) { "object"))) {
object_file = cantFail(std::move(created_object_file)); object_file = cantFail(std::move(created_object_file));
SymbolLookup symbol_resolver(callbacks); SymbolLookup symbol_resolver(callbacks);
runtime_dyld = std::unique_ptr<llvm::RuntimeDyld>(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); runtime_dyld = std::unique_ptr<llvm::RuntimeDyld>(
new llvm::RuntimeDyld(*memory_manager, symbol_resolver));
runtime_dyld->setProcessAllSections(true); runtime_dyld->setProcessAllSections(true);
@ -201,7 +214,7 @@ WasmModule::WasmModule(
} }
} }
void* WasmModule::get_func(llvm::StringRef name) const { void *WasmModule::get_func(llvm::StringRef name) const {
auto symbol = runtime_dyld->getSymbol(name); auto symbol = runtime_dyld->getSymbol(name);
return (void*)symbol.getAddress(); return (void *)symbol.getAddress();
} }

View File

@ -1,20 +1,19 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <llvm/ExecutionEngine/RuntimeDyld.h> #include <exception>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <exception>
typedef enum #include <llvm/ExecutionEngine/RuntimeDyld.h>
{
typedef enum {
PROTECT_NONE, PROTECT_NONE,
PROTECT_READ, PROTECT_READ,
PROTECT_READ_WRITE, PROTECT_READ_WRITE,
PROTECT_READ_EXECUTE, PROTECT_READ_EXECUTE,
} mem_protect_t; } mem_protect_t;
typedef enum typedef enum {
{
RESULT_OK, RESULT_OK,
RESULT_ALLOCATE_FAILURE, RESULT_ALLOCATE_FAILURE,
RESULT_PROTECT_FAILURE, RESULT_PROTECT_FAILURE,
@ -22,17 +21,19 @@ typedef enum
RESULT_OBJECT_LOAD_FAILURE, RESULT_OBJECT_LOAD_FAILURE,
} result_t; } result_t;
typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t **ptr_out, size_t *size_out); typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect,
typedef result_t (*protect_memory_t)(uint8_t *ptr, size_t size, mem_protect_t protect); uint8_t **ptr_out, size_t *size_out);
typedef result_t (*protect_memory_t)(uint8_t *ptr, size_t size,
mem_protect_t protect);
typedef result_t (*dealloc_memory_t)(uint8_t *ptr, size_t size); typedef result_t (*dealloc_memory_t)(uint8_t *ptr, size_t size);
typedef uintptr_t (*lookup_vm_symbol_t)(const char *name_ptr, size_t length); typedef uintptr_t (*lookup_vm_symbol_t)(const char *name_ptr, size_t length);
typedef void (*fde_visitor_t)(uint8_t *fde); typedef void (*fde_visitor_t)(uint8_t *fde);
typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, fde_visitor_t visitor); typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size,
fde_visitor_t visitor);
typedef void (*trampoline_t)(void *, void *, void *, void *); typedef void (*trampoline_t)(void *, void *, void *, void *);
typedef struct typedef struct {
{
/* Memory management. */ /* Memory management. */
alloc_memory_t alloc_memory; alloc_memory_t alloc_memory;
protect_memory_t protect_memory; protect_memory_t protect_memory;
@ -43,33 +44,27 @@ typedef struct
visit_fde_t visit_fde; visit_fde_t visit_fde;
} callbacks_t; } callbacks_t;
typedef struct typedef struct {
{
size_t data, vtable; size_t data, vtable;
} box_any_t; } box_any_t;
struct WasmException struct WasmException {
{ public:
public:
virtual std::string description() const noexcept = 0; virtual std::string description() const noexcept = 0;
}; };
struct UncatchableException : WasmException struct UncatchableException : WasmException {
{ public:
public: virtual std::string description() const noexcept override {
virtual std::string description() const noexcept override
{
return "Uncatchable exception"; return "Uncatchable exception";
} }
}; };
struct UserException : UncatchableException struct UserException : UncatchableException {
{ public:
public: UserException(size_t data, size_t vtable) : error_data({data, vtable}) {}
UserException(size_t data, size_t vtable) : error_data({ data, vtable }) {}
virtual std::string description() const noexcept override virtual std::string description() const noexcept override {
{
return "user exception"; return "user exception";
} }
@ -77,11 +72,20 @@ struct UserException : UncatchableException
box_any_t error_data; box_any_t error_data;
}; };
struct WasmTrap : UncatchableException struct BreakpointException : UncatchableException {
{ public:
public: BreakpointException(uintptr_t callback) : callback(callback) {}
enum Type
{ virtual std::string description() const noexcept override {
return "breakpoint exception";
}
uintptr_t callback;
};
struct WasmTrap : UncatchableException {
public:
enum Type {
Unreachable = 0, Unreachable = 0,
IncorrectCallIndirectSignature = 1, IncorrectCallIndirectSignature = 1,
MemoryOutOfBounds = 2, MemoryOutOfBounds = 2,
@ -92,23 +96,18 @@ struct WasmTrap : UncatchableException
WasmTrap(Type type) : type(type) {} WasmTrap(Type type) : type(type) {}
virtual std::string description() const noexcept override virtual std::string description() const noexcept override {
{
std::ostringstream ss; std::ostringstream ss;
ss ss << "WebAssembly trap:" << '\n' << " - type: " << type << '\n';
<< "WebAssembly trap:" << '\n'
<< " - type: " << type << '\n';
return ss.str(); return ss.str();
} }
Type type; Type type;
private: private:
friend std::ostream &operator<<(std::ostream &out, const Type &ty) friend std::ostream &operator<<(std::ostream &out, const Type &ty) {
{ switch (ty) {
switch (ty)
{
case Type::Unreachable: case Type::Unreachable:
out << "unreachable"; out << "unreachable";
break; break;
@ -133,13 +132,12 @@ struct WasmTrap : UncatchableException
} }
}; };
struct CatchableException : WasmException struct CatchableException : WasmException {
{ public:
public: CatchableException(uint32_t type_id, uint32_t value_num)
CatchableException(uint32_t type_id, uint32_t value_num) : type_id(type_id), value_num(value_num) {} : type_id(type_id), value_num(value_num) {}
virtual std::string description() const noexcept override virtual std::string description() const noexcept override {
{
return "catchable exception"; return "catchable exception";
} }
@ -147,27 +145,26 @@ struct CatchableException : WasmException
uint64_t values[1]; uint64_t values[1];
}; };
struct WasmModule struct WasmModule {
{ public:
public: WasmModule(const uint8_t *object_start, size_t object_size,
WasmModule(
const uint8_t *object_start,
size_t object_size,
callbacks_t callbacks); callbacks_t callbacks);
void *get_func(llvm::StringRef name) const; void *get_func(llvm::StringRef name) const;
bool _init_failed = false; bool _init_failed = false;
private:
private:
std::unique_ptr<llvm::RuntimeDyld::MemoryManager> memory_manager; std::unique_ptr<llvm::RuntimeDyld::MemoryManager> memory_manager;
std::unique_ptr<llvm::object::ObjectFile> object_file; std::unique_ptr<llvm::object::ObjectFile> object_file;
std::unique_ptr<llvm::RuntimeDyld> runtime_dyld; std::unique_ptr<llvm::RuntimeDyld> runtime_dyld;
}; };
extern "C" extern "C" {
{ void callback_trampoline(void *, void *);
result_t module_load(const uint8_t *mem_ptr, size_t mem_size, callbacks_t callbacks, WasmModule **module_out)
{ result_t module_load(const uint8_t *mem_ptr, size_t mem_size,
callbacks_t callbacks, WasmModule **module_out) {
*module_out = new WasmModule(mem_ptr, mem_size, callbacks); *module_out = new WasmModule(mem_ptr, mem_size, callbacks);
if ((*module_out)->_init_failed) { if ((*module_out)->_init_failed) {
@ -175,62 +172,49 @@ extern "C"
} }
return RESULT_OK; return RESULT_OK;
} }
[[noreturn]] void throw_trap(WasmTrap::Type ty) { [[noreturn]] void throw_trap(WasmTrap::Type ty) { throw WasmTrap(ty); }
throw WasmTrap(ty);
}
void module_delete(WasmModule *module) void module_delete(WasmModule *module) { delete module; }
{
delete module;
}
// Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust // Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust
// side. // side.
[[noreturn]] void throw_any(size_t data, size_t vtable) { [[noreturn]] void throw_any(size_t data, size_t vtable) {
throw UserException(data, vtable); throw UserException(data, vtable);
} }
bool invoke_trampoline( // Throw a pointer that's assumed to be codegen::BreakpointHandler on the
trampoline_t trampoline, // rust side.
void *ctx, [[noreturn]] void throw_breakpoint(uintptr_t callback) {
void *func, throw BreakpointException(callback);
void *params, }
void *results,
WasmTrap::Type *trap_out, bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func,
box_any_t *user_error, void *params, void *results, WasmTrap::Type *trap_out,
void *invoke_env) throw() box_any_t *user_error, void *invoke_env) noexcept {
{ try {
try
{
trampoline(ctx, func, params, results); trampoline(ctx, func, params, results);
return true; return true;
} } catch (const WasmTrap &e) {
catch (const WasmTrap &e)
{
*trap_out = e.type; *trap_out = e.type;
return false; return false;
} } catch (const UserException &e) {
catch (const UserException &e)
{
*user_error = e.error_data; *user_error = e.error_data;
return false; return false;
} } catch (const BreakpointException &e) {
catch (const WasmException &e) callback_trampoline(user_error, (void *)e.callback);
{ return false;
} catch (const WasmException &e) {
*trap_out = WasmTrap::Type::Unknown; *trap_out = WasmTrap::Type::Unknown;
return false; return false;
} } catch (...) {
catch (...)
{
*trap_out = WasmTrap::Type::Unknown; *trap_out = WasmTrap::Type::Unknown;
return false; return false;
} }
} }
void *get_func_symbol(WasmModule *module, const char *name) void *get_func_symbol(WasmModule *module, const char *name) {
{ return module->get_func(llvm::StringRef(name));
return module->get_func(llvm::StringRef(name)); }
}
} }

View File

@ -39,7 +39,8 @@ extern "C" {
fn module_delete(module: *mut LLVMModule); fn module_delete(module: *mut LLVMModule);
fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func; fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func;
fn throw_trap(ty: i32); fn throw_trap(ty: i32) -> !;
fn throw_breakpoint(ty: i64) -> !;
/// This should be the same as spliting up the fat pointer into two arguments, /// This should be the same as spliting up the fat pointer into two arguments,
/// but this is cleaner, I think? /// but this is cleaner, I think?
@ -103,6 +104,7 @@ fn get_callbacks() -> Callbacks {
fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _, fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _,
fn_name!("vm.exception.trap") => throw_trap as _, fn_name!("vm.exception.trap") => throw_trap as _,
fn_name!("vm.breakpoint") => throw_breakpoint as _,
_ => ptr::null(), _ => ptr::null(),
} }

View File

@ -496,6 +496,21 @@ pub struct CodegenError {
pub message: String, pub message: String,
} }
// This is only called by C++ code, the 'pub' + '#[no_mangle]' combination
// prevents unused function elimination.
#[no_mangle]
pub unsafe extern "C" fn callback_trampoline(
b: *mut Option<Box<dyn std::any::Any>>,
callback: *mut BreakpointHandler,
) {
let callback = Box::from_raw(callback);
let result: Result<(), Box<dyn std::any::Any>> = callback(BreakpointInfo { fault: None });
match result {
Ok(()) => *b = None,
Err(e) => *b = Some(e),
}
}
pub struct LLVMModuleCodeGenerator { pub struct LLVMModuleCodeGenerator {
context: Option<Context>, context: Option<Context>,
builder: Option<Builder>, builder: Option<Builder>,
@ -612,7 +627,14 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => { InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {
return Ok(()); return Ok(());
} }
InternalEvent::Breakpoint(_callback) => { InternalEvent::Breakpoint(callback) => {
let raw = Box::into_raw(Box::new(callback)) as u64;
let callback = intrinsics.i64_ty.const_int(raw, false);
builder.build_call(
intrinsics.throw_breakpoint,
&[callback.as_basic_value_enum()],
"",
);
return Ok(()); return Ok(());
} }
InternalEvent::GetInternal(idx) => { InternalEvent::GetInternal(idx) => {

View File

@ -1,4 +1,3 @@
use hashbrown::HashMap;
use inkwell::{ use inkwell::{
builder::Builder, builder::Builder,
context::Context, context::Context,
@ -9,6 +8,7 @@ use inkwell::{
values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue},
AddressSpace, AddressSpace,
}; };
use std::collections::HashMap;
use std::marker::PhantomData; use std::marker::PhantomData;
use wasmer_runtime_core::{ use wasmer_runtime_core::{
memory::MemoryType, memory::MemoryType,
@ -147,6 +147,7 @@ pub struct Intrinsics {
pub memory_size_shared_import: FunctionValue, pub memory_size_shared_import: FunctionValue,
pub throw_trap: FunctionValue, pub throw_trap: FunctionValue,
pub throw_breakpoint: FunctionValue,
pub ctx_ptr_ty: PointerType, pub ctx_ptr_ty: PointerType,
} }
@ -309,7 +310,6 @@ impl Intrinsics {
i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false); i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false);
let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false); let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false);
Self { Self {
ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None), ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None),
ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None), ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None),
@ -525,6 +525,11 @@ impl Intrinsics {
void_ty.fn_type(&[i32_ty_basic], false), void_ty.fn_type(&[i32_ty_basic], false),
None, None,
), ),
throw_breakpoint: module.add_function(
"vm.breakpoint",
void_ty.fn_type(&[i64_ty_basic], false),
None,
),
ctx_ptr_ty, ctx_ptr_ty,
} }
} }

View File

@ -1,4 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#![cfg_attr(nightly, feature(unwind_attributes))] #![cfg_attr(nightly, feature(unwind_attributes))]
mod backend; mod backend;

View File

@ -1,4 +1,9 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
pub mod call_trace; pub mod call_trace;
pub mod metering; pub mod metering;

View File

@ -129,7 +129,7 @@ pub fn set_points_used_ctx(ctx: &mut Ctx, value: u64) {
ctx.set_internal(&INTERNAL_FIELD, value); ctx.set_internal(&INTERNAL_FIELD, value);
} }
#[cfg(all(test, feature = "singlepass"))] #[cfg(all(test, any(feature = "singlepass", feature = "llvm")))]
mod tests { mod tests {
use super::*; use super::*;
use wabt::wat2wasm; use wabt::wat2wasm;
@ -247,7 +247,7 @@ mod tests {
// verify it returns the correct value // verify it returns the correct value
assert_eq!(value, 7); assert_eq!(value, 7);
// verify is uses the correct number of points // verify it used the correct number of points
assert_eq!(get_points_used(&instance), 74); assert_eq!(get_points_used(&instance), 74);
} }
@ -276,7 +276,7 @@ mod tests {
_ => unreachable!(), _ => unreachable!(),
} }
// verify is uses the correct number of points // verify it used the correct number of points
assert_eq!(get_points_used(&instance), 109); // Used points will be slightly more than `limit` because of the way we do gas checking. assert_eq!(get_points_used(&instance), 109); // Used points will be slightly more than `limit` because of the way we do gas checking.
} }

View File

@ -8,12 +8,11 @@ repository = "https://github.com/wasmerio/wasmer"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
libc = "0.2.50" libc = "0.2.60"
wasmer-runtime-core = { path = "../runtime-core" } wasmer-runtime-core = { path = "../runtime-core" }
hashbrown = "0.1"
failure = "0.1" failure = "0.1"
tar = "0.4" tar = "0.4"
wasmparser = "0.34.0" wasmparser = "0.35.1"
zstd = "0.4" zstd = "0.4"
# [target.'cfg(unix)'.dependencies.zbox] # [target.'cfg(unix)'.dependencies.zbox]

View File

@ -1,5 +1,4 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(dead_code, unused_imports, unused_variables, unused_unsafe, unreachable_patterns)]
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
#[macro_use] #[macro_use]
extern crate failure; extern crate failure;

View File

@ -1,7 +1,7 @@
use crate::vfs::file_like::FileLike; use crate::vfs::file_like::FileLike;
use crate::vfs::vfs_header::{header_from_bytes, ArchiveType, CompressionType}; use crate::vfs::vfs_header::{header_from_bytes, ArchiveType, CompressionType};
use crate::vfs::virtual_file::VirtualFile; use crate::vfs::virtual_file::VirtualFile;
use hashbrown::HashMap; use std::collections::HashMap;
use std::cell::RefCell; use std::cell::RefCell;
use std::io; use std::io;
use std::io::Read; use std::io::Read;

View File

@ -12,7 +12,7 @@ readme = "README.md"
crate-type = ["cdylib", "rlib", "staticlib"] crate-type = ["cdylib", "rlib", "staticlib"]
[dependencies] [dependencies]
libc = "0.2" libc = "0.2.60"
[dependencies.wasmer-runtime] [dependencies.wasmer-runtime]
path = "../runtime" path = "../runtime"
@ -27,4 +27,4 @@ debug = ["wasmer-runtime/debug"]
llvm = ["wasmer-runtime/llvm"] llvm = ["wasmer-runtime/llvm"]
[build-dependencies] [build-dependencies]
cbindgen = "0.8" cbindgen = "0.9.0"

View File

@ -10,9 +10,10 @@ use crate::{
}; };
use libc::c_uint; use libc::c_uint;
use std::{ffi::c_void, ptr, slice, sync::Arc}; use std::{ffi::c_void, ptr, slice, sync::Arc};
use wasmer_runtime::Module; use wasmer_runtime::{Global, Memory, Module, Table};
use wasmer_runtime_core::{ use wasmer_runtime_core::{
export::{Context, Export, FuncPointer}, export::{Context, Export, FuncPointer},
import::ImportObject,
module::ImportName, module::ImportName,
types::{FuncSig, Type}, types::{FuncSig, Type},
}; };
@ -25,6 +26,9 @@ pub struct wasmer_import_t {
pub value: wasmer_import_export_value, pub value: wasmer_import_export_value,
} }
#[repr(C)]
pub struct wasmer_import_object_t;
#[repr(C)] #[repr(C)]
#[derive(Clone)] #[derive(Clone)]
pub struct wasmer_import_func_t; pub struct wasmer_import_func_t;
@ -37,6 +41,83 @@ pub struct wasmer_import_descriptor_t;
#[derive(Clone)] #[derive(Clone)]
pub struct wasmer_import_descriptors_t; pub struct wasmer_import_descriptors_t;
/// Creates a new empty import object.
/// See also `wasmer_import_object_append`
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t {
let import_object = Box::new(ImportObject::new());
Box::into_raw(import_object) as *mut wasmer_import_object_t
}
/// Extends an existing import object with new imports
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_extend(
import_object: *mut wasmer_import_object_t,
imports: *mut wasmer_import_t,
imports_len: c_uint,
) -> wasmer_result_t {
let import_object: &mut ImportObject = &mut *(import_object as *mut ImportObject);
let mut extensions: Vec<(String, String, Export)> = Vec::new();
let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
for import in imports {
let module_name = slice::from_raw_parts(
import.module_name.bytes,
import.module_name.bytes_len as usize,
);
let module_name = if let Ok(s) = std::str::from_utf8(module_name) {
s
} else {
update_last_error(CApiError {
msg: "error converting module name to string".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
};
let import_name = slice::from_raw_parts(
import.import_name.bytes,
import.import_name.bytes_len as usize,
);
let import_name = if let Ok(s) = std::str::from_utf8(import_name) {
s
} else {
update_last_error(CApiError {
msg: "error converting import_name to string".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
};
let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory;
Export::Memory((&*mem).clone())
}
wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Export;
(&*func_export).clone()
}
wasmer_import_export_kind::WASM_GLOBAL => {
let global = import.value.global as *mut Global;
Export::Global((&*global).clone())
}
wasmer_import_export_kind::WASM_TABLE => {
let table = import.value.table as *mut Table;
Export::Table((&*table).clone())
}
};
let extension = (module_name.to_string(), import_name.to_string(), export);
extensions.push(extension)
}
import_object.extend(extensions);
return wasmer_result_t::WASMER_OK;
}
/// Gets import descriptors for the given module /// Gets import descriptors for the given module
/// ///
/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. /// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it.
@ -352,6 +433,14 @@ pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) {
} }
} }
/// Frees memory of the given ImportObject
#[no_mangle]
pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) {
if !import_object.is_null() {
unsafe { Box::from_raw(import_object as *mut ImportObject) };
}
}
struct NamedImportDescriptor { struct NamedImportDescriptor {
module: String, module: String,
name: String, name: String,

View File

@ -3,15 +3,19 @@
use crate::{ use crate::{
error::{update_last_error, CApiError}, error::{update_last_error, CApiError},
export::{wasmer_exports_t, wasmer_import_export_kind, NamedExport, NamedExports}, export::{wasmer_exports_t, wasmer_import_export_kind, NamedExport, NamedExports},
import::wasmer_import_t, import::{wasmer_import_object_t, wasmer_import_t},
memory::wasmer_memory_t, memory::wasmer_memory_t,
module::wasmer_module_t,
value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, value::{wasmer_value, wasmer_value_t, wasmer_value_tag},
wasmer_result_t, wasmer_result_t,
}; };
use libc::{c_char, c_int, c_void}; use libc::{c_char, c_int, c_void};
use std::{collections::HashMap, ffi::CStr, slice}; use std::{collections::HashMap, ffi::CStr, slice};
use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Table, Value}; use wasmer_runtime::{Ctx, Global, Instance, Memory, Module, Table, Value};
use wasmer_runtime_core::{export::Export, import::Namespace}; use wasmer_runtime_core::{
export::Export,
import::{ImportObject, Namespace},
};
#[repr(C)] #[repr(C)]
pub struct wasmer_instance_t; pub struct wasmer_instance_t;
@ -108,6 +112,45 @@ pub unsafe extern "C" fn wasmer_instantiate(
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
} }
/// Given:
/// * A prepared `wasmer` import-object
/// * A compiled wasmer module
///
/// Instantiates a wasmer instance
#[no_mangle]
pub unsafe extern "C" fn wasmer_module_import_instantiate(
instance: *mut *mut wasmer_instance_t,
module: *const wasmer_module_t,
import_object: *const wasmer_import_object_t,
) -> wasmer_result_t {
let import_object: &ImportObject = &*(import_object as *const ImportObject);
let module: &Module = &*(module as *const Module);
let new_instance: Instance = match module.instantiate(import_object) {
Ok(instance) => instance,
Err(error) => {
update_last_error(error);
return wasmer_result_t::WASMER_ERROR;
}
};
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
return wasmer_result_t::WASMER_OK;
}
/// Extracts the instance's context and returns it.
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_instance_context_get(
instance: *mut wasmer_instance_t,
) -> *const wasmer_instance_context_t {
let instance_ref = &*(instance as *const Instance);
let ctx: *const Ctx = instance_ref.context() as *const _;
ctx as *const wasmer_instance_context_t
}
/// Calls an instances exported function by `name` with the provided parameters. /// Calls an instances exported function by `name` with the provided parameters.
/// Results are set using the provided `results` pointer. /// Results are set using the provided `results` pointer.
/// ///

View File

@ -80,8 +80,13 @@
//! //!
//! [wasmer_h]: ./wasmer.h //! [wasmer_h]: ./wasmer.h
//! [wasmer_hh]: ./wasmer.hh //! [wasmer_hh]: ./wasmer.hh
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
extern crate wasmer_runtime; extern crate wasmer_runtime;
extern crate wasmer_runtime_core; extern crate wasmer_runtime_core;

View File

@ -23,3 +23,5 @@ test-module-imports
test-module-serialize test-module-serialize
test-tables test-tables
test-validate test-validate
test-context
test-module-import-instantiate

View File

@ -14,6 +14,8 @@ add_executable(test-module-imports test-module-imports.c)
add_executable(test-module-serialize test-module-serialize.c) add_executable(test-module-serialize test-module-serialize.c)
add_executable(test-tables test-tables.c) add_executable(test-tables test-tables.c)
add_executable(test-validate test-validate.c) add_executable(test-validate test-validate.c)
add_executable(test-context test-context.c)
add_executable(test-module-import-instantiate test-module-import-instantiate.c)
find_library( find_library(
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll
@ -87,3 +89,11 @@ add_test(test-tables test-tables)
target_link_libraries(test-validate general ${WASMER_LIB}) target_link_libraries(test-validate general ${WASMER_LIB})
target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS}) target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS})
add_test(test-validate test-validate) add_test(test-validate test-validate)
target_link_libraries(test-context general ${WASMER_LIB})
target_compile_options(test-context PRIVATE ${COMPILER_OPTIONS})
add_test(test-context test-context)
target_link_libraries(test-module-import-instantiate general ${WASMER_LIB})
target_compile_options(test-module-import-instantiate PRIVATE ${COMPILER_OPTIONS})
add_test(test-module-import-instantiate test-module-import-instantiate)

Binary file not shown.

View File

@ -0,0 +1,12 @@
(module
(func $inc (import "env" "inc"))
(func $mul (import "env" "mul"))
(func $get (import "env" "get") (result i32))
(func (export "inc_and_get") (result i32)
call $inc
call $get)
(func (export "mul_and_get") (result i32)
call $mul
call $get))

View File

@ -4,19 +4,17 @@ use std::process::Command;
fn test_c_api() { fn test_c_api() {
let project_tests_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests"); let project_tests_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/tests");
run_command("cmake", project_tests_dir, Some(".")); run_command("cmake", project_tests_dir, vec!["."]);
run_command("make", project_tests_dir, Some("-Wdev -Werror=dev")); run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]);
run_command("make", project_tests_dir, Some("test")); run_command("make", project_tests_dir, vec!["test", "ARGS=\"-V\""]);
} }
fn run_command(command_str: &str, dir: &str, arg: Option<&str>) { fn run_command(command_str: &str, dir: &str, args: Vec<&str>) {
println!("Running command: `{}` arg: {:?}", command_str, arg); println!("Running command: `{}` args: {:?}", command_str, args);
let mut command = Command::new(command_str); let mut command = Command::new(command_str);
if let Some(a) = arg { command.args(&args);
command.arg(a);
}
command.current_dir(dir); command.current_dir(dir);

View File

@ -0,0 +1,137 @@
#include <stdio.h>
#include "../wasmer.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>
typedef struct {
int32_t amount;
int32_t value;
} counter_data;
typedef struct {
uint8_t* bytes;
long bytes_len;
} wasm_file_t;
wasm_file_t read_wasm_file(const char* file_name) {
wasm_file_t wasm_file;
FILE *file = fopen(file_name, "r");
fseek(file, 0, SEEK_END);
wasm_file.bytes_len = ftell(file);
wasm_file.bytes = malloc(wasm_file.bytes_len);
fseek(file, 0, SEEK_SET);
fread(wasm_file.bytes, 1, wasm_file.bytes_len, file);
fclose(file);
return wasm_file;
}
void inc_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
data->value = data->value + data->amount;
}
void mul_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
data->value = data->value * data->amount;
}
int32_t get_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
return data->value;
}
counter_data *init_counter(int32_t value, int32_t amount) {
counter_data* counter = malloc(sizeof(counter_data));
counter->value = value;
counter->amount = amount;
return counter;
}
void assert_counter(wasmer_instance_t *instance, int32_t expected) {
wasmer_value_t result_one;
wasmer_value_t params[] = {};
wasmer_value_t results[] = {result_one};
wasmer_result_t call1_result = wasmer_instance_call(instance, "inc_and_get", params, 0, results, 1);
printf("Call result: %d\n", call1_result);
printf("Result: %d\n", results[0].value.I32);
assert(results[0].value.I32 == expected);
assert(call1_result == WASMER_OK);
const wasmer_instance_context_t *ctx = wasmer_instance_context_get(instance);
counter_data *cd = (counter_data*)wasmer_instance_context_data_get(ctx);
assert(cd->value == expected);
}
wasmer_import_t create_import(char* module_name, char* import_name, wasmer_import_func_t *func) {
wasmer_import_t import;
wasmer_byte_array module_name_bytes;
wasmer_byte_array import_name_bytes;
module_name_bytes.bytes = (const uint8_t *) module_name;
module_name_bytes.bytes_len = strlen(module_name);
import_name_bytes.bytes = (const uint8_t *) import_name;
import_name_bytes.bytes_len = strlen(import_name);
import.module_name = module_name_bytes;
import.import_name = import_name_bytes;
import.tag = WASM_FUNCTION;
import.value.func = func;
return import;
}
int main()
{
// Prepare Imports
wasmer_value_tag inc_params_sig[] = {};
wasmer_value_tag inc_returns_sig[] = {};
wasmer_import_func_t *inc_func = wasmer_import_func_new((void (*)(void *)) inc_counter, inc_params_sig, 0, inc_returns_sig, 0);
wasmer_import_t inc_import = create_import("env", "inc", inc_func);
wasmer_value_tag mul_params_sig[] = {};
wasmer_value_tag mul_returns_sig[] = {};
wasmer_import_func_t *mul_func = wasmer_import_func_new((void (*)(void *)) mul_counter, mul_params_sig, 0, mul_returns_sig, 0);
wasmer_import_t mul_import = create_import("env", "mul", mul_func);
wasmer_value_tag get_params_sig[] = {};
wasmer_value_tag get_returns_sig[] = {WASM_I32};
wasmer_import_func_t *get_func = wasmer_import_func_new((void (*)(void *)) get_counter, get_params_sig, 0, get_returns_sig, 1);
wasmer_import_t get_import = create_import("env", "get", get_func);
wasmer_import_t imports[] = {inc_import, mul_import, get_import};
// Read the wasm file
wasm_file_t wasm_file = read_wasm_file("assets/inc.wasm");
// Instantiate instance
printf("Instantiating\n");
wasmer_instance_t *instance = NULL;
wasmer_result_t instantiate_res = wasmer_instantiate(&instance, wasm_file.bytes, wasm_file.bytes_len, imports, 3);
printf("Compile result: %d\n", instantiate_res);
assert(instantiate_res == WASMER_OK);
// Init counter
counter_data *counter = init_counter(2, 5);
wasmer_instance_context_data_set(instance, counter);
// Run `instance.inc_and_get` and assert
assert_counter(instance, 7);
assert_counter(instance, 12);
assert_counter(instance, 17);
// Clear resources
wasmer_import_func_destroy(inc_func);
wasmer_import_func_destroy(get_func);
wasmer_instance_destroy(instance);
free(counter);
free(wasm_file.bytes);
return 0;
}

View File

@ -42,8 +42,9 @@ int main()
assert(export_length == 5); assert(export_length == 5);
// Get the `memory` export. // Get the `memory` export.
wasmer_export_t *export = wasmer_exports_get(exports, 1); wasmer_export_t *export = wasmer_exports_get(exports, 0);
wasmer_import_export_kind kind = wasmer_export_kind(export); wasmer_import_export_kind kind = wasmer_export_kind(export);
printf("Wasmer import export kind: %d (Memory is %d)\n", kind, WASM_MEMORY);
assert(kind == WASM_MEMORY); assert(kind == WASM_MEMORY);
wasmer_byte_array export_name = wasmer_export_name(export); wasmer_byte_array export_name = wasmer_export_name(export);

View File

@ -0,0 +1,149 @@
#include <stdio.h>
#include "../wasmer.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>
typedef struct {
int32_t amount;
int32_t value;
} counter_data;
typedef struct {
uint8_t* bytes;
long bytes_len;
} wasm_file_t;
wasm_file_t read_wasm_file(const char* file_name) {
wasm_file_t wasm_file;
FILE *file = fopen(file_name, "r");
fseek(file, 0, SEEK_END);
wasm_file.bytes_len = ftell(file);
wasm_file.bytes = malloc(wasm_file.bytes_len);
fseek(file, 0, SEEK_SET);
fread(wasm_file.bytes, 1, wasm_file.bytes_len, file);
fclose(file);
return wasm_file;
}
void inc_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
data->value = data->value + data->amount;
}
void mul_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
data->value = data->value * data->amount;
}
int32_t get_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
return data->value;
}
counter_data *init_counter(int32_t value, int32_t amount) {
counter_data* counter = malloc(sizeof(counter_data));
counter->value = value;
counter->amount = amount;
return counter;
}
wasmer_import_t create_import(char* module_name, char* import_name, wasmer_import_func_t *func) {
wasmer_import_t import;
wasmer_byte_array module_name_bytes;
wasmer_byte_array import_name_bytes;
module_name_bytes.bytes = (const uint8_t *) module_name;
module_name_bytes.bytes_len = strlen(module_name);
import_name_bytes.bytes = (const uint8_t *) import_name;
import_name_bytes.bytes_len = strlen(import_name);
import.module_name = module_name_bytes;
import.import_name = import_name_bytes;
import.tag = WASM_FUNCTION;
import.value.func = func;
return import;
}
int main()
{
// Prepare Imports
wasmer_value_tag inc_params_sig[] = {};
wasmer_value_tag inc_returns_sig[] = {};
wasmer_import_func_t *inc_func = wasmer_import_func_new((void (*)(void *)) inc_counter, inc_params_sig, 0, inc_returns_sig, 0);
wasmer_import_t inc_import = create_import("env", "inc", inc_func);
wasmer_value_tag mul_params_sig[] = {};
wasmer_value_tag mul_returns_sig[] = {};
wasmer_import_func_t *mul_func = wasmer_import_func_new((void (*)(void *)) mul_counter, mul_params_sig, 0, mul_returns_sig, 0);
wasmer_import_t mul_import = create_import("env", "mul", mul_func);
wasmer_value_tag get_params_sig[] = {};
wasmer_value_tag get_returns_sig[] = {WASM_I32};
wasmer_import_func_t *get_func = wasmer_import_func_new((void (*)(void *)) get_counter, get_params_sig, 0, get_returns_sig, 1);
wasmer_import_t get_import = create_import("env", "get", get_func);
// Read the wasm file
wasm_file_t wasm_file = read_wasm_file("assets/inc.wasm");
// Compile module
wasmer_module_t *module = NULL;
wasmer_result_t compile_res = wasmer_compile(&module, wasm_file.bytes, wasm_file.bytes_len);
assert(compile_res == WASMER_OK);
// Prepare Import Object
wasmer_import_object_t *import_object = wasmer_import_object_new();
// First, we import `inc_counter` and `mul_counter`
wasmer_import_t imports[] = {inc_import, mul_import};
wasmer_result_t extend_res = wasmer_import_object_extend(import_object, imports, 2);
assert(extend_res == WASMER_OK);
// Now, we'll import `inc_counter` and `mul_counter`
wasmer_import_t more_imports[] = {get_import};
wasmer_result_t extend_res2 = wasmer_import_object_extend(import_object, more_imports, 1);
assert(extend_res2 == WASMER_OK);
// Same `wasmer_import_object_extend` as the first, doesn't affect anything
wasmer_result_t extend_res3 = wasmer_import_object_extend(import_object, imports, 2);
assert(extend_res3 == WASMER_OK);
// Instantiate instance
printf("Instantiating\n");
wasmer_instance_t *instance = NULL;
wasmer_result_t instantiate_res = wasmer_module_import_instantiate(&instance, module, import_object);
printf("Compile result: %d\n", instantiate_res);
assert(instantiate_res == WASMER_OK);
// Init counter
counter_data *counter = init_counter(2, 5);
wasmer_instance_context_data_set(instance, counter);
wasmer_value_t result_one;
wasmer_value_t params[] = {};
wasmer_value_t results[] = {result_one};
wasmer_result_t call1_result = wasmer_instance_call(instance, "inc_and_get", params, 0, results, 1);
printf("Call result: %d\n", call1_result);
printf("Result: %d\n", results[0].value.I32);
wasmer_result_t call2_result = wasmer_instance_call(instance, "mul_and_get", params, 0, results, 1);
printf("Call result: %d\n", call2_result);
printf("Result: %d\n", results[0].value.I32);
// Clear resources
wasmer_import_func_destroy(inc_func);
wasmer_import_func_destroy(mul_func);
wasmer_import_func_destroy(get_func);
wasmer_instance_destroy(instance);
free(counter);
free(wasm_file.bytes);
return 0;
}

View File

@ -95,11 +95,7 @@ typedef struct {
typedef struct { typedef struct {
} wasmer_instance_t; } wasmer_import_object_t;
typedef struct {
} wasmer_instance_context_t;
typedef struct { typedef struct {
@ -119,6 +115,14 @@ typedef struct {
wasmer_import_export_value value; wasmer_import_export_value value;
} wasmer_import_t; } wasmer_import_t;
typedef struct {
} wasmer_instance_t;
typedef struct {
} wasmer_instance_context_t;
typedef struct { typedef struct {
bool has_some; bool has_some;
uint32_t some; uint32_t some;
@ -392,6 +396,24 @@ wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func,
wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func, wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func,
uint32_t *result); uint32_t *result);
/**
* Frees memory of the given ImportObject
*/
void wasmer_import_object_destroy(wasmer_import_object_t *import_object);
/**
* Extends an existing import object with new imports
*/
wasmer_result_t wasmer_import_object_extend(wasmer_import_object_t *import_object,
wasmer_import_t *imports,
unsigned int imports_len);
/**
* Creates a new empty import object.
* See also `wasmer_import_object_append`
*/
wasmer_import_object_t *wasmer_import_object_new(void);
/** /**
* Calls an instances exported function by `name` with the provided parameters. * Calls an instances exported function by `name` with the provided parameters.
* Results are set using the provided `results` pointer. * Results are set using the provided `results` pointer.
@ -417,6 +439,11 @@ void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx);
*/ */
void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr);
/**
* Extracts the instance's context and returns it.
*/
const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance);
/** /**
* Gets the memory within the context at the index `memory_idx`. * Gets the memory within the context at the index `memory_idx`.
* The index is always 0 until multiple memories are supported. * The index is always 0 until multiple memories are supported.
@ -526,6 +553,16 @@ wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module,
*/ */
void wasmer_module_destroy(wasmer_module_t *module); void wasmer_module_destroy(wasmer_module_t *module);
/**
* Given:
* A prepared `wasmer svm` import-object
* A compiled wasmer module
* Instantiates a wasmer instance
*/
wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance,
const wasmer_module_t *module,
const wasmer_import_object_t *import_object);
/** /**
* Creates a new Instance from the given module and imports. * Creates a new Instance from the given module and imports.
* Returns `wasmer_result_t::WASMER_OK` upon success. * Returns `wasmer_result_t::WASMER_OK` upon success.

View File

@ -91,11 +91,7 @@ struct wasmer_import_func_t {
}; };
struct wasmer_instance_t { struct wasmer_import_object_t {
};
struct wasmer_instance_context_t {
}; };
@ -117,6 +113,14 @@ struct wasmer_import_t {
wasmer_import_export_value value; wasmer_import_export_value value;
}; };
struct wasmer_instance_t {
};
struct wasmer_instance_context_t {
};
struct wasmer_limit_option_t { struct wasmer_limit_option_t {
bool has_some; bool has_some;
uint32_t some; uint32_t some;
@ -318,6 +322,18 @@ wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func,
wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func, wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func,
uint32_t *result); uint32_t *result);
/// Frees memory of the given ImportObject
void wasmer_import_object_destroy(wasmer_import_object_t *import_object);
/// Extends an existing import object with new imports
wasmer_result_t wasmer_import_object_extend(wasmer_import_object_t *import_object,
wasmer_import_t *imports,
unsigned int imports_len);
/// Creates a new empty import object.
/// See also `wasmer_import_object_append`
wasmer_import_object_t *wasmer_import_object_new();
/// Calls an instances exported function by `name` with the provided parameters. /// Calls an instances exported function by `name` with the provided parameters.
/// Results are set using the provided `results` pointer. /// Results are set using the provided `results` pointer.
/// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_OK` upon success.
@ -337,6 +353,9 @@ void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx);
/// passed to all imported function for instance. /// passed to all imported function for instance.
void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr);
/// Extracts the instance's context and returns it.
const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance);
/// Gets the memory within the context at the index `memory_idx`. /// Gets the memory within the context at the index `memory_idx`.
/// The index is always 0 until multiple memories are supported. /// The index is always 0 until multiple memories are supported.
const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx, const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx,
@ -418,6 +437,14 @@ wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module,
/// Frees memory for the given Module /// Frees memory for the given Module
void wasmer_module_destroy(wasmer_module_t *module); void wasmer_module_destroy(wasmer_module_t *module);
/// Given:
/// A prepared `wasmer svm` import-object
/// A compiled wasmer module
/// Instantiates a wasmer instance
wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance,
const wasmer_module_t *module,
const wasmer_import_object_t *import_object);
/// Creates a new Instance from the given module and imports. /// Creates a new Instance from the given module and imports.
/// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_OK` upon success.
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`

View File

@ -8,46 +8,46 @@ repository = "https://github.com/wasmerio/wasmer"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
nix = "0.14.0" nix = "0.14.1"
page_size = "0.4.1" page_size = "0.4.1"
wasmparser = "0.35.1" wasmparser = "0.35.1"
parking_lot = "0.7.1" parking_lot = "0.9.0"
lazy_static = "1.2.0" lazy_static = "1.3.0"
indexmap = "1.0.2"
errno = "0.2.4" errno = "0.2.4"
libc = "0.2.49" libc = "0.2.60"
hex = "0.3.2" hex = "0.3.2"
smallvec = "0.6.9" smallvec = "0.6.10"
bincode = "1.1" bincode = "1.1"
colored = "1.8" colored = "1.8"
[dependencies.indexmap]
version = "1.0.2"
features = ["serde-1"]
# Dependencies for caching. # Dependencies for caching.
[dependencies.serde] [dependencies.serde]
version = "1.0" version = "1.0.98"
# This feature is required for serde to support serializing/deserializing reference counted pointers (e.g. Rc and Arc). # This feature is required for serde to support serializing/deserializing reference counted pointers (e.g. Rc and Arc).
features = ["rc"] features = ["rc"]
[dependencies.serde_derive] [dependencies.serde_derive]
version = "1.0" version = "1.0.98"
[dependencies.serde_bytes] [dependencies.serde_bytes]
version = "0.10" version = "0.11.1"
[dependencies.serde-bench] [dependencies.serde-bench]
version = "0.0.7" version = "0.0.7"
[dependencies.blake2b_simd] [dependencies.blake2b_simd]
version = "0.4.1" version = "0.5.5"
[dependencies.digest] [dependencies.digest]
version = "0.8.0" version = "0.8.1"
[dependencies.hashbrown]
version = "0.1"
features = ["serde"]
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["memoryapi"] } winapi = { version = "0.3.7", features = ["memoryapi"] }
[dev-dependencies] [dev-dependencies]
field-offset = "0.1.1" field-offset = "0.1.1"
[build-dependencies] [build-dependencies]
blake2b_simd = "0.4.1" blake2b_simd = "0.5.5"
rustc_version = "0.2.3" rustc_version = "0.2.3"
cc = "1.0" cc = "1.0"

View File

@ -15,7 +15,7 @@ use crate::{
}; };
use std::{any::Any, ptr::NonNull}; use std::{any::Any, ptr::NonNull};
use hashbrown::HashMap; use std::collections::HashMap;
pub mod sys { pub mod sys {
pub use crate::sys::*; pub use crate::sys::*;

View File

@ -146,7 +146,7 @@ pub fn validating_parser_config(features: &Features) -> wasmparser::ValidatingPa
enable_bulk_memory: false, enable_bulk_memory: false,
enable_multi_value: false, enable_multi_value: false,
}, },
mutable_global_imports: false, mutable_global_imports: true,
} }
} }

View File

@ -134,7 +134,7 @@ impl std::fmt::Display for RuntimeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self { match self {
RuntimeError::Trap { ref msg } => { RuntimeError::Trap { ref msg } => {
write!(f, "WebAssembly trap occured during runtime: {}", msg) write!(f, "WebAssembly trap occurred during runtime: {}", msg)
} }
RuntimeError::Error { data } => { RuntimeError::Error { data } => {
if let Some(s) = data.downcast_ref::<String>() { if let Some(s) = data.downcast_ref::<String>() {

View File

@ -2,7 +2,7 @@ use crate::{
global::Global, instance::InstanceInner, memory::Memory, module::ExportIndex, global::Global, instance::InstanceInner, memory::Memory, module::ExportIndex,
module::ModuleInner, table::Table, types::FuncSig, vm, module::ModuleInner, table::Table, types::FuncSig, vm,
}; };
use hashbrown::hash_map; use indexmap::map::Iter as IndexMapIter;
use std::sync::Arc; use std::sync::Arc;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -41,7 +41,7 @@ impl FuncPointer {
pub struct ExportIter<'a> { pub struct ExportIter<'a> {
inner: &'a InstanceInner, inner: &'a InstanceInner,
iter: hash_map::Iter<'a, String, ExportIndex>, iter: IndexMapIter<'a, String, ExportIndex>,
module: &'a ModuleInner, module: &'a ModuleInner,
} }

View File

@ -1,6 +1,6 @@
use crate::export::Export; use crate::export::Export;
use hashbrown::{hash_map::Entry, HashMap};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::collections::{hash_map::Entry, HashMap};
use std::{ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
ffi::c_void, ffi::c_void,

View File

@ -1,4 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#![cfg_attr(nightly, feature(unwind_attributes))] #![cfg_attr(nightly, feature(unwind_attributes))]
#[cfg(test)] #[cfg(test)]
@ -134,7 +140,7 @@ pub fn validate_and_report_errors_with_features(
enable_reference_types: false, enable_reference_types: false,
enable_threads: false, enable_threads: false,
}, },
mutable_global_imports: false, mutable_global_imports: true,
}; };
let mut parser = wasmparser::ValidatingParser::new(wasm, Some(config)); let mut parser = wasmparser::ValidatingParser::new(wasm, Some(config));
loop { loop {

View File

@ -14,8 +14,8 @@ use crate::{
}; };
use crate::backend::CacheGen; use crate::backend::CacheGen;
use hashbrown::HashMap;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
/// This is used to instantiate a new WebAssembly module. /// This is used to instantiate a new WebAssembly module.
@ -40,7 +40,7 @@ pub struct ModuleInfo {
pub imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>, pub imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>, pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
pub exports: HashMap<String, ExportIndex>, pub exports: IndexMap<String, ExportIndex>,
pub data_initializers: Vec<DataInitializer>, pub data_initializers: Vec<DataInitializer>,
pub elem_initializers: Vec<TableInitializer>, pub elem_initializers: Vec<TableInitializer>,

View File

@ -14,7 +14,7 @@ use crate::{
}, },
units::Pages, units::Pages,
}; };
use hashbrown::HashMap; use std::collections::HashMap;
use std::fmt::Debug; use std::fmt::Debug;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use wasmparser::{ use wasmparser::{

View File

@ -2,9 +2,9 @@ use crate::{
structures::Map, structures::Map,
types::{FuncSig, SigIndex}, types::{FuncSig, SigIndex},
}; };
use hashbrown::HashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
lazy_static! { lazy_static! {

View File

@ -100,6 +100,7 @@ pub struct InstanceImage {
} }
impl ModuleStateMap { impl ModuleStateMap {
#[warn(dead_code)]
fn lookup_call_ip(&self, ip: usize, base: usize) -> Option<(&FunctionStateMap, MachineState)> { fn lookup_call_ip(&self, ip: usize, base: usize) -> Option<(&FunctionStateMap, MachineState)> {
if ip < base || ip - base >= self.total_size { if ip < base || ip - base >= self.total_size {
None None
@ -123,6 +124,7 @@ impl ModuleStateMap {
} }
} }
#[warn(dead_code)]
fn lookup_trappable_ip( fn lookup_trappable_ip(
&self, &self,
ip: usize, ip: usize,
@ -150,6 +152,7 @@ impl ModuleStateMap {
} }
} }
#[warn(dead_code)]
fn lookup_loop_ip(&self, ip: usize, base: usize) -> Option<(&FunctionStateMap, MachineState)> { fn lookup_loop_ip(&self, ip: usize, base: usize) -> Option<(&FunctionStateMap, MachineState)> {
if ip < base || ip - base >= self.total_size { if ip < base || ip - base >= self.total_size {
None None

View File

@ -16,7 +16,7 @@ use serde::{
Deserialize, Deserializer, Serialize, Serializer, Deserialize, Deserializer, Serialize, Serializer,
}; };
use serde_bytes::Bytes; use serde_bytes::{ByteBuf, Bytes};
use std::fmt; use std::fmt;
@ -56,7 +56,7 @@ impl<'de> Deserialize<'de> for Memory {
.next_element()? .next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?; .ok_or_else(|| de::Error::invalid_length(0, &self))?;
let bytes: Bytes = seq let bytes: ByteBuf = seq
.next_element()? .next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?; .ok_or_else(|| de::Error::invalid_length(1, &self))?;

View File

@ -14,7 +14,7 @@ use std::{
sync::Once, sync::Once,
}; };
use hashbrown::HashMap; use std::collections::HashMap;
/// The context of the currently running WebAssembly instance. /// The context of the currently running WebAssembly instance.
/// ///
@ -850,8 +850,9 @@ mod vm_ctx_tests {
use crate::cache::Error as CacheError; use crate::cache::Error as CacheError;
use crate::typed_func::Wasm; use crate::typed_func::Wasm;
use crate::types::{LocalFuncIndex, SigIndex}; use crate::types::{LocalFuncIndex, SigIndex};
use hashbrown::HashMap; use indexmap::IndexMap;
use std::any::Any; use std::any::Any;
use std::collections::HashMap;
use std::ptr::NonNull; use std::ptr::NonNull;
struct Placeholder; struct Placeholder;
impl RunnableModule for Placeholder { impl RunnableModule for Placeholder {
@ -890,7 +891,7 @@ mod vm_ctx_tests {
imported_tables: Map::new(), imported_tables: Map::new(),
imported_globals: Map::new(), imported_globals: Map::new(),
exports: HashMap::new(), exports: IndexMap::new(),
data_initializers: Vec::new(), data_initializers: Vec::new(),
elem_initializers: Vec::new(), elem_initializers: Vec::new(),

View File

@ -10,7 +10,7 @@ readme = "README.md"
[dependencies] [dependencies]
wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.6.0", optional = true } wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.6.0", optional = true }
lazy_static = "1.2.0" lazy_static = "1.3.0"
memmap = "0.7.0" memmap = "0.7.0"
[dependencies.wasmer-runtime-core] [dependencies.wasmer-runtime-core]
@ -23,7 +23,7 @@ version = "0.6.0"
optional = true optional = true
[dev-dependencies] [dev-dependencies]
tempfile = "3.0.7" tempfile = "3.1.0"
criterion = "0.2" criterion = "0.2"
wabt = "0.9.0" wabt = "0.9.0"

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
//! Wasmer-runtime is a library that makes embedding WebAssembly //! Wasmer-runtime is a library that makes embedding WebAssembly
//! in your application easy, efficient, and safe. //! in your application easy, efficient, and safe.
//! //!

View File

@ -13,10 +13,9 @@ wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" }
wasmparser = "0.35.1" wasmparser = "0.35.1"
dynasm = "0.3.2" dynasm = "0.3.2"
dynasmrt = "0.3.1" dynasmrt = "0.3.1"
lazy_static = "1.2.0" lazy_static = "1.3.0"
byteorder = "1" byteorder = "1.3.2"
nix = "0.14.0" nix = "0.14.1"
libc = "0.2.49" libc = "0.2.60"
smallvec = "0.6.9" smallvec = "0.6.10"
hashbrown = "0.1"
colored = "1.8" colored = "1.8"

View File

@ -1,4 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#![feature(proc_macro_hygiene)] #![feature(proc_macro_hygiene)]
#[cfg(not(any( #[cfg(not(any(

View File

@ -132,7 +132,7 @@ fn get_compiler() -> impl Compiler {
CraneliftCompiler::new() CraneliftCompiler::new()
} }
pub fn generate_imports() -> ImportObject { pub fn generate_imports(extra_imports: Vec<(String, Instance)>) -> ImportObject {
let mut features = wabt::Features::new(); let mut features = wabt::Features::new();
features.enable_simd(); features.enable_simd();
let wasm_binary = wat2wasm_with_features(IMPORT_MODULE.as_bytes(), features).expect("WAST not valid or malformed"); let wasm_binary = wat2wasm_with_features(IMPORT_MODULE.as_bytes(), features).expect("WAST not valid or malformed");
@ -143,6 +143,9 @@ pub fn generate_imports() -> ImportObject {
.expect("WASM can't be instantiated"); .expect("WASM can't be instantiated");
let mut imports = ImportObject::new(); let mut imports = ImportObject::new();
imports.register("spectest", instance); imports.register("spectest", instance);
for (name, instance) in extra_imports {
imports.register(name, instance);
}
imports imports
} }
@ -303,6 +306,8 @@ struct WastTestGenerator {
script_parser: ScriptParser, script_parser: ScriptParser,
module_calls: HashMap<i32, Vec<String>>, module_calls: HashMap<i32, Vec<String>>,
buffer: String, buffer: String,
modules_by_name: HashMap<String, i32>,
registered_modules: Vec<(i32, String)>,
} }
impl WastTestGenerator { impl WastTestGenerator {
@ -322,6 +327,8 @@ impl WastTestGenerator {
script_parser: script, script_parser: script,
buffer: buffer, buffer: buffer,
module_calls: HashMap::new(), module_calls: HashMap::new(),
modules_by_name: HashMap::new(),
registered_modules: Vec::new(),
} }
} }
@ -392,7 +399,7 @@ fn test_module_{}() {{
self.module_calls.remove(&module); self.module_calls.remove(&module);
} }
fn visit_module(&mut self, module: &ModuleBinary, _name: &Option<String>) { fn visit_module(&mut self, module: &ModuleBinary, name: &Option<String>) {
let wasm_binary: Vec<u8> = module.clone().into_vec(); let wasm_binary: Vec<u8> = module.clone().into_vec();
let mut features = Features::new(); let mut features = Features::new();
features.enable_simd(); features.enable_simd();
@ -409,7 +416,9 @@ fn test_module_{}() {{
println!(\"{{}}\", module_str); println!(\"{{}}\", module_str);
let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\"); let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\");
let module = wasmer_runtime_core::compile_with_config(&wasm_binary[..], &get_compiler(), CompilerConfig {{ features: Features {{ simd: true }}, ..Default::default() }}).expect(\"WASM can't be compiled\"); let module = wasmer_runtime_core::compile_with_config(&wasm_binary[..], &get_compiler(), CompilerConfig {{ features: Features {{ simd: true }}, ..Default::default() }}).expect(\"WASM can't be compiled\");
module.instantiate(&generate_imports()).expect(\"WASM can't be instantiated\") let mut extra_imports = Vec::new();
{}
module.instantiate(&generate_imports(extra_imports)).expect(\"WASM can't be instantiated\")
}}\n", }}\n",
self.last_module, self.last_module,
// We do this to ident four spaces, so it looks aligned to the function body // We do this to ident four spaces, so it looks aligned to the function body
@ -417,9 +426,22 @@ fn test_module_{}() {{
.replace("\n", "\n ") .replace("\n", "\n ")
.replace("\\", "\\\\") .replace("\\", "\\\\")
.replace("\"", "\\\""), .replace("\"", "\\\""),
self.registered_modules.iter().map(|(number, name)| format!("extra_imports.push((String::from(\"{}\"), create_module_{}()));", name, number)).fold(String::from(""), |acc, x| format!("{}{}\n", acc, x)),
) )
.as_str(), .as_str(),
); );
if let Some(name) = name {
self.record_named_module(name);
}
}
fn record_named_module(&mut self, name: &String) {
self.modules_by_name.insert(name.clone(), self.last_module);
}
fn visit_register_module(&mut self, name: &String, as_name: &String) {
self.registered_modules
.push((*self.modules_by_name.get(name).unwrap(), as_name.clone()));
} }
fn visit_assert_invalid(&mut self, module: &ModuleBinary) { fn visit_assert_invalid(&mut self, module: &ModuleBinary) {
@ -763,11 +785,8 @@ fn {}() {{
} => { } => {
// Do nothing for now // Do nothing for now
} }
CommandKind::Register { CommandKind::Register { name, as_name } => {
name: _, self.visit_register_module(name.as_ref().unwrap(), as_name);
as_name: _,
} => {
// Do nothing for now
} }
CommandKind::PerformAction(action) => { CommandKind::PerformAction(action) => {
self.visit_perform_action(action); self.visit_perform_action(action);

View File

@ -25,7 +25,7 @@ Currently supported command assertions:
- [x] `assert_malformed` _fully implemented_ - [x] `assert_malformed` _fully implemented_
- [ ] `assert_uninstantiable` _not implemented yet_ - [ ] `assert_uninstantiable` _not implemented yet_
- [ ] `assert_exhaustion` _not implemented yet_ - [ ] `assert_exhaustion` _not implemented yet_
- [ ] `register` _not implemented yet_ - [x] `register` _fully implemented_
- [x] `perform_action` _partially implemented, only function invocations for now_ - [x] `perform_action` _partially implemented, only function invocations for now_
### Covered spec tests ### Covered spec tests
@ -86,6 +86,7 @@ The following spec tests are currently covered:
- [x] return.wast - [x] return.wast
- [x] select.wast - [x] select.wast
- [x] set_local.wast - [x] set_local.wast
- [x] simd.wast
- [ ] skip-stack-guard-page.wast - [ ] skip-stack-guard-page.wast
- [x] stack.wast - [x] stack.wast
- [x] start.wast - [x] start.wast
@ -108,8 +109,6 @@ The following spec tests are currently covered:
There are some cases that we decided to skip for now to accelerate the release schedule: There are some cases that we decided to skip for now to accelerate the release schedule:
- `SKIP_MUTABLE_GLOBALS`: Right now the Wasm parser can't validate a module with imported/exported `mut` globals. We decided to skip the tests until Cranelift and wasmparser can handle this (see [original spec proposal](https://github.com/WebAssembly/mutable-global)). Spec tests affected:
- `globals.wast`
- `SKIP_CALL_INDIRECT_TYPE_MISMATCH`: we implemented traps in a fast way. We haven't yet covered the type mismatch on `call_indirect`. Specs affected: - `SKIP_CALL_INDIRECT_TYPE_MISMATCH`: we implemented traps in a fast way. We haven't yet covered the type mismatch on `call_indirect`. Specs affected:
- `call_indirect.wast` - `call_indirect.wast`

View File

@ -47,31 +47,27 @@
(data (i32.const 1) "h") (data (i32.const 1) "h")
) )
;; SKIP_MUTABLE_GLOBALS (module
;; (module (global (import "spectest" "global_i32") i32)
;; (global (import "spectest" "global_i32") i32) (memory 1)
;; (memory 1) (data (get_global 0) "a")
;; (data (get_global 0) "a") )
;; ) (module
;; SKIP_MUTABLE_GLOBALS (global (import "spectest" "global_i32") i32)
;; (module (import "spectest" "memory" (memory 1))
;; (global (import "spectest" "global_i32") i32) (data (get_global 0) "a")
;; (import "spectest" "memory" (memory 1)) )
;; (data (get_global 0) "a")
;; )
;; SKIP_MUTABLE_GLOBALS (module
;; (module (global $g (import "spectest" "global_i32") i32)
;; (global $g (import "spectest" "global_i32") i32) (memory 1)
;; (memory 1) (data (get_global $g) "a")
;; (data (get_global $g) "a") )
;; ) (module
;; SKIP_MUTABLE_GLOBALS (global $g (import "spectest" "global_i32") i32)
;; (module (import "spectest" "memory" (memory 1))
;; (global $g (import "spectest" "global_i32") i32) (data (get_global $g) "a")
;; (import "spectest" "memory" (memory 1)) )
;; (data (get_global $g) "a")
;; )
;; Use of internal globals in constant expressions is not allowed in MVP. ;; Use of internal globals in constant expressions is not allowed in MVP.
;; (module (memory 1) (data (get_global 0) "a") (global i32 (i32.const 0))) ;; (module (memory 1) (data (get_global 0) "a") (global i32 (i32.const 0)))
@ -138,19 +134,17 @@
(data (i32.const 0) "a") (data (i32.const 0) "a")
) )
;; SKIP_MUTABLE_GLOBALS (module
;; (module (global (import "spectest" "global_i32") i32)
;; (global (import "spectest" "global_i32") i32) (import "spectest" "memory" (memory 0))
;; (import "spectest" "memory" (memory 0)) (data (get_global 0) "a")
;; (data (get_global 0) "a") )
;; )
;; SKIP_MUTABLE_GLOBALS (module
;; (module (global (import "spectest" "global_i32") i32)
;; (global (import "spectest" "global_i32") i32) (import "spectest" "memory" (memory 0 3))
;; (import "spectest" "memory" (memory 0 3)) (data (get_global 0) "a")
;; (data (get_global 0) "a") )
;; )
(module (module
(import "spectest" "memory" (memory 0)) (import "spectest" "memory" (memory 0))

View File

@ -246,11 +246,9 @@
) )
;; mutable globals can be exported ;; mutable globals can be exported
;; SKIP_MUTABLE_GLOBALS (module (global (mut f32) (f32.const 0)) (export "a" (global 0)))
;; (module (global (mut f32) (f32.const 0)) (export "a" (global 0)))
;; SKIP_MUTABLE_GLOBALS (module (global (export "a") (mut f32) (f32.const 0)))
;; (module (global (export "a") (mut f32) (f32.const 0)))
(assert_invalid (assert_invalid
(module (global f32 (f32.neg (f32.const 0)))) (module (global f32 (f32.neg (f32.const 0))))

View File

@ -9,49 +9,48 @@
;; v128 globals ;; v128 globals
;; wasmer silently doesn't implement (register) yet (module $M
;;(module $M (global (export "a") v128 (v128.const f32x4 0.0 1.0 2.0 3.0))
;; (global (export "a") v128 (v128.const f32x4 0.0 1.0 2.0 3.0)) (global (export "b") (mut v128) (v128.const f32x4 4.0 5.0 6.0 7.0))
;; (global (export "b") (mut v128) (v128.const f32x4 4.0 5.0 6.0 7.0)) )
;;) (register "M" $M)
;;(register "M" $M)
(module (module
;; (global $a (import "M" "a") v128) (global $a (import "M" "a") v128)
;; (global $b (import "M" "b") (mut v128)) (global $b (import "M" "b") (mut v128))
;; (global $c v128 (global.get $a)) (global $c v128 (global.get $a))
(global $d v128 (v128.const i32x4 8 9 10 11)) (global $d v128 (v128.const i32x4 8 9 10 11))
;; (global $e (mut v128) (global.get $a)) (global $e (mut v128) (global.get $a))
;; (global $f (mut v128) (v128.const i32x4 12 13 14 15)) (global $f (mut v128) (v128.const i32x4 12 13 14 15))
;; (func (export "get-a") (result v128) (global.get $a)) (func (export "get-a") (result v128) (global.get $a))
;; (func (export "get-b") (result v128) (global.get $b)) (func (export "get-b") (result v128) (global.get $b))
;; (func (export "get-c") (result v128) (global.get $c)) (func (export "get-c") (result v128) (global.get $c))
(func (export "get-d") (result v128) (global.get $d)) (func (export "get-d") (result v128) (global.get $d))
;; (func (export "get-e") (result v128) (global.get $e)) (func (export "get-e") (result v128) (global.get $e))
;; (func (export "get-f") (result v128) (global.get $f)) (func (export "get-f") (result v128) (global.get $f))
;; (func (export "set-b") (param $value v128) (global.set $b (local.get $value))) (func (export "set-b") (param $value v128) (global.set $b (local.get $value)))
;; (func (export "set-e") (param $value v128) (global.set $e (local.get $value))) (func (export "set-e") (param $value v128) (global.set $e (local.get $value)))
;; (func (export "set-f") (param $value v128) (global.set $f (local.get $value))) (func (export "set-f") (param $value v128) (global.set $f (local.get $value)))
) )
;;(assert_return (invoke "get-a") (v128.const f32x4 0.0 1.0 2.0 3.0)) (assert_return (invoke "get-a") (v128.const f32x4 0.0 1.0 2.0 3.0))
;;(assert_return (invoke "get-b") (v128.const f32x4 4.0 5.0 6.0 7.0)) (assert_return (invoke "get-b") (v128.const f32x4 4.0 5.0 6.0 7.0))
;;(assert_return (invoke "get-c") (v128.const f32x4 0.0 1.0 2.0 3.0)) (assert_return (invoke "get-c") (v128.const f32x4 0.0 1.0 2.0 3.0))
(assert_return (invoke "get-d") (v128.const i32x4 8 9 10 11)) (assert_return (invoke "get-d") (v128.const i32x4 8 9 10 11))
;;(assert_return (invoke "get-e") (v128.const f32x4 0.0 1.0 2.0 3.0)) (assert_return (invoke "get-e") (v128.const f32x4 0.0 1.0 2.0 3.0))
;;(assert_return (invoke "get-f") (v128.const i32x4 12 13 14 15)) (assert_return (invoke "get-f") (v128.const i32x4 12 13 14 15))
;;(invoke "set-b" (v128.const f64x2 nan:0x1 nan:0x2)) (invoke "set-b" (v128.const f64x2 nan:0x1 nan:0x2))
;;(assert_return (invoke "get-b") (v128.const f64x2 nan:0x1 nan:0x2)) (assert_return (invoke "get-b") (v128.const f64x2 nan:0x1 nan:0x2))
;;
;;(invoke "set-e" (v128.const f64x2 -nan:0x3 +inf)) (invoke "set-e" (v128.const f64x2 -nan:0x3 +inf))
;;(assert_return (invoke "get-e") (v128.const f64x2 -nan:0x3 +inf)) (assert_return (invoke "get-e") (v128.const f64x2 -nan:0x3 +inf))
;;
;;(invoke "set-f" (v128.const f32x4 -inf +3.14 10.0e30 +nan:0x42)) (invoke "set-f" (v128.const f32x4 -inf +3.14 10.0e30 +nan:0x42))
;;(assert_return (invoke "get-f") (v128.const f32x4 -inf +3.14 10.0e30 +nan:0x42)) (assert_return (invoke "get-f") (v128.const f32x4 -inf +3.14 10.0e30 +nan:0x42))
(assert_invalid (module (global v128 (i32.const 0))) "invalid initializer expression") (assert_invalid (module (global v128 (i32.const 0))) "invalid initializer expression")
(assert_invalid (module (global v128 (i64.const 0))) "invalid initializer expression") (assert_invalid (module (global v128 (i64.const 0))) "invalid initializer expression")

View File

@ -17,7 +17,7 @@ wasmer-llvm-backend = { path = "../llvm-backend", version = "0.6.0", optional =
[build-dependencies] [build-dependencies]
glob = "0.2.11" glob = "0.3.0"
[dev-dependencies] [dev-dependencies]
wasmer-clif-backend = { path = "../clif-backend", version = "0.6.0" } wasmer-clif-backend = { path = "../clif-backend", version = "0.6.0" }

View File

@ -9,13 +9,12 @@ edition = "2018"
[dependencies] [dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" }
libc = "0.2.50" libc = "0.2.60"
rand = "0.6.5" rand = "0.7.0"
# wasmer-runtime-abi = { path = "../runtime-abi" } # wasmer-runtime-abi = { path = "../runtime-abi" }
hashbrown = "0.1.8"
generational-arena = "0.2.2" generational-arena = "0.2.2"
log = "0.4.6" log = "0.4.8"
byteorder = "1.3.1" byteorder = "1.3.2"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = "0.3" winapi = "0.3.7"

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#[cfg(target = "windows")] #[cfg(target = "windows")]
extern crate winapi; extern crate winapi;

View File

@ -8,7 +8,7 @@
use crate::syscalls::types::*; use crate::syscalls::types::*;
use generational_arena::Arena; use generational_arena::Arena;
pub use generational_arena::Index as Inode; pub use generational_arena::Index as Inode;
use hashbrown::hash_map::HashMap; use std::collections::HashMap;
use std::{ use std::{
borrow::Borrow, borrow::Borrow,
cell::Cell, cell::Cell,

View File

@ -9,10 +9,10 @@ edition = "2018"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" } wasmer-runtime-core = { path = "../runtime-core", version = "0.6.0" }
winapi = { version = "0.3", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] } winapi = { version = "0.3.7", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] }
libc = "0.2.49" libc = "0.2.60"
[build-dependencies] [build-dependencies]
cmake = "0.1.35" cmake = "0.1.40"
bindgen = "0.46.0" bindgen = "0.51.0"
regex = "1.0.6" regex = "1.2.0"

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#[cfg(windows)] #[cfg(windows)]
mod exception_handling; mod exception_handling;

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
extern crate byteorder; extern crate byteorder;
extern crate structopt; extern crate structopt;

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
extern crate structopt; extern crate structopt;
use std::env; use std::env;
@ -10,7 +15,7 @@ use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use std::str::FromStr; use std::str::FromStr;
use hashbrown::HashMap; use std::collections::HashMap;
use structopt::StructOpt; use structopt::StructOpt;
use wasmer::*; use wasmer::*;

View File

@ -1,5 +1,10 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] #![deny(
dead_code,
unused_imports,
unused_variables,
unused_unsafe,
unreachable_patterns
)]
#[macro_use] #[macro_use]
extern crate wasmer_runtime_core; extern crate wasmer_runtime_core;
// extern crate wasmer_emscripten; // extern crate wasmer_emscripten;