Merge branch 'master' into native-engine

# Conflicts:
#	Cargo.lock
This commit is contained in:
Syrus
2020-05-19 13:45:39 -07:00
24 changed files with 3536 additions and 3328 deletions

View File

@@ -45,6 +45,12 @@ jobs:
toolchain: ${{ matrix.rust }}
override: true
- run: cargo test --release
- name: Set up dependencies for Mac OS
run: brew install automake
if: matrix.os == 'macos-latest'
- name: Set up dependencies for Windows
run: choco install llvm
if: matrix.os == 'windows-latest'
- name: Build and Test C API
run: |
make capi

192
Cargo.lock generated
View File

@@ -1,5 +1,11 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "abort_on_panic"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955f37ac58af2416bac687c8ab66a4ccba282229bd7422a28d2281a5e66a6116"
[[package]]
name = "ahash"
version = "0.3.2"
@@ -97,6 +103,30 @@ dependencies = [
"serde",
]
[[package]]
name = "bindgen"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57"
dependencies = [
"bitflags",
"cexpr",
"cfg-if",
"clang-sys",
"clap",
"env_logger",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bitflags"
version = "1.2.1"
@@ -162,12 +192,32 @@ version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
[[package]]
name = "cexpr"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clang-sys"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
dependencies = [
"glob",
"libc",
"libloading 0.5.2",
]
[[package]]
name = "clap"
version = "2.33.0"
@@ -452,6 +502,19 @@ dependencies = [
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "erased-serde"
version = "0.3.11"
@@ -601,6 +664,15 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@@ -684,6 +756,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
[[package]]
name = "leb128"
version = "0.2.4"
@@ -696,6 +774,39 @@ version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
[[package]]
name = "libffi"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c18efe55925cc7f83bf60a61394696a734ae90e668d1f2bbd954354416fec6f2"
dependencies = [
"abort_on_panic",
"libc",
"libffi-sys",
]
[[package]]
name = "libffi-sys"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f00e48ce437c5741a4da3b51738498343b5158c37bfa02bcb969efcc44e4e06"
dependencies = [
"bindgen",
"cc",
"make-cmd",
"pkg-config",
]
[[package]]
name = "libloading"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
dependencies = [
"cc",
"winapi",
]
[[package]]
name = "libloading"
version = "0.6.2"
@@ -745,6 +856,12 @@ dependencies = [
"libc",
]
[[package]]
name = "make-cmd"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3"
[[package]]
name = "maybe-uninit"
version = "2.0.0"
@@ -796,6 +913,16 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
dependencies = [
"memchr",
"version_check 0.1.5",
]
[[package]]
name = "num"
version = "0.1.42"
@@ -896,6 +1023,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pkg-config"
version = "0.3.17"
@@ -924,7 +1057,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"version_check",
"version_check 0.9.1",
]
[[package]]
@@ -937,7 +1070,7 @@ dependencies = [
"quote",
"syn",
"syn-mid",
"version_check",
"version_check 0.9.1",
]
[[package]]
@@ -949,6 +1082,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.3"
@@ -1206,6 +1345,12 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.2.3"
@@ -1326,6 +1471,12 @@ dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "smallvec"
version = "1.4.0"
@@ -1431,6 +1582,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
dependencies = [
"winapi-util",
]
[[package]]
name = "test-generator"
version = "0.1.0"
@@ -1592,6 +1752,12 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]]
name = "version_check"
version = "0.9.1"
@@ -1795,7 +1961,7 @@ dependencies = [
"cfg-if",
"faerie",
"leb128",
"libloading",
"libloading 0.6.2",
"serde",
"serde_bytes",
"tempfile",
@@ -1830,6 +1996,8 @@ dependencies = [
"cbindgen",
"lazy_static",
"libc",
"libffi",
"wasm-common",
"wasmer",
"wasmer-wasi",
]
@@ -1898,6 +2066,15 @@ dependencies = [
"wast",
]
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
dependencies = [
"libc",
]
[[package]]
name = "winapi"
version = "0.3.8"
@@ -1914,6 +2091,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@@ -1,8 +1,8 @@
# Wasmer [![Build Status](https://img.shields.io/azure-devops/build/wasmerio/wasmer/3.svg?style=flat-square)](https://dev.azure.com/wasmerio/wasmer/_build/latest?definitionId=3&branchName=master) [![Join Wasmer Slack](https://img.shields.io/static/v1?label=Slack&message=join%20chat&color=brighgreen&style=flat-square)](https://slack.wasmer.io) [![MIT License](https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square)](https://github.com/wasmerio/wasmer/blob/master/LICENSE)
[`Wasmer`](https://wasmer.io/) is the most popular [WebAssembly](https://webassembly.org/)
runtime for Rust. It supports JIT (Just in Time) and AOT (Ahead of time)
compilation as well as mulitple compiler implementations.
runtime for Rust (...and also [the fastest]()!). It supports JIT (Just in Time) and AOT (Ahead of time)
compilation as well as pluggable compilers suited to your needs.
It's designed to be safe and secure, and runnable in any kind of environment.

View File

@@ -543,8 +543,8 @@ impl Function {
VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithoutEnv {
func: Box::new(func),
});
let address = std::ptr::null() as *const () as *const VMFunctionBody;
let vmctx = Box::leak(Box::new(dynamic_ctx)) as *mut _ as *mut VMContext;
let address = std::ptr::null() as *const VMFunctionBody;
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
let signature = store.engine().register_signature(&ty);
Self {
store: store.clone(),
@@ -569,8 +569,8 @@ impl Function {
env,
func: Box::new(func),
});
let address = std::ptr::null() as *const () as *const VMFunctionBody;
let vmctx = Box::leak(Box::new(dynamic_ctx)) as *mut _ as *mut VMContext;
let address = std::ptr::null() as *const VMFunctionBody;
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
let signature = store.engine().register_signature(&ty);
Self {
store: store.clone(),

View File

@@ -34,7 +34,7 @@ pub use wasmer_compiler::{Features, Target};
pub use wasmer_engine::{
DeserializeError, Engine, InstantiationError, LinkError, RuntimeError, SerializeError,
};
pub use wasmer_runtime::MemoryError;
pub use wasmer_runtime::{raise_user_trap, MemoryError};
// The compilers are mutually exclusive
#[cfg(any(

View File

@@ -326,11 +326,11 @@ impl Module {
&self.store
}
// The ABI of the ModuleInfo is very unstable, we refactor it very often.
// This funciton is public because in some cases it can be useful to get some
// extra information from the module.
//
// However, the usage is highly discouraged.
/// The ABI of the ModuleInfo is very unstable, we refactor it very often.
/// This funciton is public because in some cases it can be useful to get some
/// extra information from the module.
///
/// However, the usage is highly discouraged.
#[doc(hidden)]
pub fn info(&self) -> &ModuleInfo {
&self.compiled.module()

View File

@@ -17,6 +17,7 @@ crate-type = ["cdylib", "staticlib"]
[dependencies]
lazy_static = "1"
libc = { version = "0.2.70", default-features = false }
libffi = { version = "0.9" }
# for generating code in the same way thot the wasm-c-api does
# Commented out for now until we can find a solution to the exported function problem
# wasmer-wasm-c-api = { version = "0.16.2", path = "crates/wasm-c-api" }
@@ -27,6 +28,11 @@ features = ["compiler", "engine", "jit", "cranelift"]
path = "../api"
version = "0.16.2"
[dependencies.wasm-common]
default-features = false
path = "../wasm-common"
version = "0.16.2"
[dependencies.wasmer-wasi]
default-features = false
path = "../wasi"

View File

@@ -5,6 +5,7 @@ use crate::{
error::{update_last_error, CApiError},
global::wasmer_global_t,
import::wasmer_import_func_t,
instance::CAPIInstance,
memory::wasmer_memory_t,
module::wasmer_module_t,
table::wasmer_table_t,
@@ -14,7 +15,7 @@ use crate::{
use libc::{c_int, c_uint};
use std::ptr::{self, NonNull};
use std::slice;
use wasmer::{ExportType, ExternType, Function, ImportType, Instance, Memory, Module, Val};
use wasmer::{ExportType, ExternType, Function, ImportType, Memory, Module, Val};
/// Intermediate representation of an `Export` instance that is
/// exposed to C.
@@ -23,7 +24,7 @@ pub(crate) struct NamedExport {
pub(crate) export_type: ExportType,
/// The instance that holds the export.
pub(crate) instance: NonNull<Instance>,
pub(crate) instance: NonNull<CAPIInstance>,
}
/// Opaque pointer to `ImportType`.
@@ -403,6 +404,7 @@ pub unsafe extern "C" fn wasmer_export_to_memory(
let instance = named_export.instance.as_ref();
if let Ok(exported_memory) = instance
.instance
.exports
.get::<Memory>(&named_export.export_type.name())
{
@@ -477,7 +479,11 @@ pub unsafe extern "C" fn wasmer_export_func_call(
let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize);
let instance = named_export.instance.as_ref();
let f: &Function = match instance.exports.get(&named_export.export_type.name()) {
let f: &Function = match instance
.instance
.exports
.get(&named_export.export_type.name())
{
Ok(f) => f,
Err(err) => {
update_last_error(err);

View File

@@ -1,7 +1,11 @@
//! Functions and types for dealing with Emscripten imports
use super::*;
use crate::{get_slice_checked, instance::wasmer_instance_t, module::wasmer_module_t};
use crate::{
get_slice_checked,
instance::{wasmer_instance_t, CAPIInstance},
module::wasmer_module_t,
};
use std::ptr;
use wasmer::wasm::{Instance, Module};
@@ -54,16 +58,16 @@ pub unsafe extern "C" fn wasmer_emscripten_set_up(
if globals.is_null() || instance.is_null() {
return wasmer_result_t::WASMER_ERROR;
}
let instance = &mut *(instance as *mut Instance);
let instance = &mut *(instance as *mut CAPIInstance);
let globals = &*(globals as *mut EmscriptenGlobals);
let em_data = Box::into_raw(Box::new(EmscriptenData::new(
instance,
instance.instance,
&globals.data,
Default::default(),
))) as *mut c_void;
instance.context_mut().data = em_data;
match wasmer_emscripten::set_up_emscripten(instance) {
match wasmer_emscripten::set_up_emscripten(instance.instance) {
Ok(_) => wasmer_result_t::WASMER_OK,
Err(e) => {
update_last_error(e);
@@ -90,7 +94,7 @@ pub unsafe extern "C" fn wasmer_emscripten_call_main(
if instance.is_null() || args.is_null() {
return wasmer_result_t::WASMER_ERROR;
}
let instance = &mut *(instance as *mut Instance);
let instance = &mut *(instance as *mut CAPIInstance);
let arg_list = get_slice_checked(args, args_len as usize);
let arg_process_result: Result<Vec<&str>, _> =
@@ -113,7 +117,7 @@ pub unsafe extern "C" fn wasmer_emscripten_call_main(
return wasmer_result_t::WASMER_ERROR;
};
match wasmer_emscripten::emscripten_call_main(instance, prog_name, &arg_vec[1..]) {
match wasmer_emscripten::emscripten_call_main(instance.instance, prog_name, &arg_vec[1..]) {
Ok(_) => wasmer_result_t::WASMER_OK,
Err(e) => {
update_last_error(e);

View File

@@ -4,22 +4,23 @@
use crate::{
error::{update_last_error, CApiError},
export::{wasmer_import_export_kind, wasmer_import_export_value},
instance::wasmer_instance_context_t,
instance::{wasmer_instance_context_t, CAPIInstance},
module::wasmer_module_t,
value::wasmer_value_tag,
wasmer_byte_array, wasmer_result_t,
};
use libc::c_uint;
use std::ptr::NonNull;
use std::ptr::{self, NonNull};
use std::{
//convert::TryFrom,
ffi::c_void,
ffi::{c_void, CStr},
os::raw::c_char,
slice,
//sync::Arc,
};
use wasmer::{
Function, Global, ImportObject, ImportObjectIterator, ImportType, Memory, Module, Table,
Function, FunctionType, Global, ImportObject, ImportObjectIterator, ImportType, Memory, Module,
RuntimeError, Table, Val, ValType,
};
//use wasmer::wasm::{Export, FuncSig, Global, Memory, Module, Table, Type};
/*use wasmer_runtime_core::{
@@ -440,7 +441,9 @@ pub unsafe extern "C" fn wasmer_import_object_extend(
Extern::Memory((&*mem).clone())
}
wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Function;
// TODO: investigate consistent usage of `FunctionWrapper` in this context
let func_wrapper = import.value.func as *mut FunctionWrapper;
let func_export = func_wrapper.func.as_ptr();
Extern::Function((&*func_export).clone())
}
wasmer_import_export_kind::WASM_GLOBAL => {
@@ -589,6 +592,29 @@ pub unsafe extern "C" fn wasmer_import_func_params_arity(
*/
}
/// struct used to pass in context to functions (which must be back-patched)
#[derive(Debug, Default)]
pub(crate) struct LegacyEnv {
pub(crate) instance_ptr: Option<NonNull<CAPIInstance>>,
}
impl LegacyEnv {
pub(crate) fn ctx_ptr(&self) -> *mut CAPIInstance {
self.instance_ptr
.map(|p| p.as_ptr())
.unwrap_or(ptr::null_mut())
}
}
/// struct used to hold on to `LegacyEnv` pointer as well as the function.
/// we need to do this to initialize the context ptr inside of `LegacyEnv` when
/// instantiating the module.
#[derive(Debug)]
pub(crate) struct FunctionWrapper {
pub(crate) func: NonNull<Function>,
pub(crate) legacy_env: NonNull<LegacyEnv>,
}
/// Creates new host function, aka imported function. `func` is a
/// function pointer, where the first argument is the famous `vm::Ctx`
/// (in Rust), or `wasmer_instance_context_t` (in C). All arguments
@@ -615,20 +641,61 @@ pub unsafe extern "C" fn wasmer_import_func_new(
returns: *const wasmer_value_tag,
returns_len: c_uint,
) -> *mut wasmer_import_func_t {
unimplemented!("`wasmer_import_func_new` cannot be implemented yet")
/*
let params: &[wasmer_value_tag] = slice::from_raw_parts(params, params_len as usize);
let params: Vec<Type> = params.iter().cloned().map(|x| x.into()).collect();
let params: Vec<ValType> = params.iter().cloned().map(|x| x.into()).collect();
let returns: &[wasmer_value_tag] = slice::from_raw_parts(returns, returns_len as usize);
let returns: Vec<Type> = returns.iter().cloned().map(|x| x.into()).collect();
let returns: Vec<ValType> = returns.iter().cloned().map(|x| x.into()).collect();
let func_type = FunctionType::new(params, &returns[..]);
let export = Box::new(Extern::Function {
func: FuncPointer::new(func as _),
ctx: Context::Internal,
signature: Arc::new(FuncSig::new(params, returns)),
let store = crate::get_global_store();
let env_ptr = Box::into_raw(Box::new(LegacyEnv::default()));
let func = Function::new_dynamic_env(store, &func_type, &mut *env_ptr, move |env, args| {
use libffi::high::call::{call, Arg};
use libffi::low::CodePtr;
let ctx_ptr = env.ctx_ptr();
let ctx_ptr_val = ctx_ptr as *const _ as isize as i64;
let ffi_args: Vec<Arg> = {
let mut ffi_args = Vec::with_capacity(args.len() + 1);
ffi_args.push(Arg::new::<i64>(&ctx_ptr_val));
ffi_args.extend(args.iter().map(|ty| match ty {
Val::I32(v) => Arg::new::<i32>(v),
Val::I64(v) => Arg::new::<i64>(v),
Val::F32(v) => Arg::new::<f32>(v),
Val::F64(v) => Arg::new::<f64>(v),
_ => todo!("Unsupported type in C API"),
}));
ffi_args
};
let code_ptr = CodePtr::from_ptr(func as _);
assert!(returns.len() <= 1);
let return_value = if returns.len() == 1 {
vec![match returns[0] {
ValType::I32 => Val::I32(call::<i32>(code_ptr, &ffi_args)),
ValType::I64 => Val::I64(call::<i64>(code_ptr, &ffi_args)),
ValType::F32 => Val::F32(call::<f32>(code_ptr, &ffi_args)),
ValType::F64 => Val::F64(call::<f64>(code_ptr, &ffi_args)),
_ => todo!("Unsupported type in C API"),
}]
} else {
call::<()>(code_ptr, &ffi_args);
vec![]
};
Ok(return_value)
});
Box::into_raw(export) as *mut wasmer_import_func_t
*/
let function_wrapper = FunctionWrapper {
func: NonNull::new_unchecked(Box::into_raw(Box::new(func))),
legacy_env: NonNull::new_unchecked(env_ptr),
};
Box::into_raw(Box::new(function_wrapper)) as *mut wasmer_import_func_t
}
/// Stop the execution of a host function, aka imported function. The
@@ -648,19 +715,9 @@ pub unsafe extern "C" fn wasmer_import_func_new(
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trap(
ctx: *const wasmer_instance_context_t,
_ctx: *const wasmer_instance_context_t,
error_message: *const c_char,
) -> wasmer_result_t {
todo!("wasmer_trap: manually trap without Ctx")
/*
if ctx.is_null() {
update_last_error(CApiError {
msg: "ctx ptr is null in wasmer_trap".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
}
if error_message.is_null() {
update_last_error(CApiError {
msg: "error_message is null in wasmer_trap".to_string(),
@@ -669,12 +726,9 @@ pub unsafe extern "C" fn wasmer_trap(
return wasmer_result_t::WASMER_ERROR;
}
let ctx = &*(ctx as *const Ctx);
let error_message = CStr::from_ptr(error_message).to_str().unwrap();
(&*ctx.module)
.runnable_module
.do_early_trap(Box::new(error_message)); // never returns
wasmer::raise_user_trap(Box::new(RuntimeError::new(error_message))); // never returns
// cbindgen does not generate a binding for a function that
// returns `!`. Since we also need to error in some cases, the
@@ -684,7 +738,6 @@ pub unsafe extern "C" fn wasmer_trap(
// cbindgen, and get an acceptable clean code.
#[allow(unreachable_code)]
wasmer_result_t::WASMER_OK
*/
}
/// Sets the params buffer to the parameter types of the given wasmer_import_func_t
@@ -769,7 +822,9 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity(
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_func_destroy(func: Option<NonNull<wasmer_import_func_t>>) {
if let Some(func) = func {
Box::from_raw(func.cast::<Function>().as_ptr());
let function_wrapper = Box::from_raw(func.cast::<FunctionWrapper>().as_ptr());
let _legacy_env = Box::from_raw(function_wrapper.legacy_env.as_ptr());
let _function = Box::from_raw(function_wrapper.func.as_ptr());
}
}

View File

@@ -3,7 +3,7 @@
use crate::{
error::{update_last_error, CApiError},
export::{wasmer_exports_t, wasmer_import_export_kind, NamedExport, NamedExports},
import::wasmer_import_t,
import::{wasmer_import_t, FunctionWrapper},
memory::wasmer_memory_t,
value::{wasmer_value, wasmer_value_t, wasmer_value_tag},
wasmer_result_t,
@@ -13,18 +13,34 @@ use std::collections::HashMap;
use std::ffi::CStr;
use std::ptr::NonNull;
use std::slice;
use wasm_common::{entity::*, ExportIndex, MemoryIndex};
use wasmer::{
Exports, Extern, Function, Global, ImportObject, Instance, Memory, Module, Table, Val,
};
/// Opaque pointer to a `wasmer_runtime::Instance` value in Rust.
/// Opaque pointer to an Instance type plus metadata.
///
/// A `wasmer_runtime::Instance` represents a WebAssembly instance. It
/// This type represents a WebAssembly instance. It
/// is generally generated by the `wasmer_instantiate()` function, or by
/// the `wasmer_module_instantiate()` function for the most common paths.
#[repr(C)]
pub struct wasmer_instance_t;
/// A wrapper around a Wasmer instance with extra data to maintain the existing API
pub(crate) struct CAPIInstance {
/// The real wasmer `Instance`
pub(crate) instance: Instance,
/// List of pointers of memories that are imported into this Instance. This is
/// required because the old Wasmer API allowed accessing these from the Instance
/// but the new/current API does not. So we store them here to allow functions to
/// access this data for backwards compatibilty.
pub(crate) imported_memories: Vec<*mut Memory>,
/// The Instance/Ctx wide data. Previously the Ctx Instance were separate, but
/// given the internal API changes this is no longer true: this is a single global
/// void pointer like the old Wasmer API used to have.
pub(crate) ctx_data: Option<NonNull<c_void>>,
}
/// Opaque pointer to a `wasmer_runtime::Ctx` value in Rust.
///
/// An instance context is passed to any host function (aka imported
@@ -112,6 +128,8 @@ pub unsafe extern "C" fn wasmer_instantiate(
});
return wasmer_result_t::WASMER_ERROR;
};
let mut imported_memories = vec![];
let mut instance_pointers_to_update = vec![];
let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
let mut import_object = ImportObject::new();
let mut namespaces = HashMap::new();
@@ -147,10 +165,14 @@ pub unsafe extern "C" fn wasmer_instantiate(
let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory;
// TODO: review ownership here, probably need to clone Memory for imported_meomries
imported_memories.push(mem);
Extern::Memory((&*mem).clone())
}
wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Function;
let func_wrapper = import.value.func as *mut FunctionWrapper;
let func_export = (*func_wrapper).func.as_ptr();
instance_pointers_to_update.push((*func_wrapper).legacy_env);
Extern::Function((&*func_export).clone())
}
wasmer_import_export_kind::WASM_GLOBAL => {
@@ -187,7 +209,16 @@ pub unsafe extern "C" fn wasmer_instantiate(
return wasmer_result_t::WASMER_ERROR;
}
};
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
let c_api_instance = CAPIInstance {
instance: new_instance,
imported_memories,
ctx_data: None,
};
let c_api_instance_pointer = Box::into_raw(Box::new(c_api_instance));
for mut to_update in instance_pointers_to_update {
to_update.as_mut().instance_ptr = Some(NonNull::new_unchecked(c_api_instance_pointer));
}
*instance = c_api_instance_pointer as *mut wasmer_instance_t;
wasmer_result_t::WASMER_OK
}
@@ -207,16 +238,13 @@ pub unsafe extern "C" fn wasmer_instantiate(
/// It is often useful with `wasmer_instance_context_data_set()`.
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_instance_context_get(
pub unsafe extern "C" fn wasmer_instance_context_get(
instance: Option<NonNull<wasmer_instance_t>>,
) -> Option<&'static wasmer_instance_context_t> {
unimplemented!("wasmer_instance_context_get: API changed")
/*
let instance = instance?.as_ref();
let context: *const Ctx = instance.context() as *const _;
// TODO: double check that `wasmer_instance_t` can be safely cast into CAPIInstance
let instance: *mut CAPIInstance = instance?.cast::<CAPIInstance>().as_ptr();
context as *const wasmer_instance_context_t
*/
Some(&*(instance as *const wasmer_instance_context_t))
}
/// Calls an exported function of a WebAssembly instance by `name`
@@ -310,8 +338,8 @@ pub unsafe extern "C" fn wasmer_instance_call(
let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize);
let instance = &*(instance as *mut Instance);
let f: &Function = match instance.exports.get(func_name_r) {
let instance = &*(instance as *mut CAPIInstance);
let f: &Function = match instance.instance.exports.get(func_name_r) {
Ok(f) => f,
Err(err) => {
update_last_error(err);
@@ -405,7 +433,7 @@ pub unsafe extern "C" fn wasmer_instance_exports(
exports: *mut *mut wasmer_exports_t,
) {
let instance = if let Some(instance) = instance {
instance.cast::<Instance>()
instance.cast::<CAPIInstance>()
} else {
return;
};
@@ -414,6 +442,7 @@ pub unsafe extern "C" fn wasmer_instance_exports(
let instance_ref = instance_ref_copy.as_mut();
let exports_vec: Vec<NamedExport> = instance_ref
.instance
.module()
.exports()
.map(|export_type| NamedExport {
@@ -457,22 +486,17 @@ pub unsafe extern "C" fn wasmer_instance_exports(
/// ```
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_instance_context_data_set(
instance: *mut wasmer_instance_t,
pub unsafe extern "C" fn wasmer_instance_context_data_set(
instance: Option<NonNull<wasmer_instance_t>>,
data_ptr: *mut c_void,
) {
unimplemented!(
"wasmer_instance_context_data_set: API changed in a way that this is non-obvious"
)
/*
if instance.is_null() {
let instance = if let Some(instance_inner) = instance {
instance_inner
} else {
return;
}
};
let instance = unsafe { &mut *(instance as *mut Instance) };
instance.context_mut().data = data_ptr;
*/
instance.cast::<CAPIInstance>().as_mut().ctx_data = NonNull::new(data_ptr);
}
/// Gets the `memory_idx`th memory of the instance.
@@ -498,15 +522,53 @@ pub extern "C" fn wasmer_instance_context_data_set(
/// ```
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_instance_context_memory(
pub unsafe extern "C" fn wasmer_instance_context_memory(
ctx: *const wasmer_instance_context_t,
_memory_idx: u32,
) -> *const wasmer_memory_t {
unimplemented!("wasmer_instance_context_memory: API changed")
/*let ctx = unsafe { &*(ctx as *const Ctx) };
let memory = ctx.memory(0);
memory as *const Memory as *const wasmer_memory_t
*/
) -> Option<&'static wasmer_memory_t> {
let instance = &*(ctx as *const CAPIInstance);
let module = instance.instance.module();
let memory_index = MemoryIndex::new(0);
if module.info().is_imported_memory(memory_index) {
if let Some(memory) = instance.imported_memories.first() {
let memory: &Memory = &**memory;
return Some(&*(Box::into_raw(Box::new(memory.clone())) as *const wasmer_memory_t));
} else {
update_last_error(CApiError {
msg:
"Internal error: memory is imported but the list of imported memories is empty"
.to_string(),
});
return None;
}
} else {
let exported_memory_name = if let Some(name) = module
.info()
.exports
.iter()
.filter_map(|(name, export_index)| match export_index {
ExportIndex::Memory(idx) if *idx == memory_index => Some(name),
_ => None,
})
.next()
{
name
} else {
update_last_error(CApiError {
msg: "Could not find an exported memory".to_string(),
});
return None;
};
let memory = instance
.instance
.exports
.get_memory(exported_memory_name)
.expect(&format!(
"Module exports memory named `{}` but it's inaccessible",
&exported_memory_name
));
Some(&*(Box::into_raw(Box::new(memory.clone())) as *const wasmer_memory_t))
}
}
/// Gets the data that can be hold by an instance.
@@ -519,19 +581,11 @@ pub extern "C" fn wasmer_instance_context_memory(
/// This function returns nothing if `ctx` is a null pointer.
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_instance_context_data_get(
ctx: *const wasmer_instance_context_t,
) -> *mut c_void {
unimplemented!("wasmer_instance_context_data_get: API changed")
/*
if ctx.is_null() {
return ptr::null_mut() as _;
}
let ctx = unsafe { &*(ctx as *const Ctx) };
ctx.data
*/
pub unsafe extern "C" fn wasmer_instance_context_data_get(
ctx: Option<&'static wasmer_instance_context_t>,
) -> Option<NonNull<c_void>> {
let instance: &'static CAPIInstance = &*(ctx? as *const _ as *const CAPIInstance);
instance.ctx_data
}
/// Frees memory for the given `wasmer_instance_t`.
@@ -555,6 +609,6 @@ pub extern "C" fn wasmer_instance_context_data_get(
#[no_mangle]
pub unsafe extern "C" fn wasmer_instance_destroy(instance: Option<NonNull<wasmer_instance_t>>) {
if let Some(instance_inner) = instance {
Box::from_raw(instance_inner.cast::<Instance>().as_ptr());
Box::from_raw(instance_inner.cast::<CAPIInstance>().as_ptr());
}
}

View File

@@ -4,7 +4,7 @@ use crate::{
error::{update_last_error, CApiError},
export::wasmer_import_export_kind,
import::{wasmer_import_object_t, wasmer_import_t},
instance::wasmer_instance_t,
instance::{wasmer_instance_t, CAPIInstance},
wasmer_byte_array, wasmer_result_t,
};
use libc::c_int;
@@ -86,6 +86,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
imports_len: c_int,
) -> wasmer_result_t {
let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
let mut imported_memories = vec![];
let mut import_object = ImportObject::new();
let mut namespaces = HashMap::new();
for import in imports {
@@ -119,6 +120,7 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory;
imported_memories.push(mem);
Extern::Memory((&*mem).clone())
}
wasmer_import_export_kind::WASM_FUNCTION => {
@@ -149,7 +151,13 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
}
};
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
let c_api_instance = CAPIInstance {
instance: new_instance,
imported_memories,
ctx_data: None,
};
*instance = Box::into_raw(Box::new(c_api_instance)) as *mut wasmer_instance_t;
wasmer_result_t::WASMER_OK
}
@@ -174,7 +182,13 @@ pub unsafe extern "C" fn wasmer_module_import_instantiate(
return wasmer_result_t::WASMER_ERROR;
}
};
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;
let imported_memories = todo!("get imported memories");
let c_api_instance = CAPIInstance {
instance: new_instance,
imported_memories,
ctx_data: None,
};
*instance = Box::into_raw(Box::new(c_api_instance)) as *mut wasmer_instance_t;
return wasmer_result_t::WASMER_OK;
}

View File

@@ -4,7 +4,7 @@ project (WasmerRuntimeCApiTests)
add_executable(test-exported-memory test-exported-memory.c)
add_executable(test-exports test-exports.c)
add_executable(test-globals test-globals.c)
# functionality not yet implemented in wasmer reborn
# trampoline functionality not yet implemented in wasmer reborn
#add_executable(test-import-function test-import-function.c)
add_executable(test-import-trap test-import-trap.c)
add_executable(test-imports test-imports.c)
@@ -71,20 +71,18 @@ target_link_libraries(test-globals general ${WASMER_LIB})
target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS})
add_test(test-globals test-globals)
# functionality not yet implemented in wasmer reborn
# trampoline functionality not yet implemented in wasmer reborn
#target_link_libraries(test-import-function general ${WASMER_LIB})
#target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS})
#add_test(test-import-function test-import-function)
target_link_libraries(test-import-trap general ${WASMER_LIB})
target_compile_options(test-import-trap PRIVATE ${COMPILER_OPTIONS})
# TODO: reenable this test
#add_test(test-import-trap test-import-trap)
add_test(test-import-trap test-import-trap)
target_link_libraries(test-imports general ${WASMER_LIB})
target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS})
# TODO: reenable this test
#add_test(test-imports test-imports)
add_test(test-imports test-imports)
target_link_libraries(test-import-object general ${WASMER_LIB})
target_compile_options(test-import-object PRIVATE ${COMPILER_OPTIONS})
@@ -139,8 +137,7 @@ add_test(test-validate test-validate)
target_link_libraries(test-context general ${WASMER_LIB})
target_compile_options(test-context PRIVATE ${COMPILER_OPTIONS})
# TODO: reenable this test
#add_test(test-context test-context)
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})

View File

@@ -69,7 +69,7 @@ int main()
wasmer_last_error_message(error_str, error_len);
printf("Error str: `%s`\n", error_str);
assert(0 == strcmp(error_str, "Call error: \"Hello\""));
assert(0 == strcmp(error_str, "RuntimeError: Hello"));
printf("Destroying func\n");
wasmer_import_func_destroy(func);

View File

@@ -141,6 +141,10 @@ int main()
wasmer_value_t results[] = {result_one};
wasmer_result_t call_result = wasmer_instance_call(instance, "_hello_wasm", params, 0, results, 1);
printf("Call result: %d\n", call_result);
if (compile_result != WASMER_OK)
{
print_wasmer_error();
}
assert(call_result == WASMER_OK);
assert(print_str_called);

View File

@@ -138,9 +138,9 @@ typedef struct {
} wasmer_module_t;
/**
* Opaque pointer to a `wasmer_runtime::Instance` value in Rust.
* Opaque pointer to an Instance type plus metadata.
*
* A `wasmer_runtime::Instance` represents a WebAssembly instance. It
* This type represents a WebAssembly instance. It
* is generally generated by the `wasmer_instantiate()` function, or by
* the `wasmer_module_instantiate()` function for the most common paths.
*/
@@ -1389,7 +1389,7 @@ wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits)
*
* This function never returns otherwise.
*/
wasmer_result_t wasmer_trap(const wasmer_instance_context_t *ctx, const char *error_message);
wasmer_result_t wasmer_trap(const wasmer_instance_context_t *_ctx, const char *error_message);
/**
* Validates a sequence of bytes hoping it represents a valid WebAssembly module.

View File

@@ -100,9 +100,9 @@ struct wasmer_module_t {
};
/// Opaque pointer to a `wasmer_runtime::Instance` value in Rust.
/// Opaque pointer to an Instance type plus metadata.
///
/// A `wasmer_runtime::Instance` represents a WebAssembly instance. It
/// This type represents a WebAssembly instance. It
/// is generally generated by the `wasmer_instantiate()` function, or by
/// the `wasmer_module_instantiate()` function for the most common paths.
struct wasmer_instance_t {
@@ -1148,7 +1148,7 @@ wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits)
/// `error_message` are null.
///
/// This function never returns otherwise.
wasmer_result_t wasmer_trap(const wasmer_instance_context_t *ctx, const char *error_message);
wasmer_result_t wasmer_trap(const wasmer_instance_context_t *_ctx, const char *error_message);
/// Validates a sequence of bytes hoping it represents a valid WebAssembly module.
///

View File

@@ -65,15 +65,7 @@ impl Compiler for LLVMCompiler {
//let data = Arc::new(Mutex::new(0));
let mut func_names = SecondaryMap::new();
// We're going to "link" the sections by simply appending all compatible
// sections, then building the new relocations.
// TODO: merge constants.
let mut used_readonly_section = false;
let mut readonly_section = CustomSection {
protection: CustomSectionProtection::Read,
bytes: SectionBody::default(),
relocations: vec![],
};
// TODO: merge constants in sections.
for (func_index, _) in &module.functions {
func_names[func_index] = module
@@ -153,6 +145,6 @@ impl Compiler for LLVMCompiler {
module: &Module,
) -> Result<PrimaryMap<FunctionIndex, FunctionBody>, CompileError> {
Ok(PrimaryMap::new())
// unimplemented!("Dynamic funciton trampolines not yet implemented");
// unimplemented!("Dynamic function trampolines not yet implemented");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,18 +20,6 @@ use inkwell::{
AddressSpace,
};
use std::collections::HashMap;
/*
use wasmer_runtime_core::{
memory::MemoryType,
module::ModuleInfo,
structures::TypedIndex,
types::{
GlobalIndex, ImportedFunctionIndex, LocalOrImport, MemoryIndex, SignatureIndex, TableIndex, Type,
},
units::Pages,
vm::{Ctx, INTERNALS_SIZE},
};
*/
use wasm_common::entity::{EntityRef, PrimaryMap};
use wasm_common::{
FunctionIndex, FunctionType as FuncType, GlobalIndex, MemoryIndex, Mutability, Pages,
@@ -271,65 +259,6 @@ impl<'ctx> Intrinsics<'ctx> {
false,
);
/*
ctx_ty.set_body(
&[
local_memory_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_table_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_global_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_memory_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_table_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_global_ty
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
imported_func_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
sigindex_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
rt_intrinsics_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
stack_lower_bound_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
memory_base_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
memory_bound_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
internals_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
interrupt_signal_mem_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_function_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
],
false,
);
*/
let ret_i8x16_take_i8x16_i8x16 = i8x16_ty.fn_type(&[i8x16_ty_basic, i8x16_ty_basic], false);
let ret_i16x8_take_i16x8_i16x8 = i16x8_ty.fn_type(&[i16x8_ty_basic, i16x8_ty_basic], false);
@@ -669,17 +598,10 @@ pub enum MemoryCache<'ctx> {
/// The memory moves around.
Dynamic {
ptr_to_base_ptr: PointerValue<'ctx>,
ptr_to_bounds: PointerValue<'ctx>,
minimum: Pages,
maximum: Option<Pages>,
current_length_ptr: PointerValue<'ctx>,
},
/// The memory is always in the same place.
Static {
base_ptr: PointerValue<'ctx>,
bounds: IntValue<'ctx>,
minimum: Pages,
maximum: Option<Pages>,
},
Static { base_ptr: PointerValue<'ctx> },
}
struct TableCache<'ctx> {
@@ -747,28 +669,7 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
pub fn basic(&self) -> BasicValueEnum<'ctx> {
self.ctx_ptr_value.as_basic_value_enum()
}
/*
pub fn signal_mem(&mut self) -> PointerValue<'ctx> {
if let Some(x) = self.cached_signal_mem {
return x;
}
let (ctx_ptr_value, cache_builder) = (self.ctx_ptr_value, &self.cache_builder);
let ptr_ptr = unsafe {
cache_builder.build_struct_gep(
ctx_ptr_value,
offset_to_index(Ctx::offset_interrupt_signal_mem()),
"interrupt_signal_mem_ptr",
)
};
let ptr = cache_builder
.build_load(ptr_ptr, "interrupt_signal_mem")
.into_pointer_value();
self.cached_signal_mem = Some(ptr);
ptr
}
*/
pub fn memory(
&mut self,
index: MemoryIndex,
@@ -783,129 +684,59 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
&self.cache_builder,
&self.offsets,
);
let memory_plan = &memory_plans[index];
*cached_memories.entry(index).or_insert_with(|| {
let (memory_array_ptr_ptr, index, memory_type, minimum, maximum, field_name) = {
let desc = memory_plans.get(index).unwrap();
if let Some(local_mem_index) = wasm_module.local_memory_index(index) {
let byte_offset = intrinsics.i64_ty.const_int(
offsets
.vmctx_vmmemory_definition_base(local_mem_index)
.into(),
false,
);
(
unsafe {
cache_builder.build_gep(
ctx_ptr_value,
&[byte_offset],
"memory_base_ptr_ptr",
)
},
local_mem_index.index() as u64,
desc.style.clone(),
desc.memory.minimum,
desc.memory.maximum,
"context_field_ptr_to_local_memory",
)
let memory_definition_ptr =
if let Some(local_memory_index) = wasm_module.local_memory_index(index) {
let offset = offsets.vmctx_vmmemory_definition(local_memory_index);
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
unsafe { cache_builder.build_gep(ctx_ptr_value, &[offset], "") }
} else {
let byte_offset = intrinsics.i64_ty.const_int(
offsets.vmctx_vmmemory_import_definition(index).into(),
false,
);
(
unsafe {
cache_builder
.build_struct_gep(
ctx_ptr_value,
offset_to_index(offsets.vmctx_imported_memories_begin()),
"memory_array_ptr_ptr",
let offset = offsets.vmctx_vmmemory_import(index);
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
let memory_definition_ptr_ptr =
unsafe { cache_builder.build_gep(ctx_ptr_value, &[offset], "") };
let memory_definition_ptr_ptr = cache_builder
.build_bitcast(
memory_definition_ptr_ptr,
intrinsics.i8_ptr_ty.ptr_type(AddressSpace::Generic),
"",
)
.unwrap()
},
index.index() as u64,
desc.style.clone(),
desc.memory.minimum,
desc.memory.maximum,
"context_field_ptr_to_imported_memory",
)
}
};
let memory_array_ptr = cache_builder
.build_load(memory_array_ptr_ptr, "memory_array_ptr")
.into_pointer_value();
tbaa_label(
module,
intrinsics,
field_name,
memory_array_ptr.as_instruction_value().unwrap(),
None,
);
let const_index = intrinsics.i32_ty.const_int(index, false);
let memory_ptr_ptr = unsafe {
cache_builder.build_in_bounds_gep(
memory_array_ptr,
&[const_index],
"memory_ptr_ptr",
)
cache_builder
.build_load(memory_definition_ptr_ptr, "")
.into_pointer_value()
};
let memory_ptr = cache_builder
.build_load(memory_ptr_ptr, "memory_ptr")
let memory_definition_ptr = cache_builder
.build_bitcast(
memory_definition_ptr,
intrinsics.vmmemory_definition_ptr_ty,
"",
)
.into_pointer_value();
tbaa_label(
module,
intrinsics,
"memory_ptr",
memory_ptr.as_instruction_value().unwrap(),
Some(index as u32),
);
let (ptr_to_base_ptr, ptr_to_bounds) = unsafe {
(
cache_builder
.build_struct_gep(memory_ptr, 0, "base_ptr")
.unwrap(),
cache_builder
.build_struct_gep(memory_ptr, 1, "bounds_ptr")
.unwrap(),
)
};
match memory_type {
MemoryStyle::Dynamic => MemoryCache::Dynamic {
ptr_to_base_ptr,
ptr_to_bounds,
minimum,
maximum,
},
MemoryStyle::Static { bound: _ } => {
let base_ptr = cache_builder
.build_load(ptr_to_base_ptr, "base")
.into_pointer_value();
let bounds = cache_builder
.build_load(ptr_to_bounds, "bounds")
.into_int_value();
tbaa_label(
module,
intrinsics,
"static_memory_base",
base_ptr.as_instruction_value().unwrap(),
Some(index as u32),
);
tbaa_label(
module,
intrinsics,
"static_memory_bounds",
bounds.as_instruction_value().unwrap(),
Some(index as u32),
);
MemoryCache::Static {
base_ptr,
bounds,
minimum,
maximum,
}
.build_struct_gep(
memory_definition_ptr,
intrinsics.vmmemory_definition_base_element,
"",
)
.unwrap();
if memory_plan.style == MemoryStyle::Dynamic {
let current_length_ptr = cache_builder
.build_struct_gep(
memory_definition_ptr,
intrinsics.vmmemory_definition_current_length_element,
"",
)
.unwrap();
MemoryCache::Dynamic {
ptr_to_base_ptr: base_ptr,
current_length_ptr,
}
} else {
let base_ptr = cache_builder.build_load(base_ptr, "").into_pointer_value();
// TODO: tbaa
MemoryCache::Static { base_ptr }
}
})
}
@@ -1051,27 +882,6 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
&self.offsets,
);
*cached_sigindices.entry(index).or_insert_with(|| {
/*
let sigindex_array_ptr_ptr = unsafe {
cache_builder.build_struct_gep(
ctx_ptr_value,
offset_to_index(offsets.vmctx_signature_ids_begin()),
"sigindex_array_ptr_ptr",
)
};
let sigindex_array_ptr = cache_builder
.build_load(sigindex_array_ptr_ptr, "sigindex_array_ptr")
.into_pointer_value();
let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false);
let sigindex_ptr = unsafe {
cache_builder.build_in_bounds_gep(
sigindex_array_ptr,
&[const_index],
"sigindex_ptr",
)
};
*/
let byte_offset = intrinsics
.i64_ty
.const_int(offsets.vmctx_vmshared_signature_id(index).into(), false);

View File

@@ -3,7 +3,6 @@ use inkwell::{
values::{BasicValue, BasicValueEnum, PhiValue},
};
use smallvec::SmallVec;
use std::cell::Cell;
use std::ops::{BitAnd, BitOr, BitOrAssign};
use wasmer_compiler::CompileError;
@@ -196,7 +195,6 @@ impl BitAnd for ExtraInfo {
pub struct State<'ctx> {
pub stack: Vec<(BasicValueEnum<'ctx>, ExtraInfo)>,
control_stack: Vec<ControlFrame<'ctx>>,
value_counter: Cell<usize>,
pub reachable: bool,
}
@@ -206,7 +204,6 @@ impl<'ctx> State<'ctx> {
Self {
stack: vec![],
control_stack: vec![],
value_counter: Cell::new(0),
reachable: true,
}
}
@@ -270,13 +267,6 @@ impl<'ctx> State<'ctx> {
))
}
pub fn var_name(&self) -> String {
let counter = self.value_counter.get();
let s = format!("s{}", counter);
self.value_counter.set(counter + 1);
s
}
pub fn push1<T: BasicValue<'ctx>>(&mut self, value: T) {
self.push1_extra(value, Default::default());
}

View File

@@ -74,4 +74,12 @@ impl Compiler for SinglepassCompiler {
"Singlepass trampoline compilation not supported yet".to_owned(),
))
}
fn compile_dynamic_function_trampolines(
&self,
module: &Module,
) -> Result<PrimaryMap<FunctionIndex, FunctionBody>, CompileError> {
Ok(PrimaryMap::new())
// unimplemented!("Dynamic function trampolines not yet implemented");
}
}

View File

@@ -4,7 +4,7 @@ use crate::x64_decl::{new_machine_state, X64Register};
use smallvec::smallvec;
use smallvec::SmallVec;
use std::collections::HashSet;
use wasmparser::Type as WpType;
use wasmer_compiler::wasmparser::Type as WpType;
struct MachineStackOffset(usize);

View File

@@ -29,8 +29,8 @@ pub struct TableElements {
pub elements: Box<[FunctionIndex]>,
}
/// Implemenation styles for WebAssembly linear memory.
#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
/// Implementation styles for WebAssembly linear memory.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MemoryStyle {
/// The actual memory can be resized and moved.
Dynamic,
@@ -53,7 +53,7 @@ pub struct MemoryPlan {
pub offset_guard_size: u64,
}
/// Implemenation styles for WebAssembly tables.
/// Implementation styles for WebAssembly tables.
#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
pub enum TableStyle {
/// Signatures are stored in the table and checked in the caller.