WIP: just got result from greeting(but with second unexpected output)

This commit is contained in:
Valery Antopol 2021-11-08 10:15:12 +03:00
parent 1efd1413d7
commit 611d024b23
16 changed files with 802 additions and 350 deletions

573
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,5 +11,5 @@ name = "marine_it_interfaces"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.2" } wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.1", path = "../../../interface-types/wasmer-it" }
multimap = "0.8.1" multimap = "0.8.1"

View File

@ -17,7 +17,7 @@ marine-module-interface = { path = "../module-interface", version = "0.1.6" }
anyhow = "1.0.31" anyhow = "1.0.31"
walrus = "0.18.0" walrus = "0.18.0"
wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1"} wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1"}
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.2" } wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.1", path = "../../../interface-types/wasmer-it" }
nom = "5.1" nom = "5.1"
itertools = "0.10.0" itertools = "0.10.0"

View File

@ -16,7 +16,7 @@ marine-it-interfaces = { path = "../it-interfaces", version = "0.4.1" }
anyhow = "1.0.31" anyhow = "1.0.31"
walrus = "0.18.0" walrus = "0.18.0"
wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1"} wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1"}
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.2" } wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.1", path = "../../../interface-types/wasmer-it" }
nom = "5.1" nom = "5.1"
itertools = "0.10.0" itertools = "0.10.0"

View File

@ -23,7 +23,9 @@ marine-utils = { path = "../crates/utils", version = "0.2.0" }
#wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" } #wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
# dynamicfunc-fat-closures allows using state inside DynamicFunc # dynamicfunc-fat-closures allows using state inside DynamicFunc
#wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] } #wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] }
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.2" } #wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.2" }
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.1", path = "../../interface-types/wasmer-it" }
it-utils = { path = "../../interface-types/crates/utils", version = "0.1.0" }
it-lilo = "0.1.0" it-lilo = "0.1.0"
#wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.1" } #wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.1" }
@ -34,6 +36,7 @@ boolinator = "2.4.0"
once_cell = "1.7.2" once_cell = "1.7.2"
semver = "0.11.0" semver = "0.11.0"
serde = "1.0.118" serde = "1.0.118"
serde_json = "1.0.68"
log = "0.4.8" log = "0.4.8"
paste = "1.0.5" paste = "1.0.5"

View File

@ -5,11 +5,13 @@
<title>hello-wasm example</title> <title>hello-wasm example</title>
</head> </head>
<body> <body>
<script type="module"> <script type="module" src="index.js">
import init, {greet} from "./pkg/marine_web_runtime.js"; import init, {greet, test_read_memory, test_write_memory} from "./pkg/marine_web_runtime.js";
init() init()
.then(() => { .then(() => {
greet("WebAssembly") greet("WebAssembly 2");
test_read_memory();
test_write_memory();
}); });
</script> </script>
</body> </body>

View File

@ -1,5 +1,31 @@
export function call_export(module_name, export_name) { export function call_export(module_name, export_name, args) {
window.MARINE_WASM_MODULES[module_name].exports[export_name]() console.log("JS: call_export called with: ", module_name, export_name, args)
let parsed_args = JSON.parse(args);
console.log("parsed args: ", args);
let prepared_args = [];
for (let i = 0; i < parsed_args.length; i++) {
let arg = parsed_args[i];
console.log(arg)
prepared_args.push(arg["I32"])
}
console.log("prepared args: ", prepared_args);
let result = window.MARINE_WASM_MODULES[module_name].exports[export_name](...prepared_args);
console.log("got result: ", result)
let json_string = "[]";
if (result !== undefined) {
json_string = "[" + JSON.stringify(result) + "]"
}
console.log("got result_string: ", json_string)
return json_string
}
export function get_memory_size(module_name) {
console.log("called get_memory_size with name=", module_name);
let buf = new Uint8Array(window.MARINE_WASM_MODULES[module_name].exports.memory.buffer);
console.log("result=", buf.byteLength);
return buf.byteLength
} }
export function write_memory(module_name, offset, bytes) { export function write_memory(module_name, offset, bytes) {
@ -8,4 +34,19 @@ export function write_memory(module_name, offset, bytes) {
export function read_memory(module_name, offset, size) { export function read_memory(module_name, offset, size) {
}
export function write_byte(module_name, offset, value) {
console.log("write_byte called with args: module_name={}, offset={}, value={}", module_name, offset, value)
let buf = new Uint8Array(window.MARINE_WASM_MODULES[module_name].exports.memory.buffer);
console.log(buf)
buf[offset] = value
}
export function read_byte(module_name, offset) {
console.log("read_byte called with args: module_name={}, offset={}", module_name, offset)
let buf = new Uint8Array(window.MARINE_WASM_MODULES[module_name].exports.memory.buffer);
console.log(buf)
console.log("read_byte returns {}", buf[offset])
return buf[offset];
} }

View File

@ -34,6 +34,7 @@ use wasmer_it::ast::{Interfaces, FunctionArg};
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
#[allow(unused)] #[allow(unused)]
use wasmer_it::interpreter::wasm::structures::{LocalImport, Export,Memory,MemoryView}; use wasmer_it::interpreter::wasm::structures::{LocalImport, Export,Memory,MemoryView};
use module::MModule;
pub(crate) mod marine_js; pub(crate) mod marine_js;
@ -76,6 +77,8 @@ pub(crate) type MResult<T> = std::result::Result<T, MError>;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::str::FromStr; use std::str::FromStr;
use crate::module::type_converters::ival_to_string;
static MINIMAL_SUPPORTED_SDK_VERSION: Lazy<semver::Version> = Lazy::new(|| { static MINIMAL_SUPPORTED_SDK_VERSION: Lazy<semver::Version> = Lazy::new(|| {
semver::Version::from_str("0.6.0").expect("invalid minimal sdk version specified") semver::Version::from_str("0.6.0").expect("invalid minimal sdk version specified")
}); });
@ -102,35 +105,8 @@ pub struct JsLocalImport {
} }
impl LocalImport for JsLocalImport {
fn name(&self) -> &str {
todo!()
}
fn inputs_cardinality(&self) -> usize {
todo!()
}
fn outputs_cardinality(&self) -> usize {
todo!()
}
fn arguments(&self) -> &[FunctionArg] {
todo!()
}
fn outputs(&self) -> &[IType] {
todo!()
}
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
//call_export(self.module_name, self.name())
Err(())
}
}
struct JsExport { struct JsExport {
name: String, //name: String,
} }
@ -155,7 +131,7 @@ impl Export for JsExport {
todo!() todo!()
} }
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()> { fn call(&self, _arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
todo!() todo!()
} }
} }
@ -173,6 +149,10 @@ extern "C" {
fn log(s: &str); fn log(s: &str);
} }
pub fn js_log(s: &str) {
log(s)
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn greet(name: &str) { pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name)); alert(&format!("Hello, {}!", name));
@ -180,17 +160,18 @@ pub fn greet(name: &str) {
#[wasm_bindgen] #[wasm_bindgen]
pub fn test_call_export() { pub fn test_call_export() {
call_export("greeting", "test_export"); call_export("greeting", "test_export", "[0]");
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn test_read_memory() { pub fn test_read_memory() {
let _result = read_memory("greeting", 0, 4); let result:u8 = read_byte("greeting", 0);
log(&result.to_string())
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn test_write_memory() { pub fn test_write_memory() {
let _result = write_memory("greeting", 0, &[0, 1, 2, 3]); write_byte("greeting", 0, 42);
} }
#[wasm_bindgen] #[wasm_bindgen]
@ -204,6 +185,21 @@ pub fn test_it_section(bytes: &[u8]) {
log(&result) log(&result)
} }
#[wasm_bindgen]
pub fn test_instantiate_module(name: &str, wit_section_bytes: &[u8]) {
#[allow(unused)]
let mut module = MModule::new(
name,
wit_section_bytes,
).unwrap();
js_log("callng export");
let output = module.call("greeting", "greeting", &vec![IValue::String("wasm test".to_string())]).unwrap();
for out in output {
js_log(&format!("got output: {}", ival_to_string(&out)));
}
js_log("export call finished");
}
pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfaces<'_>, MyError> { pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfaces<'_>, MyError> {
match wasmer_it::decoders::binary::parse::<(&[u8], nom::error::ErrorKind)>(wit_section_bytes) { match wasmer_it::decoders::binary::parse::<(&[u8], nom::error::ErrorKind)>(wit_section_bytes) {
Ok((remainder, it)) if remainder.is_empty() => Ok(it), Ok((remainder, it)) if remainder.is_empty() => Ok(it),

View File

@ -4,19 +4,28 @@ use wasm_bindgen::prelude::*;
use std::marker::PhantomData; use std::marker::PhantomData;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::borrow::Cow; use std::borrow::Cow;
use it_utils::{MemSlice2, ByteAccess, MemSlice3};
use marine_it_interfaces::MITInterfaces;
use crate::js_log;
use crate::module::type_converters::{itype_arg_to_wtypes, itype_to_raw_output_types};
// marine-related imports // marine-related imports
#[wasm_bindgen(module = "/marine-js.js")] #[wasm_bindgen(module = "/marine-js.js")]
extern { extern {
pub fn call_export(module_name: &str, export_name: &str) -> i32; pub fn call_export(module_name: &str, export_name: &str, args: &str) -> String;
pub fn read_memory(module_name: &str, module_offset: usize, module_len: usize) -> Vec<u8>; pub fn read_memory(module_name: &str, module_offset: usize, module_len: usize) -> Vec<u8>;
pub fn write_memory(module_name: &str, module_offset: usize, data: &[u8]) -> i32; pub fn write_memory(module_name: &str, module_offset: usize, data: &[u8]) -> i32;
pub fn read_byte(module_name: &str, module_offset: usize) -> u8;
pub fn write_byte(module_name: &str, module_offset: usize, value: u8);
pub fn get_memory_size(module_name: &str) -> i32;
} }
pub struct Ctx {} //pub struct Ctx {}
/*
pub struct Func<'a, Args: 'a, Rets> { pub struct Func<'a, Args: 'a, Rets> {
data: PhantomData<Args>, data: PhantomData<Args>,
data2: PhantomData<Rets>, data2: PhantomData<Rets>,
@ -26,7 +35,8 @@ pub struct Func<'a, Args: 'a, Rets> {
pub struct DynamicFunc<'a> { pub struct DynamicFunc<'a> {
data: PhantomData<&'a i32> data: PhantomData<&'a i32>
} }
*/
#[derive(Clone)]
pub struct FuncSig { pub struct FuncSig {
params: Cow<'static, [WType]>, params: Cow<'static, [WType]>,
returns: Cow<'static, [WType]>, returns: Cow<'static, [WType]>,
@ -43,17 +53,27 @@ impl FuncSig {
} }
pub struct Instance { pub struct Instance {
pub exports: Exports pub exports: Exports,
pub module_name: String,
} }
impl Instance { impl Instance {
pub fn exports(&self) -> &Exports { pub fn new(mit: &MITInterfaces, module_name: String) -> Self {
&self.exports Self {
exports: Exports::new(mit),
module_name
}
}
pub fn exports(&self) -> ExportIter {
ExportIter::new(&self.exports)
} }
} }
pub struct DynFunc<'a> { pub struct DynFunc<'a> {
pub(crate) signature: FuncSig, pub(crate) signature: FuncSig,
pub name: String,
pub module_name: String,
//pub(crate) instance_inner: &'a InstanceInner, //pub(crate) instance_inner: &'a InstanceInner,
//func_index: FuncIndex, //func_index: FuncIndex,
data3: PhantomData<&'a i32> data3: PhantomData<&'a i32>
@ -64,12 +84,33 @@ impl<'a> DynFunc<'_> {
&self.signature &self.signature
} }
pub fn call(&self, _args: &[WValue]) -> Result<Vec<WValue>, String> { pub fn call(&self, args: &[WValue]) -> Result<Vec<WValue>, String> {
Err("not implemented".to_string()) crate::js_log(&format!("called DynFunc::call name=({}) with n args {}", self.name, args.len()));
let result = serde_json::ser::to_string(args);
if let Err(e) = result {
js_log(&format!("cannot serialize: {}", e));
return Err("cannot serialize".to_string());
}
let args = result.unwrap();
let output = call_export(&self.module_name, &self.name, &args);
js_log(&format!("DynFunc::Call got result json {}", output));
let value = serde_json::de::from_str::<serde_json::Value>(&output);
match value {
Ok(serde_json::Value::Array(values)) => {
let values = values.iter().map(|value|{
WValue::I32(value.as_i64().unwrap() as i32)
}).collect::<Vec<_>>();
Ok(values)
},
_ => {
js_log("invalid_json got");
Err("invalid json got".to_string())
}
}
} }
} }
/*
pub struct SigRegistry {} pub struct SigRegistry {}
pub struct ExportIndex {} pub struct ExportIndex {}
pub struct WasmTypeList {} pub struct WasmTypeList {}
@ -79,21 +120,91 @@ pub struct Namespace {}
pub struct ImportObject {} pub struct ImportObject {}
pub struct Module {} pub struct Module {}
pub struct LocalMemory {} pub struct LocalMemory {}
*/
#[allow(dead_code)]
#[derive(Clone)]
pub enum Export { pub enum Export {
Memory(i32) Memory,
Function(ProcessedExport)
} }
pub struct Exports { impl Export {
some_export: DynFunc<'static> pub fn name(&self) -> String {
} match self {
Self::Memory => "memory".to_string(),
impl Exports { Self::Function(func) => func.name.clone()
pub fn get(&self, _name: &str) -> Result<DynFunc<'_>, String> { }
Ok(self.some_export)
} }
} }
pub struct Exports {
//some_export: DynFunc<'static>
exports: Vec<Export>,
}
impl Exports {
pub fn new(mit: &MITInterfaces) -> Self {
let mut exports = mit
.exports()
.filter_map( |export| {
crate::js_log(&format!("processing export {} {}", export.name, export.function_type));
let fn_type = mit.type_by_idx(export.function_type).unwrap();
crate::js_log(&format!("got type {}", fn_type.to_string()));
if let wasmer_it::ast::Type::Function{arguments, output_types} = fn_type {
let arg_types = arguments.iter().map(|arg| itype_arg_to_wtypes(&arg.ty)).flatten().collect();
let output_types = output_types.iter().map(itype_to_raw_output_types).flatten().collect();
let sig = FuncSig {
params: Cow::Owned(arg_types),
returns: Cow::Owned(output_types),
};
crate::js_log(&format!("it is a function: {}", export.name.to_string()));
Some(Export::Function(ProcessedExport {
sig,
index: export.function_type,
name: export.name.to_string()
}))
} else {
crate::js_log(&format!("it is not a function"));
None
}
}).collect::<Vec<Export>>();
exports.push(Export::Memory);
crate::js_log(&format!("processed exports"));
Self {
exports
}
}
pub fn get(&self, name: &str) -> Result<DynFunc<'_>, String> {
crate::js_log(&format!("Exports.get called with name {}", name));
let export = self.exports.iter().find(|export| {
if let Export::Function(func) = export {
func.name == name
} else {
false
}
});
match export {
Some(Export::Function(function)) => {
Ok(DynFunc {
signature: function.sig.clone(),
name: function.name.clone(),
module_name: "greeting".to_string(),
data3: Default::default()
})
}
Some(_) |
None => Err(format!("cannot find export {}", name))
}
}
}
#[derive(Clone)]
pub struct ProcessedExport {
sig: FuncSig,
index: u32,
name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum WType { pub enum WType {
@ -134,6 +245,7 @@ pub enum WValue {
} }
impl WValue { impl WValue {
/*
/// The `Type` of this `Value`. /// The `Type` of this `Value`.
pub fn ty(&self) -> WType { pub fn ty(&self) -> WType {
match self { match self {
@ -155,5 +267,74 @@ impl WValue {
WValue::V128(x) => x, WValue::V128(x) => x,
} }
} }
*/
} }
/// An iterator to an instance's exports.
pub struct ExportIter<'a> {
_data: PhantomData<&'a i32>,
exports: &'a Exports,
index: usize,
}
impl<'a> ExportIter<'a> {
pub(crate) fn new(exports: &'a Exports) -> Self {
Self {
_data: PhantomData::<&'a i32>::default(),
exports,
index: 0,
}
}
}
impl<'a> Iterator for ExportIter<'a> {
type Item = (String, Export);
fn next(&mut self) -> Option<(String, Export)> {
let export = self.exports.exports.get(self.index);
self.index += 1;
export.map(|export| {
(export.name(), export.clone())
})
}
}
#[derive(Clone)]
pub struct WasmMemory {
pub module_name: &'static str,
}
impl MemSlice3 for WasmMemory {
fn len(&self) -> usize {
crate::js_log("WasmMemory::len calledx");
get_memory_size(&self.module_name) as usize
}
fn index(&self, index: usize) -> it_utils::ByteAccess {
crate::js_log(&format!("WasmMemory::index called with {}", index));
ByteAccess {
slice: MemSlice2{ slice_ref: self},
index
}
}
fn get(&self, index: usize) -> u8 {
crate::js_log(&format!("WasmMemory::get called with {}", index));
read_byte(&self.module_name, index)
}
fn set(&self, index: usize, value: u8) {
crate::js_log(&format!("WasmMemory::set called with {} {}", index, value));
write_byte(&self.module_name, index, value);
}
fn range_iter(&self, begin: usize, end: usize) -> it_utils::MemSliceIter {
crate::js_log(&format!("WasmMemory::range_iter called with {} {}", begin, end));
it_utils::MemSliceIter {
begin,
end,
slice: MemSlice2 {slice_ref: self}
}
}
}

View File

@ -19,4 +19,4 @@ mod version_checker;
//pub(crate) use prepare::prepare_module; //pub(crate) use prepare::prepare_module;
//pub(crate) use version_checker::check_sdk_version; //pub(crate) use version_checker::check_sdk_version;
//pub(crate) use version_checker::check_it_version; pub(crate) use version_checker::check_it_version;

View File

@ -25,7 +25,7 @@ use marine_it_interfaces::MITInterfaces;
//use marine_it_parser::extract_it_from_module; //use marine_it_parser::extract_it_from_module;
use marine_utils::SharedString; use marine_utils::SharedString;
//use wasmer_core::Instance as WasmerInstance; //use wasmer_core::Instance as WasmerInstance;
use crate::marine_js::Instance as WasmerInstance; use crate::marine_js::{Instance as WasmerInstance};
//use wasmer_core::import::Namespace; //use wasmer_core::import::Namespace;
//use crate::marine_js::Namespace; //use crate::marine_js::Namespace;
//use wasmer_runtime::compile; //use wasmer_runtime::compile;
@ -43,6 +43,7 @@ use crate::module::wit_function::WITFunction;
type ITInterpreter = type ITInterpreter =
Interpreter<ITInstance, ITExport, WITFunction, WITMemory, WITMemoryView<'static>>; Interpreter<ITInstance, ITExport, WITFunction, WITMemory, WITMemoryView<'static>>;
use crate::js_log;
#[derive(Clone)] #[derive(Clone)]
pub(super) struct ITModuleFunc { pub(super) struct ITModuleFunc {
@ -60,14 +61,13 @@ pub(super) struct Callable {
impl Callable { impl Callable {
pub fn call(&mut self, args: &[IValue]) -> MResult<Vec<IValue>> { pub fn call(&mut self, args: &[IValue]) -> MResult<Vec<IValue>> {
use wasmer_it::interpreter::stack::Stackable; use wasmer_it::interpreter::stack::Stackable;
js_log(&format!("Callable::call: start"));
let result = self let result = self
.it_module_func .it_module_func
.interpreter .interpreter
.run(args, Arc::make_mut(&mut self.it_instance))? .run(args, Arc::make_mut(&mut self.it_instance))?
.as_slice() .as_slice()
.to_owned(); .to_owned();
Ok(result) Ok(result)
} }
} }
@ -110,35 +110,38 @@ pub(crate) fn extract_it_from_bytes(wit_section_bytes: &[u8]) -> Result<Interfac
Err(e) => Err(format!("ITParserError::CorruptedITSection({})", e)), Err(e) => Err(format!("ITParserError::CorruptedITSection({})", e)),
} }
} }
#[allow(unused)]
impl MModule { impl MModule {
pub(crate) fn new( pub(crate) fn new(
name: &str, name: &str,
wit_section_bytes: &[u8], wit_section_bytes: &[u8],
wasmer_instance: WasmerInstance, //wasmer_instance: WasmerInstance,
//config: MModuleConfig, //config: MModuleConfig,
modules: &HashMap<String, MModule>, //modules: &HashMap<String, MModule>,
) -> MResult<Self> { ) -> MResult<Self> {
//let wasmer_module = compile(wasm_bytes)?; //let wasmer_module = compile(wasm_bytes)?;
//crate::misc::check_sdk_version(name, &wasmer_module)?; //crate::misc::check_sdk_version(name, &wasmer_module)?;
let it = extract_it_from_bytes(&wit_section_bytes)?; let it = extract_it_from_bytes(&wit_section_bytes)?;
//crate::misc::check_it_version(name, &it.version)?; crate::misc::check_it_version(name, &it.version)?;
js_log("checked it_section");
let mit = MITInterfaces::new(it); let mit = MITInterfaces::new(it);
js_log("created mit");
let wasmer_instance = WasmerInstance::new(&mit, name.to_string());
js_log("created wasmer_instance");
let mut wit_instance = Arc::new_uninit(); let mut wit_instance = Arc::new_uninit();
js_log("created wit_instance");
//let wit_import_object = Self::adjust_wit_imports(&mit, wit_instance.clone())?; //let wit_import_object = Self::adjust_wit_imports(&mit, wit_instance.clone())?;
//let raw_imports = config.raw_imports.clone(); //let raw_imports = config.raw_imports.clone();
//let (wasi_import_object, host_closures_import_object) = //let (wasi_import_object, host_closures_import_object) =
// Self::create_import_objects(config, &mit, wit_import_object.clone())?; // Self::create_import_objects(config, &mit, wit_import_object.clone())?;
//let wasmer_instance = Instance::new(&mit);
// let wasmer_instance = wasmer_module.instantiate(&wasi_import_object)?; // let wasmer_instance = wasmer_module.instantiate(&wasi_import_object)?;
let it_instance = unsafe { let it_instance = unsafe {
// get_mut_unchecked here is safe because currently only this modules have reference to // get_mut_unchecked here is safe because currently only this modules have reference to
// it and the environment is single-threaded // it and the environment is single-threaded
*Arc::get_mut_unchecked(&mut wit_instance) = *Arc::get_mut_unchecked(&mut wit_instance) =
MaybeUninit::new(ITInstance::new(&wasmer_instance, name, &mit, modules)?); MaybeUninit::new(ITInstance::new(&wasmer_instance, /*name,*/ &mit, /*modules*/)?);
std::mem::transmute::<_, Arc<ITInstance>>(wit_instance) std::mem::transmute::<_, Arc<ITInstance>>(wit_instance)
}; };
@ -169,6 +172,7 @@ impl MModule {
) -> MResult<Vec<IValue>> { ) -> MResult<Vec<IValue>> {
self.export_funcs.get_mut(function_name).map_or_else( self.export_funcs.get_mut(function_name).map_or_else(
|| { || {
crate::js_log(&format!("MModule::call: cannot find export {}", function_name));
Err(MError::NoSuchFunction( Err(MError::NoSuchFunction(
module_name.to_string(), module_name.to_string(),
function_name.to_string(), function_name.to_string(),

View File

@ -15,37 +15,59 @@
*/ */
use wasmer_it::interpreter::wasm; use wasmer_it::interpreter::wasm;
use std::cell::Cell; use wasmer_it::interpreter::wasm::structures::MemSlice2;
use std::marker::PhantomData; use crate::js_log;
use crate::marine_js::WasmMemory;
//use wasmer_core::memory::{Memory, MemoryView}; //use wasmer_core::memory::{Memory, MemoryView};
// WEB TODO: implement with js interface // WEB TODO: implement with js interface
pub(super) struct WITMemoryView<'a> { pub(super) struct WITMemoryView<'a> {
data3: PhantomData<&'a i32>, slice: MemSlice2<'a>,
data: Vec<Cell<u8>>,
} }
impl<'a> std::ops::Deref for WITMemoryView<'a> { impl<'a> WITMemoryView<'a> {
type Target = [std::cell::Cell<u8>]; pub fn new(memory: &'a WasmMemory) -> Self {
crate::js_log("WITMemoryView::new called");
fn deref(&self) -> &Self::Target { Self {
self.data.deref() slice: MemSlice2 {
} slice_ref: memory
} }
#[derive(Clone)]
pub(super) struct WITMemory {
memory: i32,
}
impl wasm::structures::MemoryView for WITMemoryView<'_> {}
impl<'a> wasm::structures::Memory<WITMemoryView<'a>> for WITMemory {
fn view(&self) -> WITMemoryView<'a> {
WITMemoryView {
data: Vec::new(),
data3: <_>::default()
} }
} }
} }
impl<'a> std::ops::Deref for WITMemoryView<'a> {
type Target = MemSlice2<'a>;
fn deref(&self) -> &Self::Target {
crate::js_log("got slice from WITMemoryView");
&self.slice
}
}
impl wasm::structures::MemoryView for WITMemoryView<'static> {}
const MEMORY_CONTAINTER: WasmMemory = WasmMemory {
module_name: "greeting",
};
#[derive(Clone)]
pub(super) struct WITMemory {
}
impl WITMemory {
pub fn new(_module_name: String) -> Self {
js_log("created WITMemory");
Self {}
}
}
impl wasm::structures::Memory<WITMemoryView<'static>> for WITMemory {
fn view(&self) -> WITMemoryView<'static> {
crate::js_log("got memory view");
WITMemoryView::new(&MEMORY_CONTAINTER)
}
}

View File

@ -19,7 +19,7 @@ mod marine_module;
mod memory; mod memory;
mod wit_function; mod wit_function;
mod wit_instance; mod wit_instance;
mod type_converters; pub mod type_converters;
pub use wit_instance::MRecordTypes; pub use wit_instance::MRecordTypes;
pub use wasmer_it::IType; pub use wasmer_it::IType;

View File

@ -17,7 +17,7 @@
/// Contains converters of types and values between Wasmer and wasmer_interface_types. /// Contains converters of types and values between Wasmer and wasmer_interface_types.
use super::{WType, WValue, IType, IValue}; use super::{WType, WValue, IType, IValue};
pub(super) fn wtype_to_itype(ty: &WType) -> IType { pub(crate) fn wtype_to_itype(ty: &WType) -> IType {
match ty { match ty {
WType::I32 => IType::I32, WType::I32 => IType::I32,
WType::I64 => IType::I64, WType::I64 => IType::I64,
@ -26,8 +26,8 @@ pub(super) fn wtype_to_itype(ty: &WType) -> IType {
WType::V128 => unimplemented!(), WType::V128 => unimplemented!(),
} }
} }
/*
pub(super) fn itype_to_wtype(ty: &IType) -> WType { pub(crate) fn itype_to_wtype(ty: &IType) -> WType {
match ty { match ty {
IType::S8 => WType::I32, IType::S8 => WType::I32,
IType::S16 => WType::I32, IType::S16 => WType::I32,
@ -48,13 +48,17 @@ pub(super) fn itype_to_wtype(ty: &IType) -> WType {
} }
} }
*/
pub(super) fn ival_to_wval(value: &IValue) -> WValue { pub(super) fn ival_to_wval(value: &IValue) -> WValue {
match value { match value {
IValue::I32(v) => WValue::I32(*v), IValue::I32(v) => WValue::I32(*v),
IValue::I64(v) => WValue::I64(*v), IValue::I64(v) => WValue::I64(*v),
IValue::F32(v) => WValue::F32(*v), IValue::F32(v) => WValue::F32(*v),
IValue::F64(v) => WValue::F64(*v), IValue::F64(v) => WValue::F64(*v),
_ => unimplemented!(), _ => {
crate::js_log(&format!("called ival_to_wval with unknown value"));
unimplemented!()
},
} }
} }
@ -67,3 +71,68 @@ pub(super) fn wval_to_ival(value: &WValue) -> IValue {
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
pub fn itype_arg_to_wtypes(arg: &IType) -> Vec<WType> {
match arg {
IType::Boolean
| IType::S8
| IType::S16
| IType::S32
| IType::I32
| IType::U8
| IType::U16
| IType::U32 => vec![WType::I32],
IType::S64 | IType::U64 | IType::I64 => vec![WType::I64],
IType::F32 => vec![WType::F32],
IType::F64 => vec![WType::F64],
IType::String => vec![WType::I32, WType::I32],
_ => {
crate::js_log("itype_arg_to_wtypes got unexpected type");
unimplemented!();
}
}
}
pub fn itype_to_raw_output_types(ty: &IType) -> Vec<WType> {
match ty {
IType::Boolean
| IType::S8
| IType::S16
| IType::S32
| IType::I32
| IType::U8
| IType::U16
| IType::U32 => vec![WType::I32],
IType::I64 | IType::U64 | IType::S64 => vec![WType::I64],
IType::F32 => vec![WType::F32],
IType::F64 => vec![WType::F64],
| IType::String
| IType::Record(..) => vec![],
_ => {
crate::js_log("itype_to_raw_output_types got unexpected type");
unimplemented!();
}
}
}
pub fn ival_to_string(val: &IValue) -> String {
match val {
IValue::Boolean(val) => {val.to_string()}
IValue::S8(val) => {val.to_string()}
IValue::S16(val) => {val.to_string()}
IValue::S32(val) => {val.to_string()}
IValue::S64(val) => {val.to_string()}
IValue::U8(val) => {val.to_string()}
IValue::U16(val) => {val.to_string()}
IValue::U32(val) => {val.to_string()}
IValue::U64(val) => {val.to_string()}
IValue::F32(val) => {val.to_string()}
IValue::F64(val) => {val.to_string()}
IValue::String(val) => {val.to_string()}
IValue::ByteArray(_) => {"some byte array".to_string()}
IValue::Array(_) => {"some array".to_string()}
IValue::I32(val) => {val.to_string()}
IValue::I64(val) => {val.to_string()}
IValue::Record(_) => {"some record".to_string()}
}
}

View File

@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
use super::marine_module::MModule; //use super::marine_module::MModule;
use super::{IType, IFunctionArg, IValue, WValue}; use super::{IType, IFunctionArg, IValue, WValue};
use super::marine_module::Callable; //use super::marine_module::Callable;
use crate::MResult; use crate::MResult;
//use crate::marine_js; //use crate::marine_js;
@ -31,11 +31,11 @@ use crate::marine_js::DynFunc;
enum WITFunctionInner { enum WITFunctionInner {
Export { Export {
func: Rc<DynFunc<'static>>, func: Rc<DynFunc<'static>>,
}, },/*
Import { Import {
// TODO: use dyn Callable here // TODO: use dyn Callable here
callable: Rc<Callable>, callable: Rc<Callable>,
}, },*/
} }
/// Represents all import and export functions that could be called from IT context by call-core. /// Represents all import and export functions that could be called from IT context by call-core.
@ -52,6 +52,7 @@ impl WITFunction {
pub(super) fn from_export(dyn_func: DynFunc<'static>, name: String) -> MResult<Self> { pub(super) fn from_export(dyn_func: DynFunc<'static>, name: String) -> MResult<Self> {
use super::type_converters::wtype_to_itype; use super::type_converters::wtype_to_itype;
let signature = dyn_func.signature(); let signature = dyn_func.signature();
let arguments = signature let arguments = signature
.params() .params()
@ -82,7 +83,7 @@ impl WITFunction {
inner, inner,
}) })
} }
/*
/// Creates function from a module import. /// Creates function from a module import.
pub(super) fn from_import( pub(super) fn from_import(
wit_module: &MModule, wit_module: &MModule,
@ -104,6 +105,7 @@ impl WITFunction {
inner, inner,
}) })
} }
*/
} }
impl wasm::structures::LocalImport for WITFunction { impl wasm::structures::LocalImport for WITFunction {
@ -129,16 +131,16 @@ impl wasm::structures::LocalImport for WITFunction {
fn call(&self, arguments: &[IValue]) -> std::result::Result<Vec<IValue>, ()> { fn call(&self, arguments: &[IValue]) -> std::result::Result<Vec<IValue>, ()> {
use super::type_converters::{ival_to_wval, wval_to_ival}; use super::type_converters::{ival_to_wval, wval_to_ival};
crate::js_log(&format!("called WITFunction::call with n argts {}", arguments.len()));
match &self.inner { match &self.inner {
WITFunctionInner::Export { func, .. } => func WITFunctionInner::Export { func, .. } => func
.as_ref() .as_ref()
.call(&arguments.iter().map(ival_to_wval).collect::<Vec<WValue>>()) .call(&arguments.iter().map(ival_to_wval).collect::<Vec<WValue>>())
.map(|result| result.iter().map(wval_to_ival).collect()) .map(|result| result.iter().map(wval_to_ival).collect())
.map_err(|_| ()), .map_err(|_| ()),/*
WITFunctionInner::Import { callable, .. } => Rc::make_mut(&mut callable.clone()) WITFunctionInner::Import { callable, .. } => Rc::make_mut(&mut callable.clone())
.call(arguments) .call(arguments)
.map_err(|_| ()), .map_err(|_| ()),*/
} }
} }
} }

View File

@ -15,19 +15,18 @@
*/ */
use super::wit_prelude::*; use super::wit_prelude::*;
use super::marine_module::MModule; //use super::marine_module::MModule;
use super::IRecordType; use super::IRecordType;
use crate::MResult; use crate::{js_log, MResult};
use marine_it_interfaces::MITInterfaces; use marine_it_interfaces::MITInterfaces;
use marine_it_interfaces::ITAstType; use marine_it_interfaces::ITAstType;
use wasmer_it::interpreter::wasm; use wasmer_it::interpreter::wasm;
use wasmer_it::interpreter::wasm::structures::{LocalImportIndex, TypedIndex}; use wasmer_it::interpreter::wasm::structures::{LocalImportIndex, Memory, MemSlice2, TypedIndex};
//use wasmer_core::Instance as WasmerInstance; //use wasmer_core::Instance as WasmerInstance;
use crate::marine_js::{Instance as WasmerInstance, DynFunc}; use crate::marine_js::{Instance as WasmerInstance, DynFunc};
use std::collections::HashMap; use std::collections::HashMap;
use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
pub type MRecordTypes = HashMap<u64, Rc<IRecordType>>; pub type MRecordTypes = HashMap<u64, Rc<IRecordType>>;
@ -48,15 +47,15 @@ pub(super) struct ITInstance {
impl ITInstance { impl ITInstance {
pub(super) fn new( pub(super) fn new(
wasmer_instance: &WasmerInstance, wasmer_instance: &WasmerInstance,
module_name: &str, //module_name: &str,
wit: &MITInterfaces<'_>, wit: &MITInterfaces<'_>,
modules: &HashMap<String, MModule>, //modules: &HashMap<String, MModule>,
) -> MResult<Self> { ) -> MResult<Self> {
let mut exports = Self::extract_raw_exports(wasmer_instance, wit)?; let exports = Self::extract_raw_exports(wasmer_instance, wit)?;
let imports = Self::extract_imports(module_name, modules, wit, exports.len())?; //let imports = Self::extract_imports("test", &<_>::default(), wit, exports.len())?;
let memories = Self::extract_memories(wasmer_instance); let memories = Self::extract_memories(wasmer_instance);
exports.extend(imports); //exports.extend(imports);
let funcs = exports; let funcs = exports;
let record_types_by_id = Self::extract_record_types(wit); let record_types_by_id = Self::extract_record_types(wit);
@ -94,6 +93,7 @@ impl ITInstance {
.collect() .collect()
} }
/*
/// Extracts only those imports that don't have implementations. /// Extracts only those imports that don't have implementations.
fn extract_imports( fn extract_imports(
module_name: &str, module_name: &str,
@ -138,14 +138,16 @@ impl ITInstance {
.collect::<MResult<HashMap<_, _>>>() .collect::<MResult<HashMap<_, _>>>()
} }
*/
fn extract_memories(wasmer_instance: &WasmerInstance) -> Vec<WITMemory> { fn extract_memories(wasmer_instance: &WasmerInstance) -> Vec<WITMemory> {
//use wasmer_core::export::Export::Memory; //use wasmer_core::export::Export::Memory;
use crate::marine_js::Export::Memory; use crate::marine_js::Export::Memory;
let mut memories = wasmer_instance let memories = wasmer_instance
.exports() .exports()
.filter_map(|(_, export)| match export { .filter_map(|(_, export)| match export {
Memory(memory) => Some(WITMemory{memory}), Memory => Some(WITMemory::new(wasmer_instance.module_name.clone())),
_ => None, _ => None,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -178,19 +180,23 @@ impl ITInstance {
} }
} }
impl wasm::structures::Instance<ITExport, WITFunction, WITMemory, WITMemoryView<'_>> impl wasm::structures::Instance<ITExport, WITFunction, WITMemory, WITMemoryView<'static>>
for ITInstance for ITInstance
{ {
fn export(&self, _export_name: &str) -> Option<&ITExport> { fn export(&self, _export_name: &str) -> Option<&ITExport> {
js_log(&format!("called ITInstance::export with {}", _export_name));
// exports aren't used in this version of IT // exports aren't used in this version of IT
None None
} }
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&WITFunction> { fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&WITFunction> {
js_log(&format!("called ITInstance::local_or_import with {}", index.index()));
js_log(&format!("ITInstance::export funcs size {}", self.funcs.len()));
self.funcs.get(&index.index()) self.funcs.get(&index.index())
} }
fn memory(&self, index: usize) -> Option<&WITMemory> { fn memory(&self, index: usize) -> Option<&WITMemory> {
js_log(&format!("called ITInstance::memory with {}", index));
if index >= self.memories.len() { if index >= self.memories.len() {
None None
} else { } else {
@ -198,26 +204,29 @@ impl wasm::structures::Instance<ITExport, WITFunction, WITMemory, WITMemoryView<
} }
} }
fn memory_slice(&self, index: usize) -> Option<&[Cell<u8>]> { fn memory_slice(&self, index: usize) -> Option<MemSlice2> {
//use wasmer_core::vm::LocalMemory; //use wasmer_core::vm::LocalMemory;
use crate::marine_js::LocalMemory; //use crate::marine_js::LocalMemory;
js_log(&format!("called ITInstance::memory_slice with {}", index));
if index >= self.memories.len() { if index >= self.memories.len() {
return None; return None;
} }
let memory = &self.memories[index]; let memory = &self.memories[index];
let LocalMemory { base, .. } = unsafe { *memory.0.vm_local_memory() }; /* let LocalMemory { base, .. } = unsafe { *memory.0.vm_local_memory() };
let length = memory.0.size().bytes().0 / std::mem::size_of::<u8>(); let length = memory.0.size().bytes().0 / std::mem::size_of::<u8>();
let mut_slice: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(base, length) }; let mut_slice: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(base, length) };
let cell_slice: &Cell<[u8]> = Cell::from_mut(mut_slice); let cell_slice: &Cell<[u8]> = Cell::from_mut(mut_slice);
let slice = cell_slice.as_slice_of_cells(); let slice = cell_slice.as_slice_of_cells();
*/
Some(slice) Some(*memory.view())
//Some(memory.view().boxed_copy())
} }
fn wit_record_by_id(&self, index: u64) -> Option<&Rc<IRecordType>> { fn wit_record_by_id(&self, index: u64) -> Option<&Rc<IRecordType>> {
js_log(&format!("called ITInstance::wit_record_by_id with {}", index));
self.record_types_by_id.get(&index) self.record_types_by_id.get(&index)
} }
} }