mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-12 06:45:32 +00:00
Fix IT generation (#87)
This commit is contained in:
parent
fa38bc4025
commit
c51b5982d6
@ -29,7 +29,7 @@ jobs:
|
|||||||
(cd ./examples; ./build.sh)
|
(cd ./examples; ./build.sh)
|
||||||
(cd ./fluence-faas/tests/wasm_tests; ./build.sh)
|
(cd ./fluence-faas/tests/wasm_tests; ./build.sh)
|
||||||
|
|
||||||
cargo test --release -v --all-features -p marine-runtime -p fluence-faas -p fluence-app-service -p marine -p mrepl
|
cargo test --release -v --all-features -p marine-it-generator -p marine-runtime -p fluence-faas -p fluence-app-service -p marine -p mrepl
|
||||||
cargo clippy -v -p marine-runtime -p fluence-faas -p fluence-app-service -p marine -p mrepl
|
cargo clippy -v -p marine-runtime -p fluence-faas -p fluence-app-service -p marine -p mrepl
|
||||||
|
|
||||||
- save_cache:
|
- save_cache:
|
||||||
|
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -700,9 +700,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence"
|
name = "fluence"
|
||||||
version = "0.6.5"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd1f159a4da6aef89e8e4a0bf061a8031d669d03d9928266942581a52df03f56"
|
checksum = "88b09e1cd11a51ba4d169db347d009fe41ece2714eef4d5df720343733a1d5a6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence-sdk-main",
|
"fluence-sdk-main",
|
||||||
"marine-macro",
|
"marine-macro",
|
||||||
@ -805,9 +805,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-sdk-main"
|
name = "fluence-sdk-main"
|
||||||
version = "0.6.4"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3a5d1ca20ada064379d959a9a82f9c006e4d9388533cf06010186fef6dd583b"
|
checksum = "68d93cde99e1494e11755a39b93863333397245c9959c774fe3bebd9e4143879"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"marine-macro",
|
"marine-macro",
|
||||||
@ -1549,18 +1549,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "marine-macro"
|
name = "marine-macro"
|
||||||
version = "0.6.4"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c1652b6ac1bbdde9a66c16c8a2f9cd34d005a1f1b211a538c5b28764faa6ef4"
|
checksum = "f63d927851847cc3dd9e3bd0f10bdeb313859d4822d5b5f650d9d34d461ed419"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"marine-macro-impl",
|
"marine-macro-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "marine-macro-impl"
|
name = "marine-macro-impl"
|
||||||
version = "0.6.4"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80fee75eaf1a97ee9fe2d382c0537c06a79e5d7ab9d81bda6cb263fb8fd1a15a"
|
checksum = "fb504be4a90e229ab453c7369cc8a9063acec819f3397802eea719cd0a232be1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1699,9 +1699,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "marine-timestamp-macro"
|
name = "marine-timestamp-macro"
|
||||||
version = "0.6.2"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6feb612ccd3fd39ec3d50c9a1a96885e1fd32d36a92cf674a0fbe6f7c452613"
|
checksum = "5994c7db5567d21609f2a2e5a40d9d4564f86c17ca35b2d77007152619b9d7fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "marine-it-generator"
|
name = "marine-it-generator"
|
||||||
description = "Fluence Marine interface types generator"
|
description = "Fluence Marine interface types generator"
|
||||||
version = "0.5.1"
|
version = "0.5.2"
|
||||||
authors = ["Fluence Labs"]
|
authors = ["Fluence Labs"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
marine-it-parser = { path = "../it-parser", version = "0.6.0"}
|
marine-it-parser = { path = "../it-parser", version = "0.6.0"}
|
||||||
marine-macro-impl = "0.6.4"
|
marine-macro-impl = "0.6.9"
|
||||||
|
|
||||||
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.0" }
|
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.0" }
|
||||||
it-lilo = "0.1.0"
|
it-lilo = "0.1.0"
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
mod fn_instructions;
|
mod fn_instructions;
|
||||||
mod foreign_mod_instructions;
|
mod foreign_mod_instructions;
|
||||||
mod record_instructions;
|
mod record_instructions;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
@ -102,6 +104,75 @@ impl<'a> ITResolver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ITResolver<'a> {
|
||||||
|
pub(crate) fn add_adapter(
|
||||||
|
&mut self,
|
||||||
|
function_type: u32,
|
||||||
|
instructions: Vec<wasmer_it::interpreter::Instruction>,
|
||||||
|
) {
|
||||||
|
let adapter = wasmer_it::ast::Adapter {
|
||||||
|
function_type,
|
||||||
|
instructions,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.interfaces.adapters.push(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_implementation(
|
||||||
|
&mut self,
|
||||||
|
core_function_type: u32,
|
||||||
|
adapter_function_type: u32,
|
||||||
|
) {
|
||||||
|
let implementation = wasmer_it::ast::Implementation {
|
||||||
|
core_function_type,
|
||||||
|
adapter_function_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.interfaces.implementations.push(implementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_export(&mut self, name: &'a str, function_type: u32) {
|
||||||
|
let export = wasmer_it::ast::Export {
|
||||||
|
name,
|
||||||
|
function_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.interfaces.exports.push(export);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_import(&mut self, namespace: &'a str, name: &'a str, function_type: u32) {
|
||||||
|
let import = wasmer_it::ast::Import {
|
||||||
|
namespace,
|
||||||
|
name,
|
||||||
|
function_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.interfaces.imports.push(import);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_fn_type(
|
||||||
|
&mut self,
|
||||||
|
arguments: Rc<Vec<wasmer_it::ast::FunctionArg>>,
|
||||||
|
output_types: Rc<Vec<IType>>,
|
||||||
|
) {
|
||||||
|
let fn_type = wasmer_it::ast::Type::Function {
|
||||||
|
arguments,
|
||||||
|
output_types,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.interfaces.types.push(fn_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_record_type(
|
||||||
|
&mut self,
|
||||||
|
name: String,
|
||||||
|
fields: wasmer_it::NEVec<wasmer_it::IRecordFieldType>,
|
||||||
|
) {
|
||||||
|
let record = wasmer_it::IRecordType { name, fields };
|
||||||
|
self.insert_record_type(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) trait ITGenerator {
|
pub(crate) trait ITGenerator {
|
||||||
fn generate_it<'a>(&'a self, it_resolver: &mut ITResolver<'a>) -> Result<()>;
|
fn generate_it<'a>(&'a self, it_resolver: &mut ITResolver<'a>) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
@ -14,68 +14,44 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mod args_it_generator;
|
||||||
|
mod output_type_it_generator;
|
||||||
|
|
||||||
use super::ITGenerator;
|
use super::ITGenerator;
|
||||||
use super::ITResolver;
|
use super::ITResolver;
|
||||||
use super::utils::ptype_to_itype_checked;
|
use super::utils::*;
|
||||||
use crate::default_export_api_config::*;
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
use crate::default_export_api_config::RELEASE_OBJECTS;
|
||||||
|
|
||||||
use marine_macro_impl::FnType;
|
use marine_macro_impl::FnType;
|
||||||
use marine_macro_impl::ParsedType;
|
|
||||||
use wasmer_it::interpreter::Instruction;
|
use wasmer_it::interpreter::Instruction;
|
||||||
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
|
||||||
use wasmer_it::IType;
|
|
||||||
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
impl ITGenerator for FnType {
|
impl ITGenerator for FnType {
|
||||||
fn generate_it<'a>(&'a self, it_resolver: &mut ITResolver<'a>) -> Result<()> {
|
fn generate_it<'a>(&'a self, it_resolver: &mut ITResolver<'a>) -> Result<()> {
|
||||||
use wasmer_it::ast::Type;
|
generate_it_types(self, it_resolver)?;
|
||||||
use wasmer_it::ast::Adapter;
|
generate_instructions(self, it_resolver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let arguments = self
|
fn generate_it_types<'f>(fn_type: &'f FnType, it_resolver: &mut ITResolver<'f>) -> Result<()> {
|
||||||
.signature
|
let arguments = generate_it_args(&fn_type.signature, it_resolver)?;
|
||||||
.arguments
|
let output_types = generate_it_output_type(&fn_type.signature, it_resolver)?;
|
||||||
.iter()
|
|
||||||
.map(|arg| -> Result<IFunctionArg> {
|
|
||||||
Ok(IFunctionArg {
|
|
||||||
name: arg.name.clone(),
|
|
||||||
ty: ptype_to_itype_checked(&arg.ty, it_resolver)?,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>>>()?;
|
|
||||||
|
|
||||||
let arguments = Rc::new(arguments);
|
|
||||||
|
|
||||||
let output_types = self
|
|
||||||
.signature
|
|
||||||
.output_types
|
|
||||||
.iter()
|
|
||||||
.map(|ty| ptype_to_itype_checked(ty, it_resolver))
|
|
||||||
.collect::<Result<Vec<_>>>()?;
|
|
||||||
let output_types = Rc::new(output_types);
|
|
||||||
|
|
||||||
let interfaces = &mut it_resolver.interfaces;
|
|
||||||
interfaces.types.push(Type::Function {
|
|
||||||
arguments: arguments.clone(),
|
|
||||||
output_types: output_types.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
it_resolver.add_fn_type(arguments.clone(), output_types.clone());
|
||||||
// TODO: replace with Wasm types
|
// TODO: replace with Wasm types
|
||||||
interfaces.types.push(Type::Function {
|
it_resolver.add_fn_type(arguments, output_types);
|
||||||
arguments,
|
|
||||||
output_types,
|
|
||||||
});
|
|
||||||
|
|
||||||
let adapter_idx = (interfaces.types.len() - 2) as u32;
|
let export_idx = (it_resolver.interfaces.types.len() - 1) as u32;
|
||||||
let export_idx = (interfaces.types.len() - 1) as u32;
|
it_resolver.add_export(&fn_type.signature.name, export_idx);
|
||||||
|
|
||||||
interfaces.exports.push(wasmer_it::ast::Export {
|
Ok(())
|
||||||
name: &self.signature.name,
|
}
|
||||||
function_type: export_idx,
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut instructions = self
|
fn generate_instructions<'f>(fn_type: &'f FnType, it_resolver: &mut ITResolver<'f>) -> Result<()> {
|
||||||
|
use args_it_generator::ArgumentITGenerator;
|
||||||
|
use output_type_it_generator::OutputITGenerator;
|
||||||
|
|
||||||
|
let mut instructions = fn_type
|
||||||
.signature
|
.signature
|
||||||
.arguments
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
@ -83,7 +59,7 @@ impl ITGenerator for FnType {
|
|||||||
.try_fold::<_, _, Result<_>>(Vec::new(), |mut instructions, (arg_id, arg)| {
|
.try_fold::<_, _, Result<_>>(Vec::new(), |mut instructions, (arg_id, arg)| {
|
||||||
let new_instructions = arg
|
let new_instructions = arg
|
||||||
.ty
|
.ty
|
||||||
.generate_instructions_for_input_type(arg_id as _, it_resolver)?;
|
.generate_instructions_for_arg(arg_id as _, it_resolver)?;
|
||||||
|
|
||||||
instructions.extend(new_instructions);
|
instructions.extend(new_instructions);
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
@ -94,145 +70,31 @@ impl ITGenerator for FnType {
|
|||||||
function_index: export_function_index,
|
function_index: export_function_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
let instructions = self
|
let mut should_generate_release = false;
|
||||||
|
let mut instructions = fn_type
|
||||||
.signature
|
.signature
|
||||||
.output_types
|
.output_types
|
||||||
.iter()
|
.iter()
|
||||||
.try_fold::<_, _, Result<_>>(instructions, |mut instructions, ty| {
|
.try_fold::<_, _, Result<_>>(instructions, |mut instructions, ty| {
|
||||||
let new_instructions = ty.generate_instructions_for_output_type(it_resolver)?;
|
let new_instructions = ty.generate_instructions_for_output_type(it_resolver)?;
|
||||||
|
|
||||||
instructions.extend(new_instructions);
|
instructions.extend(new_instructions);
|
||||||
|
|
||||||
|
should_generate_release |= ty.is_complex_type();
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let adapter = Adapter {
|
if should_generate_release {
|
||||||
function_type: adapter_idx,
|
instructions.push(Instruction::CallCore {
|
||||||
instructions,
|
function_index: RELEASE_OBJECTS.id,
|
||||||
};
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it_resolver.interfaces.adapters.push(adapter);
|
let types_count = it_resolver.interfaces.types.len() as u32;
|
||||||
|
let adapter_idx = types_count - 2;
|
||||||
|
let export_idx = types_count - 1;
|
||||||
|
|
||||||
let implementation = wasmer_it::ast::Implementation {
|
it_resolver.add_adapter(adapter_idx, instructions);
|
||||||
core_function_type: export_idx,
|
it_resolver.add_implementation(export_idx, adapter_idx);
|
||||||
adapter_function_type: adapter_idx,
|
|
||||||
};
|
|
||||||
it_resolver.interfaces.implementations.push(implementation);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate IT instructions for a function.
|
|
||||||
trait FnInstructionGenerator {
|
|
||||||
fn generate_instructions_for_input_type<'a>(
|
|
||||||
&self,
|
|
||||||
arg_id: u32,
|
|
||||||
it_resolver: &mut ITResolver<'a>,
|
|
||||||
) -> Result<Vec<Instruction>>;
|
|
||||||
|
|
||||||
fn generate_instructions_for_output_type<'a>(
|
|
||||||
&self,
|
|
||||||
it_resolver: &mut ITResolver<'a>,
|
|
||||||
) -> Result<Vec<Instruction>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FnInstructionGenerator for ParsedType {
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn generate_instructions_for_input_type<'a>(&self, index: u32, it_resolver: &mut ITResolver<'a>) -> Result<Vec<Instruction>> {
|
|
||||||
let instructions = match self {
|
|
||||||
ParsedType::Boolean(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromBool],
|
|
||||||
ParsedType::I8(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8],
|
|
||||||
ParsedType::I16(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS16],
|
|
||||||
ParsedType::I32(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS32],
|
|
||||||
ParsedType::I64(_) => vec![Instruction::ArgumentGet { index }, Instruction::I64FromS64],
|
|
||||||
ParsedType::U8(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU8],
|
|
||||||
ParsedType::U16(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU16],
|
|
||||||
ParsedType::U32(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU32],
|
|
||||||
ParsedType::U64(_) => vec![Instruction::ArgumentGet { index }, Instruction::I64FromU64],
|
|
||||||
ParsedType::F32(_) => vec![Instruction::ArgumentGet { index }],
|
|
||||||
ParsedType::F64(_) => vec![Instruction::ArgumentGet { index }],
|
|
||||||
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => {
|
|
||||||
let type_tag = it_lilo::utils::ser_type_size(&IType::U8) as i32;
|
|
||||||
vec![
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::StringSize,
|
|
||||||
Instruction::PushI32 { value: type_tag },
|
|
||||||
Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::StringLowerMemory,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
ParsedType::Vector(value_type, _) => {
|
|
||||||
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
|
||||||
vec![
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::ArrayLowerMemory {
|
|
||||||
value_type
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
ParsedType::Record(record_name, _) => {
|
|
||||||
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
|
||||||
|
|
||||||
vec! [
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::RecordLowerMemory { record_type_id },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn generate_instructions_for_output_type<'a>(&self, it_resolver: &mut ITResolver<'a>) -> Result<Vec<Instruction>> {
|
|
||||||
let instructions = match self {
|
|
||||||
ParsedType::Boolean(_) => vec![Instruction::BoolFromI32],
|
|
||||||
ParsedType::I8(_) => vec![Instruction::S8FromI32],
|
|
||||||
ParsedType::I16(_) => vec![Instruction::S16FromI32],
|
|
||||||
ParsedType::I32(_) => vec![Instruction::S32FromI32],
|
|
||||||
ParsedType::I64(_) => vec![Instruction::S64FromI64],
|
|
||||||
ParsedType::U8(_) => vec![Instruction::U8FromI32],
|
|
||||||
ParsedType::U16(_) => vec![Instruction::U16FromI32],
|
|
||||||
ParsedType::U32(_) => vec![Instruction::U32FromI32],
|
|
||||||
ParsedType::U64(_) => vec![Instruction::U64FromI64],
|
|
||||||
ParsedType::F32(_) => vec![],
|
|
||||||
ParsedType::F64(_) => vec![],
|
|
||||||
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => vec![
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
|
|
||||||
Instruction::StringLiftMemory,
|
|
||||||
Instruction::CallCore { function_index: RELEASE_OBJECTS.id },
|
|
||||||
],
|
|
||||||
ParsedType::Vector(value_type, _) => {
|
|
||||||
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
|
||||||
if let IType::U8 = value_type {
|
|
||||||
vec![
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
|
|
||||||
Instruction::ByteArrayLiftMemory,
|
|
||||||
Instruction::CallCore { function_index: RELEASE_OBJECTS.id },
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
vec![
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
|
|
||||||
Instruction::ArrayLiftMemory { value_type },
|
|
||||||
Instruction::CallCore { function_index: RELEASE_OBJECTS.id },
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ParsedType::Record(record_name, _) => {
|
|
||||||
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
|
||||||
|
|
||||||
vec! [
|
|
||||||
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
|
||||||
Instruction::RecordLiftMemory { record_type_id },
|
|
||||||
Instruction::CallCore { function_index: RELEASE_OBJECTS.id },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::ITResolver;
|
||||||
|
use super::ptype_to_itype_checked;
|
||||||
|
use crate::default_export_api_config::*;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
use marine_macro_impl::ParsedType;
|
||||||
|
use wasmer_it::interpreter::Instruction;
|
||||||
|
use wasmer_it::IType;
|
||||||
|
|
||||||
|
/// Generates IT instructions for a argument of an export function.
|
||||||
|
pub(super) trait ArgumentITGenerator {
|
||||||
|
fn generate_instructions_for_arg<'a>(
|
||||||
|
&self,
|
||||||
|
arg_id: u32,
|
||||||
|
it_resolver: &mut ITResolver<'a>,
|
||||||
|
) -> Result<Vec<Instruction>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArgumentITGenerator for ParsedType {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn generate_instructions_for_arg<'a>(&self, index: u32, it_resolver: &mut ITResolver<'a>) -> Result<Vec<Instruction>> {
|
||||||
|
let instructions = match self {
|
||||||
|
ParsedType::Boolean(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromBool],
|
||||||
|
ParsedType::I8(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS8],
|
||||||
|
ParsedType::I16(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS16],
|
||||||
|
ParsedType::I32(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromS32],
|
||||||
|
ParsedType::I64(_) => vec![Instruction::ArgumentGet { index }, Instruction::I64FromS64],
|
||||||
|
ParsedType::U8(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU8],
|
||||||
|
ParsedType::U16(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU16],
|
||||||
|
ParsedType::U32(_) => vec![Instruction::ArgumentGet { index }, Instruction::I32FromU32],
|
||||||
|
ParsedType::U64(_) => vec![Instruction::ArgumentGet { index }, Instruction::I64FromU64],
|
||||||
|
ParsedType::F32(_) => vec![Instruction::ArgumentGet { index }],
|
||||||
|
ParsedType::F64(_) => vec![Instruction::ArgumentGet { index }],
|
||||||
|
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => {
|
||||||
|
let type_tag = it_lilo::utils::ser_type_size(&IType::U8) as i32;
|
||||||
|
vec![
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::StringSize,
|
||||||
|
Instruction::PushI32 { value: type_tag },
|
||||||
|
Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::StringLowerMemory,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
ParsedType::Vector(value_type, _) => {
|
||||||
|
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
||||||
|
vec![
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::ArrayLowerMemory {
|
||||||
|
value_type
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
ParsedType::Record(record_name, _) => {
|
||||||
|
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
||||||
|
|
||||||
|
vec! [
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::RecordLowerMemory { record_type_id },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::ITResolver;
|
||||||
|
use super::ptype_to_itype_checked;
|
||||||
|
use crate::default_export_api_config::*;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
use marine_macro_impl::ParsedType;
|
||||||
|
use wasmer_it::interpreter::Instruction;
|
||||||
|
use wasmer_it::IType;
|
||||||
|
|
||||||
|
/// Generates IT instructions for a output type of an export function.
|
||||||
|
pub(super) trait OutputITGenerator {
|
||||||
|
fn generate_instructions_for_output_type<'a>(
|
||||||
|
&self,
|
||||||
|
it_resolver: &mut ITResolver<'a>,
|
||||||
|
) -> Result<Vec<Instruction>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputITGenerator for ParsedType {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn generate_instructions_for_output_type<'a>(&self, it_resolver: &mut ITResolver<'a>) -> Result<Vec<Instruction>> {
|
||||||
|
let instructions = match self {
|
||||||
|
ParsedType::Boolean(_) => vec![Instruction::BoolFromI32],
|
||||||
|
ParsedType::I8(_) => vec![Instruction::S8FromI32],
|
||||||
|
ParsedType::I16(_) => vec![Instruction::S16FromI32],
|
||||||
|
ParsedType::I32(_) => vec![Instruction::S32FromI32],
|
||||||
|
ParsedType::I64(_) => vec![Instruction::S64FromI64],
|
||||||
|
ParsedType::U8(_) => vec![Instruction::U8FromI32],
|
||||||
|
ParsedType::U16(_) => vec![Instruction::U16FromI32],
|
||||||
|
ParsedType::U32(_) => vec![Instruction::U32FromI32],
|
||||||
|
ParsedType::U64(_) => vec![Instruction::U64FromI64],
|
||||||
|
ParsedType::F32(_) => vec![],
|
||||||
|
ParsedType::F64(_) => vec![],
|
||||||
|
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => vec![
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
|
||||||
|
Instruction::StringLiftMemory,
|
||||||
|
],
|
||||||
|
ParsedType::Vector(value_type, _) => {
|
||||||
|
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
||||||
|
if let IType::U8 = value_type {
|
||||||
|
vec![
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
|
||||||
|
Instruction::ByteArrayLiftMemory,
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_SIZE_FUNC.id },
|
||||||
|
Instruction::ArrayLiftMemory { value_type },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ParsedType::Record(record_name, _) => {
|
||||||
|
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
||||||
|
|
||||||
|
vec! [
|
||||||
|
Instruction::CallCore { function_index: GET_RESULT_PTR_FUNC.id },
|
||||||
|
Instruction::RecordLiftMemory { record_type_id },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
}
|
@ -14,17 +14,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mod args_it_generator;
|
||||||
|
mod output_type_it_generator;
|
||||||
|
|
||||||
use super::ITGenerator;
|
use super::ITGenerator;
|
||||||
use super::ITResolver;
|
use super::ITResolver;
|
||||||
use super::utils::ptype_to_itype_checked;
|
use super::utils::*;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::default_export_api_config::*;
|
use crate::default_export_api_config::RELEASE_OBJECTS;
|
||||||
use crate::instructions_generator::utils::wtype_to_itype;
|
use crate::instructions_generator::utils::wtype_to_itype;
|
||||||
|
|
||||||
use marine_macro_impl::ExternModType;
|
use marine_macro_impl::ExternModType;
|
||||||
use marine_macro_impl::ExternFnType;
|
use marine_macro_impl::ExternFnType;
|
||||||
use marine_macro_impl::ParsedType;
|
use marine_macro_impl::ParsedType;
|
||||||
use marine_macro_impl::FnArgument;
|
use marine_macro_impl::FnArgument;
|
||||||
|
use marine_macro_impl::FnSignature;
|
||||||
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||||
use wasmer_it::interpreter::Instruction;
|
use wasmer_it::interpreter::Instruction;
|
||||||
use wasmer_it::IType;
|
use wasmer_it::IType;
|
||||||
@ -49,108 +53,76 @@ impl ITGenerator for ExternModType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_it_for_import<'a>(
|
fn generate_it_for_import<'a>(
|
||||||
import: &'a ExternFnType,
|
fn_type: &'a ExternFnType,
|
||||||
namespace: &'a str,
|
namespace: &'a str,
|
||||||
it_resolver: &mut ITResolver<'a>,
|
it_resolver: &mut ITResolver<'a>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use wasmer_it::ast::Type;
|
generate_it_types(fn_type, namespace, it_resolver)?;
|
||||||
use wasmer_it::ast::Adapter;
|
generate_it_instructions(fn_type, it_resolver)
|
||||||
|
}
|
||||||
|
|
||||||
let arguments = import
|
fn generate_it_types<'f>(
|
||||||
.signature
|
fn_type: &'f ExternFnType,
|
||||||
.arguments
|
namespace: &'f str,
|
||||||
.iter()
|
it_resolver: &mut ITResolver<'f>,
|
||||||
.map(|arg| -> Result<IFunctionArg> {
|
) -> Result<()> {
|
||||||
Ok(IFunctionArg {
|
let arguments = generate_it_args(&fn_type.signature, it_resolver)?;
|
||||||
name: arg.name.clone(),
|
let output_types = generate_it_output_type(&fn_type.signature, it_resolver)?;
|
||||||
ty: ptype_to_itype_checked(&arg.ty, it_resolver)?,
|
it_resolver.add_fn_type(arguments, output_types);
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>>>()?;
|
|
||||||
let arguments = Rc::new(arguments);
|
|
||||||
|
|
||||||
let output_types = import
|
let raw_arguments = generate_raw_args(&fn_type.signature);
|
||||||
.signature
|
let raw_output_types = generate_raw_output_type(&fn_type.signature);
|
||||||
.output_types
|
it_resolver.add_fn_type(raw_arguments.clone(), raw_output_types.clone());
|
||||||
.iter()
|
it_resolver.add_fn_type(raw_arguments, raw_output_types);
|
||||||
.map(|ty| ptype_to_itype_checked(ty, it_resolver))
|
|
||||||
.collect::<Result<Vec<_>>>()?;
|
|
||||||
let output_types = Rc::new(output_types);
|
|
||||||
|
|
||||||
let interfaces = &mut it_resolver.interfaces;
|
let types_count = it_resolver.interfaces.types.len() as u32;
|
||||||
interfaces.types.push(Type::Function {
|
let import_idx = types_count - 3;
|
||||||
arguments,
|
let raw_import_idx = types_count - 1;
|
||||||
output_types,
|
|
||||||
});
|
|
||||||
|
|
||||||
let raw_inputs = import
|
let link_name = match &fn_type.link_name {
|
||||||
.signature
|
|
||||||
.arguments
|
|
||||||
.iter()
|
|
||||||
.map(to_raw_input_types)
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let raw_inputs = Rc::new(raw_inputs);
|
|
||||||
|
|
||||||
let raw_outputs = import
|
|
||||||
.signature
|
|
||||||
.output_types
|
|
||||||
.iter()
|
|
||||||
.map(|ty| {
|
|
||||||
to_raw_output_type(ty)
|
|
||||||
.iter()
|
|
||||||
.map(wtype_to_itype)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let raw_outputs = Rc::new(raw_outputs);
|
|
||||||
|
|
||||||
interfaces.types.push(Type::Function {
|
|
||||||
arguments: raw_inputs.clone(),
|
|
||||||
output_types: raw_outputs.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
interfaces.types.push(Type::Function {
|
|
||||||
arguments: raw_inputs,
|
|
||||||
output_types: raw_outputs,
|
|
||||||
});
|
|
||||||
|
|
||||||
let adapter_idx = (interfaces.types.len() - 2) as u32;
|
|
||||||
let import_idx = (interfaces.types.len() - 3) as u32;
|
|
||||||
let raw_import_idx = (interfaces.types.len() - 1) as u32;
|
|
||||||
|
|
||||||
let link_name = match &import.link_name {
|
|
||||||
Some(link_name) => link_name,
|
Some(link_name) => link_name,
|
||||||
None => &import.signature.name,
|
None => &fn_type.signature.name,
|
||||||
};
|
};
|
||||||
|
|
||||||
interfaces.imports.push(wasmer_it::ast::Import {
|
it_resolver.add_import(namespace, link_name, import_idx);
|
||||||
namespace: &namespace,
|
it_resolver.add_import(namespace, link_name, raw_import_idx);
|
||||||
name: link_name,
|
|
||||||
function_type: import_idx,
|
|
||||||
});
|
|
||||||
|
|
||||||
interfaces.imports.push(wasmer_it::ast::Import {
|
Ok(())
|
||||||
namespace: &namespace,
|
}
|
||||||
name: link_name,
|
|
||||||
function_type: raw_import_idx,
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut instructions = import
|
fn generate_it_instructions<'f>(
|
||||||
|
fn_type: &'f ExternFnType,
|
||||||
|
it_resolver: &mut ITResolver<'f>,
|
||||||
|
) -> Result<()> {
|
||||||
|
use args_it_generator::ArgumentITGenerator;
|
||||||
|
use output_type_it_generator::OutputITGenerator;
|
||||||
|
|
||||||
|
let adapter_idx = (it_resolver.interfaces.types.len() - 2) as u32;
|
||||||
|
let raw_import_idx = (it_resolver.interfaces.types.len() - 1) as u32;
|
||||||
|
|
||||||
|
let mut should_generate_release = false;
|
||||||
|
let mut instructions = fn_type
|
||||||
.signature
|
.signature
|
||||||
.arguments
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.try_fold::<_, _, Result<_>>((0, Vec::new()), |(arg_id, mut instructions), arg| {
|
.try_fold::<_, _, Result<_>>((0, Vec::new()), |(arg_id, mut instructions), arg| {
|
||||||
let (new_instructions, shift) = arg
|
let (new_instructions, shift) = arg
|
||||||
.ty
|
.ty
|
||||||
.generate_instructions_for_input_type(arg_id as _, it_resolver)?;
|
.generate_instructions_for_arg(arg_id as _, it_resolver)?;
|
||||||
|
|
||||||
|
should_generate_release |= arg.ty.is_complex_type();
|
||||||
|
|
||||||
instructions.extend(new_instructions);
|
instructions.extend(new_instructions);
|
||||||
Ok((arg_id + shift, instructions))
|
Ok((arg_id + shift, instructions))
|
||||||
})?
|
})?
|
||||||
.1;
|
.1;
|
||||||
|
|
||||||
|
if should_generate_release {
|
||||||
|
instructions.push(Instruction::CallCore {
|
||||||
|
function_index: RELEASE_OBJECTS.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
let import_function_index = (it_resolver.interfaces.exports.len()
|
let import_function_index = (it_resolver.interfaces.exports.len()
|
||||||
+ it_resolver.interfaces.imports.len() / 2
|
+ it_resolver.interfaces.imports.len() / 2
|
||||||
@ -159,7 +131,7 @@ fn generate_it_for_import<'a>(
|
|||||||
function_index: import_function_index,
|
function_index: import_function_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
let instructions = import
|
let instructions = fn_type
|
||||||
.signature
|
.signature
|
||||||
.output_types
|
.output_types
|
||||||
.iter()
|
.iter()
|
||||||
@ -170,137 +142,37 @@ fn generate_it_for_import<'a>(
|
|||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let adapter = Adapter {
|
it_resolver.add_adapter(adapter_idx, instructions);
|
||||||
function_type: adapter_idx,
|
it_resolver.add_implementation(raw_import_idx, adapter_idx);
|
||||||
instructions,
|
|
||||||
};
|
|
||||||
it_resolver.interfaces.adapters.push(adapter);
|
|
||||||
|
|
||||||
let implementation = wasmer_it::ast::Implementation {
|
|
||||||
core_function_type: raw_import_idx,
|
|
||||||
adapter_function_type: adapter_idx,
|
|
||||||
};
|
|
||||||
it_resolver.interfaces.implementations.push(implementation);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate IT instructions for a foreign mod.
|
pub(crate) fn generate_raw_args<'f>(signature: &FnSignature) -> Rc<Vec<IFunctionArg>> {
|
||||||
trait ForeignModInstructionGenerator {
|
let raw_inputs = signature
|
||||||
fn generate_instructions_for_input_type<'a>(
|
.arguments
|
||||||
&self,
|
.iter()
|
||||||
arg_id: u32,
|
.map(to_raw_input_types)
|
||||||
it_resolver: &mut ITResolver<'a>,
|
.flatten()
|
||||||
) -> Result<(Vec<Instruction>, u32)>;
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
fn generate_instructions_for_output_type<'a>(
|
Rc::new(raw_inputs)
|
||||||
&self,
|
|
||||||
it_resolver: &mut ITResolver<'a>,
|
|
||||||
) -> Result<Vec<Instruction>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
pub(crate) fn generate_raw_output_type<'f>(signature: &FnSignature) -> Rc<Vec<IType>> {
|
||||||
impl ForeignModInstructionGenerator for ParsedType {
|
let raw_outputs = signature
|
||||||
fn generate_instructions_for_input_type<'a>(
|
.output_types
|
||||||
&self,
|
.iter()
|
||||||
index: u32,
|
.map(|ty| {
|
||||||
it_resolver: &mut ITResolver<'a>,
|
to_raw_output_type(ty)
|
||||||
) -> Result<(Vec<Instruction>, u32)> {
|
.iter()
|
||||||
let instructions = match self {
|
.map(wtype_to_itype)
|
||||||
ParsedType::Boolean(_) => (vec![Instruction::ArgumentGet { index }, Instruction::BoolFromI32], 1),
|
.collect::<Vec<_>>()
|
||||||
ParsedType::I8(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S8FromI32], 1),
|
})
|
||||||
ParsedType::I16(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S16FromI32], 1),
|
.flatten()
|
||||||
ParsedType::I32(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S32FromI32], 1),
|
.collect::<Vec<_>>();
|
||||||
ParsedType::I64(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S64FromI64], 1),
|
|
||||||
ParsedType::U8(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U8FromI32], 1),
|
|
||||||
ParsedType::U16(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U16FromI32], 1),
|
|
||||||
ParsedType::U32(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U32FromI32], 1),
|
|
||||||
ParsedType::U64(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U64FromI64], 1),
|
|
||||||
ParsedType::F32(_) => (vec![Instruction::ArgumentGet { index }], 1),
|
|
||||||
ParsedType::F64(_) => (vec![Instruction::ArgumentGet { index }], 1),
|
|
||||||
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => (vec![
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::ArgumentGet { index: index + 1 },
|
|
||||||
Instruction::StringLiftMemory,
|
|
||||||
], 2),
|
|
||||||
ParsedType::Vector(value_type, _) => {
|
|
||||||
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
|
||||||
if let IType::U8 = value_type {
|
|
||||||
(vec![
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::ArgumentGet { index: index + 1 },
|
|
||||||
Instruction::ByteArrayLiftMemory,
|
|
||||||
], 2)
|
|
||||||
} else {
|
|
||||||
(vec![
|
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::ArgumentGet { index: index + 1 },
|
|
||||||
Instruction::ArrayLiftMemory { value_type },
|
|
||||||
], 2)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ParsedType::Record(record_name, _) => {
|
|
||||||
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
|
||||||
|
|
||||||
(vec![
|
Rc::new(raw_outputs)
|
||||||
Instruction::ArgumentGet { index },
|
|
||||||
Instruction::RecordLiftMemory { record_type_id },
|
|
||||||
], 1)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn generate_instructions_for_output_type<'a>(&self, it_resolver: &mut ITResolver<'a>) -> Result<Vec<Instruction>> {
|
|
||||||
let instructions = match self {
|
|
||||||
ParsedType::Boolean(_) => vec![Instruction::I32FromBool],
|
|
||||||
ParsedType::I8(_) => vec![Instruction::I32FromS8],
|
|
||||||
ParsedType::I16(_) => vec![Instruction::I32FromS16],
|
|
||||||
ParsedType::I32(_) => vec![Instruction::I32FromS32],
|
|
||||||
ParsedType::I64(_) => vec![Instruction::I64FromS64],
|
|
||||||
ParsedType::U8(_) => vec![Instruction::I32FromU8],
|
|
||||||
ParsedType::U16(_) => vec![Instruction::I32FromU16],
|
|
||||||
ParsedType::U32(_) => vec![Instruction::I32FromU32],
|
|
||||||
ParsedType::U64(_) => vec![Instruction::I64FromU64],
|
|
||||||
ParsedType::F32(_) => vec![],
|
|
||||||
ParsedType::F64(_) => vec![],
|
|
||||||
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => {
|
|
||||||
let type_tag = it_lilo::utils::ser_type_size(&IType::U8) as i32;
|
|
||||||
|
|
||||||
vec![
|
|
||||||
Instruction::Dup,
|
|
||||||
Instruction::StringSize,
|
|
||||||
Instruction::PushI32 { value: type_tag },
|
|
||||||
Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
|
|
||||||
Instruction::Swap2,
|
|
||||||
Instruction::StringLowerMemory,
|
|
||||||
Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id },
|
|
||||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
ParsedType::Vector(value_type, _) => {
|
|
||||||
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
|
||||||
|
|
||||||
vec![
|
|
||||||
Instruction::ArrayLowerMemory { value_type },
|
|
||||||
Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id },
|
|
||||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
ParsedType::Record(record_name, _) => {
|
|
||||||
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
|
||||||
|
|
||||||
vec![
|
|
||||||
Instruction::RecordLowerMemory { record_type_id },
|
|
||||||
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(instructions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use marine_macro_impl::RustType;
|
use marine_macro_impl::RustType;
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::ITResolver;
|
||||||
|
use super::ptype_to_itype_checked;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
use marine_macro_impl::ParsedType;
|
||||||
|
use wasmer_it::interpreter::Instruction;
|
||||||
|
use wasmer_it::IType;
|
||||||
|
|
||||||
|
/// Generate IT instructions for a foreign mod.
|
||||||
|
pub(super) trait ArgumentITGenerator {
|
||||||
|
fn generate_instructions_for_arg<'a>(
|
||||||
|
&self,
|
||||||
|
arg_id: u32,
|
||||||
|
it_resolver: &mut ITResolver<'a>,
|
||||||
|
) -> Result<(Vec<Instruction>, u32)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
impl ArgumentITGenerator for ParsedType {
|
||||||
|
fn generate_instructions_for_arg<'a>(
|
||||||
|
&self,
|
||||||
|
index: u32,
|
||||||
|
it_resolver: &mut ITResolver<'a>,
|
||||||
|
) -> Result<(Vec<Instruction>, u32)> {
|
||||||
|
let instructions = match self {
|
||||||
|
ParsedType::Boolean(_) => (vec![Instruction::ArgumentGet { index }, Instruction::BoolFromI32], 1),
|
||||||
|
ParsedType::I8(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S8FromI32], 1),
|
||||||
|
ParsedType::I16(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S16FromI32], 1),
|
||||||
|
ParsedType::I32(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S32FromI32], 1),
|
||||||
|
ParsedType::I64(_) => (vec![Instruction::ArgumentGet { index }, Instruction::S64FromI64], 1),
|
||||||
|
ParsedType::U8(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U8FromI32], 1),
|
||||||
|
ParsedType::U16(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U16FromI32], 1),
|
||||||
|
ParsedType::U32(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U32FromI32], 1),
|
||||||
|
ParsedType::U64(_) => (vec![Instruction::ArgumentGet { index }, Instruction::U64FromI64], 1),
|
||||||
|
ParsedType::F32(_) => (vec![Instruction::ArgumentGet { index }], 1),
|
||||||
|
ParsedType::F64(_) => (vec![Instruction::ArgumentGet { index }], 1),
|
||||||
|
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => (vec![
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::ArgumentGet { index: index + 1 },
|
||||||
|
Instruction::StringLiftMemory,
|
||||||
|
], 2),
|
||||||
|
ParsedType::Vector(value_type, _) => {
|
||||||
|
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
||||||
|
if let IType::U8 = value_type {
|
||||||
|
(vec![
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::ArgumentGet { index: index + 1 },
|
||||||
|
Instruction::ByteArrayLiftMemory,
|
||||||
|
], 2)
|
||||||
|
} else {
|
||||||
|
(vec![
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::ArgumentGet { index: index + 1 },
|
||||||
|
Instruction::ArrayLiftMemory { value_type },
|
||||||
|
], 2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ParsedType::Record(record_name, _) => {
|
||||||
|
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
||||||
|
|
||||||
|
(vec![
|
||||||
|
Instruction::ArgumentGet { index },
|
||||||
|
Instruction::RecordLiftMemory { record_type_id },
|
||||||
|
], 1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::ITResolver;
|
||||||
|
use super::ptype_to_itype_checked;
|
||||||
|
use crate::Result;
|
||||||
|
use crate::default_export_api_config::*;
|
||||||
|
|
||||||
|
use marine_macro_impl::ParsedType;
|
||||||
|
use wasmer_it::interpreter::Instruction;
|
||||||
|
use wasmer_it::IType;
|
||||||
|
|
||||||
|
/// Generate IT instructions for a foreign mod.
|
||||||
|
pub(super) trait OutputITGenerator {
|
||||||
|
fn generate_instructions_for_output_type<'a>(
|
||||||
|
&self,
|
||||||
|
it_resolver: &mut ITResolver<'a>,
|
||||||
|
) -> Result<Vec<Instruction>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
impl OutputITGenerator for ParsedType {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn generate_instructions_for_output_type<'a>(&self, it_resolver: &mut ITResolver<'a>) -> Result<Vec<Instruction>> {
|
||||||
|
let instructions = match self {
|
||||||
|
ParsedType::Boolean(_) => vec![Instruction::I32FromBool],
|
||||||
|
ParsedType::I8(_) => vec![Instruction::I32FromS8],
|
||||||
|
ParsedType::I16(_) => vec![Instruction::I32FromS16],
|
||||||
|
ParsedType::I32(_) => vec![Instruction::I32FromS32],
|
||||||
|
ParsedType::I64(_) => vec![Instruction::I64FromS64],
|
||||||
|
ParsedType::U8(_) => vec![Instruction::I32FromU8],
|
||||||
|
ParsedType::U16(_) => vec![Instruction::I32FromU16],
|
||||||
|
ParsedType::U32(_) => vec![Instruction::I32FromU32],
|
||||||
|
ParsedType::U64(_) => vec![Instruction::I64FromU64],
|
||||||
|
ParsedType::F32(_) => vec![],
|
||||||
|
ParsedType::F64(_) => vec![],
|
||||||
|
ParsedType::Utf8Str(_) | ParsedType::Utf8String(_) => {
|
||||||
|
let type_tag = it_lilo::utils::ser_type_size(&IType::U8) as i32;
|
||||||
|
|
||||||
|
vec![
|
||||||
|
Instruction::Dup,
|
||||||
|
Instruction::StringSize,
|
||||||
|
Instruction::PushI32 { value: type_tag },
|
||||||
|
Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
|
||||||
|
Instruction::Swap2,
|
||||||
|
Instruction::StringLowerMemory,
|
||||||
|
Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id },
|
||||||
|
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
ParsedType::Vector(value_type, _) => {
|
||||||
|
let value_type = ptype_to_itype_checked(value_type, it_resolver)?;
|
||||||
|
|
||||||
|
vec![
|
||||||
|
Instruction::ArrayLowerMemory { value_type },
|
||||||
|
Instruction::CallCore { function_index: SET_RESULT_SIZE_FUNC.id },
|
||||||
|
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
ParsedType::Record(record_name, _) => {
|
||||||
|
let record_type_id = it_resolver.get_record_type_id(record_name)? as u32;
|
||||||
|
|
||||||
|
vec![
|
||||||
|
Instruction::RecordLowerMemory { record_type_id },
|
||||||
|
Instruction::CallCore { function_index: SET_RESULT_PTR_FUNC.id },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,6 @@ use marine_macro_impl::RecordType;
|
|||||||
use marine_macro_impl::RecordFields;
|
use marine_macro_impl::RecordFields;
|
||||||
|
|
||||||
use wasmer_it::IRecordFieldType;
|
use wasmer_it::IRecordFieldType;
|
||||||
use wasmer_it::IRecordType;
|
|
||||||
use wasmer_it::NEVec;
|
use wasmer_it::NEVec;
|
||||||
|
|
||||||
impl ITGenerator for RecordType {
|
impl ITGenerator for RecordType {
|
||||||
@ -48,12 +47,7 @@ impl ITGenerator for RecordType {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let new_record_type = IRecordType {
|
it_resolver.add_record_type(self.name.clone(), fields);
|
||||||
name: self.name.clone(),
|
|
||||||
fields,
|
|
||||||
};
|
|
||||||
|
|
||||||
it_resolver.insert_record_type(new_record_type);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
334
crates/it-generator/src/instructions_generator/tests.rs
Normal file
334
crates/it-generator/src/instructions_generator/tests.rs
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::ITGenerator;
|
||||||
|
use crate::default_export_api_config::RELEASE_OBJECTS;
|
||||||
|
use crate::instructions_generator::ITResolver;
|
||||||
|
|
||||||
|
use marine_macro_impl::*;
|
||||||
|
use wasmer_it::interpreter::Instruction;
|
||||||
|
use wasmer_it::IType;
|
||||||
|
|
||||||
|
fn generate_export_fn(args: Vec<ParsedType>, output: Option<ParsedType>) -> FnType {
|
||||||
|
let name = String::from("some_fn_name");
|
||||||
|
|
||||||
|
let arguments = args
|
||||||
|
.into_iter()
|
||||||
|
.map(|ty| FnArgument {
|
||||||
|
name: String::from("arg_name"),
|
||||||
|
ty,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let output_types = match output {
|
||||||
|
Some(output) => vec![output],
|
||||||
|
None => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let signature = FnSignature {
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
output_types,
|
||||||
|
};
|
||||||
|
|
||||||
|
FnType { signature }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_import_mod(args: Vec<ParsedType>, output: Option<ParsedType>) -> ExternModType {
|
||||||
|
let name = String::from("some_fn_name");
|
||||||
|
|
||||||
|
let arguments = args
|
||||||
|
.into_iter()
|
||||||
|
.map(|ty| FnArgument {
|
||||||
|
name: String::from("arg_name"),
|
||||||
|
ty,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let output_types = match output {
|
||||||
|
Some(output) => vec![output],
|
||||||
|
None => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let signature = FnSignature {
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
output_types,
|
||||||
|
};
|
||||||
|
|
||||||
|
let extern_fn_type = ExternFnType {
|
||||||
|
link_name: None,
|
||||||
|
signature,
|
||||||
|
};
|
||||||
|
|
||||||
|
ExternModType {
|
||||||
|
namespace: String::from("some namespace"),
|
||||||
|
imports: vec![extern_fn_type],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_arg_types_in_export() {
|
||||||
|
let args = vec![
|
||||||
|
ParsedType::I8(PassingStyle::ByValue),
|
||||||
|
ParsedType::I16(PassingStyle::ByValue),
|
||||||
|
ParsedType::I32(PassingStyle::ByValue),
|
||||||
|
ParsedType::I64(PassingStyle::ByValue),
|
||||||
|
ParsedType::U8(PassingStyle::ByValue),
|
||||||
|
ParsedType::U16(PassingStyle::ByValue),
|
||||||
|
ParsedType::U32(PassingStyle::ByValue),
|
||||||
|
ParsedType::U64(PassingStyle::ByValue),
|
||||||
|
ParsedType::F32(PassingStyle::ByValue),
|
||||||
|
ParsedType::F64(PassingStyle::ByValue),
|
||||||
|
];
|
||||||
|
|
||||||
|
let outputs = Some(ParsedType::I32(PassingStyle::ByValue));
|
||||||
|
let fn_type = generate_export_fn(args, outputs);
|
||||||
|
|
||||||
|
let mut it_resolver = ITResolver::default();
|
||||||
|
fn_type
|
||||||
|
.generate_it(&mut it_resolver)
|
||||||
|
.expect("IT generation succeeded");
|
||||||
|
|
||||||
|
let interfaces = it_resolver.interfaces;
|
||||||
|
|
||||||
|
let actual_instruction = &interfaces.adapters[0].instructions;
|
||||||
|
|
||||||
|
let expected_instruction = vec![
|
||||||
|
Instruction::ArgumentGet { index: 0 },
|
||||||
|
Instruction::I32FromS8,
|
||||||
|
Instruction::ArgumentGet { index: 1 },
|
||||||
|
Instruction::I32FromS16,
|
||||||
|
Instruction::ArgumentGet { index: 2 },
|
||||||
|
Instruction::I32FromS32,
|
||||||
|
Instruction::ArgumentGet { index: 3 },
|
||||||
|
Instruction::I64FromS64,
|
||||||
|
Instruction::ArgumentGet { index: 4 },
|
||||||
|
Instruction::I32FromU8,
|
||||||
|
Instruction::ArgumentGet { index: 5 },
|
||||||
|
Instruction::I32FromU16,
|
||||||
|
Instruction::ArgumentGet { index: 6 },
|
||||||
|
Instruction::I32FromU32,
|
||||||
|
Instruction::ArgumentGet { index: 7 },
|
||||||
|
Instruction::I64FromU64,
|
||||||
|
Instruction::ArgumentGet { index: 8 },
|
||||||
|
Instruction::ArgumentGet { index: 9 },
|
||||||
|
Instruction::CallCore { function_index: 0 },
|
||||||
|
Instruction::S32FromI32,
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(actual_instruction, &expected_instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn complex_arg_types_in_export() {
|
||||||
|
let args = vec![
|
||||||
|
ParsedType::I8(PassingStyle::ByValue),
|
||||||
|
ParsedType::I16(PassingStyle::ByValue),
|
||||||
|
ParsedType::I32(PassingStyle::ByValue),
|
||||||
|
ParsedType::I64(PassingStyle::ByValue),
|
||||||
|
ParsedType::U8(PassingStyle::ByValue),
|
||||||
|
ParsedType::U16(PassingStyle::ByValue),
|
||||||
|
ParsedType::U32(PassingStyle::ByValue),
|
||||||
|
ParsedType::U64(PassingStyle::ByValue),
|
||||||
|
ParsedType::F32(PassingStyle::ByValue),
|
||||||
|
ParsedType::F64(PassingStyle::ByValue),
|
||||||
|
ParsedType::Utf8String(PassingStyle::ByValue),
|
||||||
|
ParsedType::Vector(
|
||||||
|
Box::new(ParsedType::U8(PassingStyle::ByValue)),
|
||||||
|
PassingStyle::ByValue,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
let outputs = Some(ParsedType::Utf8String(PassingStyle::ByValue));
|
||||||
|
let fn_type = generate_export_fn(args, outputs);
|
||||||
|
|
||||||
|
let mut it_resolver = ITResolver::default();
|
||||||
|
fn_type
|
||||||
|
.generate_it(&mut it_resolver)
|
||||||
|
.expect("IT generation succeeded");
|
||||||
|
|
||||||
|
let interfaces = it_resolver.interfaces;
|
||||||
|
|
||||||
|
let actual_instruction = &interfaces.adapters[0].instructions;
|
||||||
|
|
||||||
|
let expected_instruction = vec![
|
||||||
|
Instruction::ArgumentGet { index: 0 },
|
||||||
|
Instruction::I32FromS8,
|
||||||
|
Instruction::ArgumentGet { index: 1 },
|
||||||
|
Instruction::I32FromS16,
|
||||||
|
Instruction::ArgumentGet { index: 2 },
|
||||||
|
Instruction::I32FromS32,
|
||||||
|
Instruction::ArgumentGet { index: 3 },
|
||||||
|
Instruction::I64FromS64,
|
||||||
|
Instruction::ArgumentGet { index: 4 },
|
||||||
|
Instruction::I32FromU8,
|
||||||
|
Instruction::ArgumentGet { index: 5 },
|
||||||
|
Instruction::I32FromU16,
|
||||||
|
Instruction::ArgumentGet { index: 6 },
|
||||||
|
Instruction::I32FromU32,
|
||||||
|
Instruction::ArgumentGet { index: 7 },
|
||||||
|
Instruction::I64FromU64,
|
||||||
|
Instruction::ArgumentGet { index: 8 },
|
||||||
|
Instruction::ArgumentGet { index: 9 },
|
||||||
|
Instruction::ArgumentGet { index: 10 },
|
||||||
|
Instruction::StringSize,
|
||||||
|
Instruction::PushI32 { value: 1 },
|
||||||
|
Instruction::CallCore { function_index: 0 },
|
||||||
|
Instruction::ArgumentGet { index: 10 },
|
||||||
|
Instruction::StringLowerMemory,
|
||||||
|
Instruction::ArgumentGet { index: 11 },
|
||||||
|
Instruction::ArrayLowerMemory {
|
||||||
|
value_type: IType::U8,
|
||||||
|
},
|
||||||
|
Instruction::CallCore { function_index: 0 },
|
||||||
|
Instruction::CallCore { function_index: 3 },
|
||||||
|
Instruction::CallCore { function_index: 2 },
|
||||||
|
Instruction::StringLiftMemory,
|
||||||
|
Instruction::CallCore {
|
||||||
|
function_index: RELEASE_OBJECTS.id,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(actual_instruction, &expected_instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_arg_types_in_import() {
|
||||||
|
let args = vec![
|
||||||
|
ParsedType::I8(PassingStyle::ByValue),
|
||||||
|
ParsedType::I16(PassingStyle::ByValue),
|
||||||
|
ParsedType::I32(PassingStyle::ByValue),
|
||||||
|
ParsedType::I64(PassingStyle::ByValue),
|
||||||
|
ParsedType::U8(PassingStyle::ByValue),
|
||||||
|
ParsedType::U16(PassingStyle::ByValue),
|
||||||
|
ParsedType::U32(PassingStyle::ByValue),
|
||||||
|
ParsedType::U64(PassingStyle::ByValue),
|
||||||
|
ParsedType::F32(PassingStyle::ByValue),
|
||||||
|
ParsedType::F64(PassingStyle::ByValue),
|
||||||
|
];
|
||||||
|
|
||||||
|
let outputs = Some(ParsedType::I32(PassingStyle::ByValue));
|
||||||
|
let import_fn_type = generate_import_mod(args, outputs);
|
||||||
|
|
||||||
|
let mut it_resolver = ITResolver::default();
|
||||||
|
import_fn_type
|
||||||
|
.generate_it(&mut it_resolver)
|
||||||
|
.expect("IT generation succeeded");
|
||||||
|
|
||||||
|
let interfaces = it_resolver.interfaces;
|
||||||
|
|
||||||
|
let actual_instruction = &interfaces.adapters[0].instructions;
|
||||||
|
|
||||||
|
let expected_instruction = vec![
|
||||||
|
Instruction::ArgumentGet { index: 0 },
|
||||||
|
Instruction::S8FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 1 },
|
||||||
|
Instruction::S16FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 2 },
|
||||||
|
Instruction::S32FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 3 },
|
||||||
|
Instruction::S64FromI64,
|
||||||
|
Instruction::ArgumentGet { index: 4 },
|
||||||
|
Instruction::U8FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 5 },
|
||||||
|
Instruction::U16FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 6 },
|
||||||
|
Instruction::U32FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 7 },
|
||||||
|
Instruction::U64FromI64,
|
||||||
|
Instruction::ArgumentGet { index: 8 },
|
||||||
|
Instruction::ArgumentGet { index: 9 },
|
||||||
|
Instruction::CallCore { function_index: 0 },
|
||||||
|
Instruction::I32FromS32,
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(actual_instruction, &expected_instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn complex_arg_types_in_import() {
|
||||||
|
let args = vec![
|
||||||
|
ParsedType::I8(PassingStyle::ByValue),
|
||||||
|
ParsedType::I16(PassingStyle::ByValue),
|
||||||
|
ParsedType::I32(PassingStyle::ByValue),
|
||||||
|
ParsedType::I64(PassingStyle::ByValue),
|
||||||
|
ParsedType::U8(PassingStyle::ByValue),
|
||||||
|
ParsedType::U16(PassingStyle::ByValue),
|
||||||
|
ParsedType::U32(PassingStyle::ByValue),
|
||||||
|
ParsedType::U64(PassingStyle::ByValue),
|
||||||
|
ParsedType::F32(PassingStyle::ByValue),
|
||||||
|
ParsedType::F64(PassingStyle::ByValue),
|
||||||
|
ParsedType::Utf8String(PassingStyle::ByValue),
|
||||||
|
ParsedType::Vector(
|
||||||
|
Box::new(ParsedType::U8(PassingStyle::ByValue)),
|
||||||
|
PassingStyle::ByValue,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
let outputs = Some(ParsedType::Utf8String(PassingStyle::ByValue));
|
||||||
|
let fn_type = generate_import_mod(args, outputs);
|
||||||
|
|
||||||
|
let mut it_resolver = ITResolver::default();
|
||||||
|
fn_type
|
||||||
|
.generate_it(&mut it_resolver)
|
||||||
|
.expect("IT generation succeeded");
|
||||||
|
|
||||||
|
let interfaces = it_resolver.interfaces;
|
||||||
|
|
||||||
|
let actual_instruction = &interfaces.adapters[0].instructions;
|
||||||
|
|
||||||
|
let expected_instruction = vec![
|
||||||
|
Instruction::ArgumentGet { index: 0 },
|
||||||
|
Instruction::S8FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 1 },
|
||||||
|
Instruction::S16FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 2 },
|
||||||
|
Instruction::S32FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 3 },
|
||||||
|
Instruction::S64FromI64,
|
||||||
|
Instruction::ArgumentGet { index: 4 },
|
||||||
|
Instruction::U8FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 5 },
|
||||||
|
Instruction::U16FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 6 },
|
||||||
|
Instruction::U32FromI32,
|
||||||
|
Instruction::ArgumentGet { index: 7 },
|
||||||
|
Instruction::U64FromI64,
|
||||||
|
Instruction::ArgumentGet { index: 8 },
|
||||||
|
Instruction::ArgumentGet { index: 9 },
|
||||||
|
Instruction::ArgumentGet { index: 10 },
|
||||||
|
Instruction::ArgumentGet { index: 11 },
|
||||||
|
Instruction::StringLiftMemory,
|
||||||
|
Instruction::ArgumentGet { index: 12 },
|
||||||
|
Instruction::ArgumentGet { index: 13 },
|
||||||
|
Instruction::ByteArrayLiftMemory,
|
||||||
|
Instruction::CallCore {
|
||||||
|
function_index: RELEASE_OBJECTS.id,
|
||||||
|
},
|
||||||
|
Instruction::CallCore { function_index: 0 },
|
||||||
|
Instruction::Dup,
|
||||||
|
Instruction::StringSize,
|
||||||
|
Instruction::PushI32 { value: 1 },
|
||||||
|
Instruction::CallCore { function_index: 0 },
|
||||||
|
Instruction::Swap2,
|
||||||
|
Instruction::StringLowerMemory,
|
||||||
|
Instruction::CallCore { function_index: 4 },
|
||||||
|
Instruction::CallCore { function_index: 5 },
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(actual_instruction, &expected_instruction);
|
||||||
|
}
|
@ -18,8 +18,12 @@ use super::IType;
|
|||||||
use crate::instructions_generator::ITResolver;
|
use crate::instructions_generator::ITResolver;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
|
use marine_macro_impl::FnSignature;
|
||||||
use marine_macro_impl::ParsedType;
|
use marine_macro_impl::ParsedType;
|
||||||
use marine_macro_impl::RustType;
|
use marine_macro_impl::RustType;
|
||||||
|
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
// return error if there is no record with such name
|
// return error if there is no record with such name
|
||||||
pub(crate) fn ptype_to_itype_checked(
|
pub(crate) fn ptype_to_itype_checked(
|
||||||
@ -102,3 +106,37 @@ pub(crate) fn wtype_to_itype(pty: &RustType) -> IType {
|
|||||||
RustType::F64 => IType::F64,
|
RustType::F64 => IType::F64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn generate_it_args<'f>(
|
||||||
|
signature: &FnSignature,
|
||||||
|
it_resolver: &mut ITResolver<'f>,
|
||||||
|
) -> Result<Rc<Vec<IFunctionArg>>> {
|
||||||
|
let arguments = signature
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.map(|arg| -> Result<IFunctionArg> {
|
||||||
|
Ok(IFunctionArg {
|
||||||
|
name: arg.name.clone(),
|
||||||
|
ty: ptype_to_itype_checked(&arg.ty, it_resolver)?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
let arguments = Rc::new(arguments);
|
||||||
|
Ok(arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn generate_it_output_type<'f>(
|
||||||
|
signature: &FnSignature,
|
||||||
|
it_resolver: &mut ITResolver<'f>,
|
||||||
|
) -> Result<Rc<Vec<IType>>> {
|
||||||
|
let output_types = signature
|
||||||
|
.output_types
|
||||||
|
.iter()
|
||||||
|
.map(|ty| ptype_to_itype_checked(ty, it_resolver))
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
let output_types = Rc::new(output_types);
|
||||||
|
|
||||||
|
Ok(output_types)
|
||||||
|
}
|
||||||
|
@ -11,7 +11,7 @@ name = "marine_module_info_parser"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence-sdk-main = "0.6.3"
|
fluence-sdk-main = "0.6.9"
|
||||||
|
|
||||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0" }
|
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0" }
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ name = "call_parameters"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fluence-test = "0.1.7"
|
fluence-test = "0.1.7"
|
||||||
|
@ -12,7 +12,7 @@ name = "greeting"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fluence-test = "0.1.7"
|
fluence-test = "0.1.7"
|
||||||
|
@ -10,5 +10,5 @@ name = "records_effector"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
test-record = { path = "../test-record" }
|
test-record = { path = "../test-record" }
|
||||||
|
@ -10,5 +10,5 @@ name = "records_pure"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
test-record = { path = "../test-record" }
|
test-record = { path = "../test-record" }
|
||||||
|
@ -10,4 +10,4 @@ name = "test_record"
|
|||||||
path = "src/test_record.rs"
|
path = "src/test_record.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
|
@ -10,5 +10,5 @@ name = "sqlite_test"
|
|||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
marine-sqlite-connector = "0.4.0"
|
marine-sqlite-connector = "0.4.0"
|
||||||
|
@ -9,7 +9,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
marine-runtime = { path = "../runtime", version = "0.5.0" }
|
marine-runtime = { path = "../runtime", version = "0.5.0" }
|
||||||
marine-utils = { path = "../crates/utils", version = "0.2.0" }
|
marine-utils = { path = "../crates/utils", version = "0.2.0" }
|
||||||
fluence-sdk-main = { version = "0.6.3", features = ["logger"] }
|
fluence-sdk-main = { version = "0.6.9", features = ["logger"] }
|
||||||
fluence = { version = "0.6.3", features = ["logger"] }
|
fluence = { version = "0.6.3", features = ["logger"] }
|
||||||
|
|
||||||
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
|
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
|
||||||
|
@ -14,5 +14,5 @@ name = "arrays_passing_effector"
|
|||||||
path = "src/effector.rs"
|
path = "src/effector.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
safe-transmute = "0.11.0"
|
safe-transmute = "0.11.0"
|
||||||
|
@ -14,5 +14,5 @@ name = "records_passing_pure"
|
|||||||
path = "src/pure.rs"
|
path = "src/pure.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence = "0.6.4"
|
fluence = "0.6.9"
|
||||||
safe-transmute = "0.11.0"
|
safe-transmute = "0.11.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "marine"
|
name = "marine"
|
||||||
description = "Fluence Marine command line tool"
|
description = "Fluence Marine command line tool"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
authors = ["Fluence Labs"]
|
authors = ["Fluence Labs"]
|
||||||
repository = "https://github.com/fluencelabs/marine/tools/cli"
|
repository = "https://github.com/fluencelabs/marine/tools/cli"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
@ -13,7 +13,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fluence-app-service = { path = "../../fluence-app-service", version = "0.7.1", features = ["raw-module-api"] }
|
fluence-app-service = { path = "../../fluence-app-service", version = "0.7.1", features = ["raw-module-api"] }
|
||||||
fluence-sdk-main = { version = "0.6.3", features = ["logger"] }
|
fluence-sdk-main = { version = "0.6.9", features = ["logger"] }
|
||||||
|
|
||||||
anyhow = "1.0.31"
|
anyhow = "1.0.31"
|
||||||
clap = "2.33.1"
|
clap = "2.33.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user